Drag-Drop Image Uploader

Enables image uploading by simply dragging and dropping images onto a fixed div in the bottom right corner of the page. Easily upload and use images on any website with this convenient script.

当前为 2023-05-21 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Drag-Drop Image Uploader
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.4
  5. // @description Enables image uploading by simply dragging and dropping images onto a fixed div in the bottom right corner of the page. Easily upload and use images on any website with this convenient script.
  6. // @match https://*/*
  7. // @grant none
  8. // @license MIT License
  9. // @author CY Fung
  10. // @run-at document-start
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15.  
  16. if (location.hostname === 'lihkg.com') {
  17.  
  18. if (location.pathname !== '/robots.txt') return;
  19. if (window.name !== 'pNwjxjQi') return;
  20. if (window === top) return;
  21.  
  22. function T(e) {
  23. return new Promise(function (resolve, reject) {
  24. window.history.replaceState(null, '', 'https://lihkg.com');
  25. var xhr = new XMLHttpRequest();
  26. var formData = new FormData();
  27. formData.append('image', e);
  28. xhr.open('POST', 'https://api.na.cx/upload');
  29.  
  30. // Set the Referer header to an empty string
  31. xhr.onreadystatechange = function () {
  32. if (xhr.readyState === 4) {
  33. if (xhr.status === 200) {
  34. var response = JSON.parse(xhr.responseText);
  35. var status = response.status;
  36. var url = response.url;
  37. var error = response.error;
  38.  
  39. if (status === 200) {
  40. resolve(url);
  41. } else {
  42. reject(new Error(error));
  43. }
  44. } else {
  45. reject(new Error('Status is not 200'));
  46. }
  47. }
  48. };
  49.  
  50. xhr.send(formData);
  51. });
  52. }
  53.  
  54.  
  55. let iframe = document;
  56.  
  57. // Function to handle the dragenter event
  58. function handleDragEnter(e) {
  59. top.postMessage('pNwjxjQi-top-dragenter', '*');
  60. // Add a class to visually indicate the drag over the iframe
  61. //iframe.classList.add("drag-over");
  62. }
  63.  
  64. // Function to handle the dragover event
  65. function handleDragOver(e) {
  66. // top.postMessage('pNwjxjQi-top-dragover','*');
  67. e.preventDefault();
  68. e.dataTransfer.dropEffect = 'copy';
  69. }
  70.  
  71. // Function to handle the dragleave event
  72. function handleDragLeave(e) {
  73. top.postMessage('pNwjxjQi-top-dragleave', '*');
  74. // Remove the class when the drag leaves the iframe
  75. //iframe.classList.remove("drag-over");
  76. }
  77.  
  78. async function goUpload(e) {
  79.  
  80. var files = e.dataTransfer.files;
  81. let images = [...files].filter(file => file.type == "image/png" || file.type == "image/jpg" || file.type == "image/jpeg" || file.type == "image/gif")
  82. console.log(images);
  83.  
  84. for (const image of images) {
  85. await T(image)
  86. .then(function (url) {
  87. // focusElement.focus();
  88. // document.execCommand("insertText", false, url)
  89. top.postMessage({ p: 'pNwjxjQi-top-finish-upload', url: url }, '*')
  90. console.log('Uploaded image URL:', url);
  91. })
  92. .catch(function (error) {
  93. console.error('Upload failed:', error);
  94. });
  95. }
  96.  
  97. }
  98.  
  99. // Function to handle the drop event
  100. function handleDrop(e) {
  101. e.preventDefault();
  102. top.postMessage('pNwjxjQi-top-drop', '*');
  103.  
  104. // Remove the class when the drop occurs
  105. //iframe.classList.remove("drag-over");
  106.  
  107. // Access the dropped files or data
  108.  
  109. goUpload(e);
  110.  
  111. // Process the dropped files or data as needed
  112. // ...
  113. }
  114. // Add event listeners for drag and drop events
  115. iframe.addEventListener("dragenter", handleDragEnter, false);
  116. iframe.addEventListener("dragover", handleDragOver, false);
  117. iframe.addEventListener("dragleave", handleDragLeave, false);
  118. iframe.addEventListener("drop", handleDrop, false);
  119.  
  120.  
  121. top.postMessage('pNwjxjQi-top-uploader-ready', '*');
  122.  
  123.  
  124. } else {
  125.  
  126. function onReady() {
  127.  
  128. // Create the fixed div element
  129. var fixedDiv = document.createElement('div');
  130. fixedDiv.style.position = 'fixed';
  131. fixedDiv.style.zIndex = '8888';
  132. fixedDiv.style.bottom = '10px';
  133. fixedDiv.style.right = '10px';
  134. fixedDiv.style.width = '200px';
  135. fixedDiv.style.height = '200px';
  136. fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
  137. fixedDiv.style.border = '2px solid white';
  138. fixedDiv.style.borderRadius = '5px';
  139. fixedDiv.style.padding = '0px';
  140. fixedDiv.style.color = 'white';
  141. fixedDiv.style.fontSize = '14px';
  142. fixedDiv.style.textAlign = 'center';
  143. // fixedDiv.style.cursor = 'move';
  144. // fixedDiv.draggable = true;
  145. fixedDiv.style.opacity = '0'; // Set initial opacity to 0 (hidden)
  146. fixedDiv.style.display = 'none';
  147. fixedDiv.id = 'ewIMf5Dw';
  148. fixedDiv.style.background = 'url(https://static.thenounproject.com/png/3905046-200.png)';
  149. fixedDiv.style.backgroundPosition = 'center';
  150. fixedDiv.style.backgroundSize = 'cover';
  151. fixedDiv.style.backgroundRepeat = 'no-repeat';
  152.  
  153. fixedDiv.style.pointerEvents = 'none';
  154.  
  155. let focusElement = null;
  156.  
  157. let moused = false;
  158.  
  159. let lastDragIn = 0;
  160. let cid = 0;
  161. function setupIframe(iframe) {
  162. iframe.name = 'pNwjxjQi';
  163.  
  164. iframe.style.position = 'relative';
  165. iframe.style.width = '100%';
  166. iframe.style.height = '100%';
  167. iframe.style.opacity = '0';
  168. iframe.style.pointerEvents = 'all';
  169. iframe.style.transform = 'translateY(-300vh)';
  170. fixedDiv.style.transform = 'translateY(-300vh)';
  171.  
  172. }
  173.  
  174. // Create the Intersection Observer
  175. var observer = new IntersectionObserver(function (entries) {
  176. entries.forEach(function (entry) {
  177. if (entry.isIntersecting) {
  178. // When fixedDiv appears, check if it has an iframe inside
  179. var iframe = fixedDiv.querySelector('iframe');
  180. if (!iframe) {
  181. // If no iframe inside, create and append one
  182. iframe = document.createElement('iframe');
  183. setupIframe(iframe);
  184. iframe.src = 'https://lihkg.com/robots.txt';
  185. fixedDiv.appendChild(iframe);
  186. }
  187. }
  188. });
  189. });
  190.  
  191. // Observe the fixedDiv element
  192. observer.observe(fixedDiv);
  193.  
  194.  
  195.  
  196. document.addEventListener('dragleave', function (event) {
  197. if (moused) return;
  198.  
  199. if (cid > 0) cid = clearTimeout(cid);
  200. if (event.relatedTarget) return;
  201. console.log(221);
  202.  
  203. let endTime = Date.now();
  204. cid = setTimeout(() => {
  205. cid = 0;
  206. requestAnimationFrame(() => {
  207. if (lastDragIn > endTime) return;
  208.  
  209. if (fixedDiv.style.display !== 'none' && !moused) {
  210.  
  211. // focusElement = null;
  212. fixedDiv.style.display = 'none';
  213. fixedDiv.style.opacity = '0';
  214. }
  215. });
  216. }, 80)
  217.  
  218. event.preventDefault();
  219.  
  220. });
  221.  
  222. document.addEventListener('dragenter', function (event) {
  223. if (moused) return;
  224. if (cid > 0) cid = clearTimeout(cid);
  225. if (event.relatedTarget) return;
  226. console.log(222);
  227.  
  228.  
  229. lastDragIn = Date.now();
  230.  
  231. let activeNode = document.activeElement || 0;
  232. let activeNodeName = activeNode.nodeName;
  233. if (activeNodeName === 'TEXTAREA' || (activeNodeName === 'INPUT' && (!activeNode.type || activeNode.type == 'text'))) {
  234. if (fixedDiv.style.display === 'none') {
  235. fixedDiv.style.display = 'block';
  236. fixedDiv.style.opacity = '0.4';
  237. focusElement = activeNode;
  238. console.log(focusElement)
  239. }
  240. }
  241.  
  242. requestAnimationFrame(() => {
  243.  
  244. lastDragIn = Date.now();
  245. });
  246. }, true);
  247.  
  248. document.addEventListener('drop', function (event) {
  249. moused = false;
  250. if (moused) return;
  251. if (cid > 0) cid = clearTimeout(cid);
  252. console.log(223);
  253.  
  254. let endTime = Date.now();
  255. cid = setTimeout(() => {
  256. cid = 0;
  257. if (lastDragIn > endTime) return;
  258. if (fixedDiv.style.display !== 'none' && !moused) {
  259. // focusElement = null;
  260.  
  261. fixedDiv.style.display = 'none';
  262. fixedDiv.style.opacity = '0';
  263. }
  264. }, 80)
  265.  
  266.  
  267. }, true);
  268.  
  269. // Append the div to the document body
  270. document.body.appendChild(fixedDiv);
  271.  
  272.  
  273. window.addEventListener('message', event => {
  274.  
  275. let data = (((event || 0).data || 0));
  276.  
  277.  
  278. if (data === 'pNwjxjQi-top-uploader-ready') {
  279.  
  280. let fixedDiv = document.querySelector('#ewIMf5Dw');
  281. let iframe = fixedDiv.querySelector('iframe');
  282.  
  283. iframe.style.transform = '';
  284. fixedDiv.style.transform = '';
  285.  
  286. }
  287.  
  288. if (data === 'pNwjxjQi-top-dragenter') {
  289. moused = true;
  290. fixedDiv.style.opacity = '1';
  291. }
  292. if (data === 'pNwjxjQi-top-dragleave') {
  293. moused = false;
  294. fixedDiv.style.opacity = '0.4';
  295. }
  296.  
  297. if (data === 'pNwjxjQi-top-dragenter') {
  298.  
  299. if (cid > 0) cid = clearTimeout(cid);
  300. }
  301.  
  302. if (data === 'pNwjxjQi-top-dragleave') {
  303.  
  304. let endTime = Date.now();
  305. if (cid > 0) cid = clearTimeout(cid);
  306. cid = setTimeout(() => {
  307. cid = 0;
  308. requestAnimationFrame(() => {
  309. if (lastDragIn > endTime) return;
  310.  
  311. if (fixedDiv.style.display !== 'none' && !moused) {
  312.  
  313. // focusElement = null;
  314. fixedDiv.style.display = 'none';
  315. fixedDiv.style.opacity = '0';
  316. }
  317. });
  318. }, 80)
  319.  
  320. }
  321.  
  322. if (data.p === 'pNwjxjQi-top-finish-upload') {
  323. let url = event.data.url;
  324. focusElement.focus();
  325. document.execCommand("insertText", false, url)
  326. }
  327.  
  328. if (data === 'pNwjxjQi-top-drop') {
  329. moused = false;
  330.  
  331. let endTime = Date.now();
  332. cid = setTimeout(() => {
  333. cid = 0;
  334. if (lastDragIn > endTime) return;
  335. if (fixedDiv.style.display !== 'none' && !moused) {
  336. // focusElement = null;
  337.  
  338. fixedDiv.style.display = 'none';
  339. fixedDiv.style.opacity = '0';
  340. }
  341. }, 80)
  342. }
  343.  
  344. })
  345.  
  346. }
  347. if (document.readyState !== 'loading') {
  348. onReady();
  349. } else {
  350. document.addEventListener('DOMContentLoaded', onReady, false);
  351. }
  352.  
  353.  
  354.  
  355. }
  356. })();