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