pasteUpload

add paste upload function to input

目前为 2023-05-09 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name pasteUpload
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description add paste upload function to input
  6. // @author gahing
  7. // @license MIT
  8. // @match https://*/*
  9. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15.  
  16. /**
  17. * 添加全局样式,鼠标 hover 高亮 input 容器
  18. */
  19. const highlightCls = "__input--highlight";
  20. const addGlobalStyle = () => {
  21. const styleDom = document.createElement("style");
  22. styleDom.innerHTML = `.${highlightCls} { outline: 1.5px dashed rgba(0, 0, 0, 0.8) !important; \n background: rgb(154, 185, 227) !important; }`;
  23. document.head.appendChild(styleDom);
  24. };
  25.  
  26. // 记录当前的 input[type=file] 元素
  27. let currentInputFileDOM = null;
  28. /**
  29. * 处理鼠标移入事件,记录 input[type=file] 元素并为容器增加高亮样式
  30. * @param e
  31. */
  32. const handleMouseEnter = (el) => {
  33. if (!el.classList) {
  34. return;
  35. }
  36. // 当前元素为 input[type=file] 时处理
  37. if (el.nodeName === "INPUT" && el.type === "file") {
  38. currentInputFileDOM = el;
  39. el.classList.add(highlightCls);
  40. } else {
  41. const inputFiles = el.querySelectorAll("input[type=file]");
  42. // 当前 DOM 节点有且仅有一个 input[type=file] 子元素时处理
  43. if (inputFiles.length === 1) {
  44. currentInputFileDOM = inputFiles[0];
  45. el.classList.add(highlightCls);
  46. }
  47. }
  48. };
  49.  
  50. /**
  51. * 处理鼠标移出事件,移出高亮样式
  52. * @param e
  53. */
  54. const handleMouseLeave = (el) => {
  55. if (!el.classList) {
  56. return;
  57. }
  58. if (el.classList.contains(highlightCls)) {
  59. currentInputFileDOM = null;
  60. el.classList.remove(highlightCls);
  61. }
  62. };
  63.  
  64. /**
  65. * 处理粘贴事件
  66. * @param e
  67. */
  68. const handlePaste = (e, warn = console.log) => {
  69. const clipboardFiles = e.clipboardData.files;
  70. if (!clipboardFiles) {
  71. warn("当前浏览器不支持 clipboardData");
  72. return;
  73. }
  74. const clipboardFile = Array.from(clipboardFiles).find((item) =>
  75. item.type.includes("image")
  76. );
  77. if (!clipboardFile) {
  78. warn("当前剪切板内容非图片文件");
  79. return;
  80. }
  81.  
  82. if (!currentInputFileDOM) {
  83. warn("未找到 input[type=file] 元素");
  84. return;
  85. }
  86. // 修改文件输入框取值
  87. let newFilelist = new DataTransfer();
  88. // 如果 input 多选,需要将旧值先进行复制
  89. if (currentInputFileDOM.multiple) {
  90. [...currentInputFileDOM.files].forEach((item) =>
  91. newFilelist.items.add(item)
  92. );
  93. }
  94. newFilelist.items.add(clipboardFile);
  95. currentInputFileDOM.files = newFilelist.files;
  96. console.log("修改 fileList 成功");
  97. // 手动触发 change 事件
  98. currentInputFileDOM.dispatchEvent(
  99. new Event("change", {
  100. bubbles: true
  101. })
  102. );
  103. };
  104.  
  105. // 下面代码用于给外部脚本使用
  106. const _handleMouseEnter = (e) => {
  107. return handleMouseEnter(e.target);
  108. };
  109. const _handleMouseLeave = (e) => {
  110. return handleMouseLeave(e.target);
  111. };
  112. /**
  113. * 监听事件
  114. */
  115. const listenEvent = () => {
  116. // 由于绑定的是全局,这里使用 mouseover / mouseout 事件,子元素间移动才会触发事件
  117. document.addEventListener("mouseover", _handleMouseEnter);
  118. document.addEventListener("mouseout", _handleMouseLeave);
  119. document.addEventListener("paste", handlePaste);
  120. };
  121.  
  122. /**
  123. * 重置状态
  124. */
  125. const resetEvent = () => {
  126. document.removeEventListener("mouseover", _handleMouseEnter);
  127. document.removeEventListener("mouseout", _handleMouseLeave);
  128. document.removeEventListener("paste", handlePaste);
  129. };
  130. /**
  131. * 创建开关按钮
  132. * @returns
  133. */
  134. const createSwitchButton = () => {
  135. const button = document.createElement('button')
  136. button.innerText = '开启粘贴上传'
  137. button.style = 'position: fixed; bottom: 20px; right: 20px;'
  138. document.body.appendChild(button)
  139. let enablePaste = false
  140. button.addEventListener('click', () => {
  141. enablePaste = !enablePaste
  142. if (enablePaste) {
  143. listenEvent()
  144. button.innerText = '关闭粘贴上传'
  145. } else {
  146. resetEvent()
  147. button.innerText = '开启粘贴上传'
  148. }
  149. })
  150. }
  151.  
  152. addGlobalStyle();
  153. createSwitchButton()
  154.  
  155. })();