paste to form file field

ctrl-v to paste clipboard file into file form field

目前为 2021-08-24 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name paste to form file field
  3. // @namespace http://gholk.github.io/
  4. // @description ctrl-v to paste clipboard file into file form field
  5. // @match https://www.google.com/imghp
  6. // @version 4
  7. // @grant GM.xmlHttpRequest
  8. // ==/UserScript==
  9.  
  10. document.body.addEventListener('paste', (paste) => {
  11. if (paste.clipboardData.files.length == 0) return
  12. putFileIntoForm(paste.clipboardData.files)
  13. })
  14. document.body.addEventListener('dragover', (over) => over.preventDefault())
  15. document.body.addEventListener('drop', async (drop) => {
  16. drop.preventDefault()
  17. const data = drop.dataTransfer
  18. console.debug('type', ...data.types)
  19. let fileList
  20. if (typeof GM != 'undefined' &&
  21. data.files.length == 0 && ~data.types.indexOf('text/plain')) {
  22. const urlList = data.getData('text/plain')
  23. .split('\n').filter(u => u.charAt(0) != '#')
  24. console.debug(urlList)
  25. try {
  26. fileList = await Promise.all(urlList.map(fetchFile))
  27. console.debug(fileList)
  28. fileList = createFileList(...fileList)
  29. }
  30. catch (e) {
  31. console.error(e)
  32. return
  33. }
  34. }
  35. else fileList = drop.dataTransfer.files
  36. putFileIntoForm(fileList)
  37. })
  38.  
  39. function createFileList(...fileList) {
  40. // attribute to https://stackoverflow.com/a/56447852/8362703
  41. const data = new DataTransfer()
  42. for (const file of fileList) data.items.add(file)
  43. return data.files
  44. }
  45.  
  46. async function fetchFile(url) {
  47. function xhrToFileType(xhr) {
  48. for (const row of xhr.responseHeaders.split(/\n/)) {
  49. // line-end with \r\n
  50. const scan = row.match(/^content-type: (.*)\/(.*)/i)
  51. if (scan) return scan[2]
  52. }
  53. }
  54. return await new Promise((resolve, reject) => {
  55. GM.xmlHttpRequest({
  56. method: 'GET', url,
  57. responseType: 'blob',
  58. onload(xhr) {
  59. const blob = xhr.response
  60. const type = xhrToFileType(xhr)
  61. let file
  62. if (type) {
  63. file = new File(
  64. [blob], `drop-image.${type}`,
  65. {type: `image/${type}`}
  66. )
  67. }
  68. else file = new File([blob], `drop-image`)
  69. resolve(file)
  70. },
  71. onerror(xhr) {
  72. reject(xhr.statusText)
  73. }
  74. })
  75. })
  76. }
  77.  
  78. function putFileIntoForm(fileList) {
  79. const input = document.querySelector('input[type = "file"]')
  80. if (!input) return
  81. console.debug('fileList:', ...fileList)
  82. // attribute to https://stackoverflow.com/a/50427897/8362703
  83. input.files = fileList
  84. const change = new Event('change', {bubbles: true, cancelable: false})
  85. input.dispatchEvent(change)
  86. }