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-07-02 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Drag-Drop Image Uploader
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.7
  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 rgb(244, 244, 244)';
  152. fixedDiv.style.outline = '2px solid rgb(20, 20, 20)';
  153. fixedDiv.style.borderRadius = '5px';
  154. fixedDiv.style.padding = '0px';
  155. fixedDiv.style.color = 'white';
  156. fixedDiv.style.fontSize = '14px';
  157. fixedDiv.style.textAlign = 'center';
  158. // fixedDiv.style.cursor = 'move';
  159. // fixedDiv.draggable = true;
  160. fixedDiv.style.opacity = '0'; // Set initial opacity to 0 (hidden)
  161. fixedDiv.style.display = 'none';
  162. fixedDiv.id = 'ewIMf5Dw';
  163.  
  164. fixedDiv.style.background = 'url(https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/icons/drag-drop-image-uploader.svg)';
  165. fixedDiv.style.background = 'url(https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/icons/drag-drop-image-uploader.svg), rgba(135,206,250, 0.2)';
  166.  
  167. fixedDiv.style.backgroundPosition = 'center';
  168. fixedDiv.style.backgroundSize = 'cover';
  169. fixedDiv.style.backgroundRepeat = 'no-repeat';
  170.  
  171. fixedDiv.style.pointerEvents = 'none';
  172.  
  173. // Append the div to the document body
  174. document.body.appendChild(fixedDiv);
  175.  
  176. // Create the Intersection Observer
  177. let observer = new IntersectionObserver(function (entries) {
  178. entries.forEach(function (entry) {
  179. if (entry.isIntersecting) {
  180. // When fixedDiv appears, check if it has an iframe inside
  181. let iframe = fixedDiv.querySelector('iframe');
  182. if (!iframe) {
  183. // If no iframe inside, create and append one
  184. iframe = document.createElement('iframe');
  185. setupIframe(iframe);
  186. iframe.src = 'https://lihkg.com/robots.txt';
  187. fixedDiv.appendChild(iframe);
  188. }
  189. }
  190. });
  191. });
  192.  
  193. // Observe the fixedDiv element
  194. observer.observe(fixedDiv);
  195.  
  196. return fixedDiv;
  197. }
  198. function setupIframe(iframe) {
  199. if (!fixedDiv) return;
  200. iframe.name = 'pNwjxjQi';
  201.  
  202. iframe.style.position = 'relative';
  203. iframe.style.width = '100%';
  204. iframe.style.height = '100%';
  205. iframe.style.opacity = '0';
  206. iframe.style.pointerEvents = 'all';
  207. iframe.style.transform = 'translateY(-300vh)';
  208. fixedDiv.style.transform = 'translateY(-300vh)';
  209.  
  210. }
  211.  
  212.  
  213.  
  214.  
  215. document.addEventListener('dragleave', function (event) {
  216. if (!fixedDiv) return;
  217. if (moused) return;
  218.  
  219. if (cid > 0) cid = clearTimeout(cid);
  220. if (event.relatedTarget) return;
  221. console.log(221);
  222.  
  223. let endTime = Date.now();
  224. cid = setTimeout(() => {
  225. cid = 0;
  226. requestAnimationFrame(() => {
  227. if (lastDragIn > endTime) return;
  228.  
  229. if (fixedDiv.style.display !== 'none' && !moused) {
  230.  
  231. // focusElement = null;
  232. fixedDiv.style.display = 'none';
  233. fixedDiv.style.opacity = '0';
  234. }
  235. });
  236. }, 80)
  237.  
  238. event.preventDefault();
  239.  
  240. });
  241.  
  242. document.addEventListener('dragenter', function (event) {
  243. if (!fixedDiv) fixedDiv = createFixedDiv();
  244. if (moused) return;
  245. if (cid > 0) cid = clearTimeout(cid);
  246. if (event.relatedTarget) return;
  247. console.log(222);
  248.  
  249.  
  250. lastDragIn = Date.now();
  251.  
  252. let activeNode = document.activeElement || 0;
  253. let activeNodeName = activeNode.nodeName;
  254. if (activeNodeName === 'TEXTAREA' || (activeNodeName === 'INPUT' && (!activeNode.type || activeNode.type == 'text'))) {
  255. if (fixedDiv.style.display === 'none') {
  256. fixedDiv.style.display = 'block';
  257. fixedDiv.style.opacity = '0.4';
  258. focusElement = activeNode;
  259. console.log(focusElement)
  260. }
  261. }
  262.  
  263. requestAnimationFrame(() => {
  264.  
  265. lastDragIn = Date.now();
  266. });
  267. }, true);
  268.  
  269. document.addEventListener('drop', function (event) {
  270. if (!fixedDiv) return;
  271. moused = false;
  272. if (moused) return;
  273. if (cid > 0) cid = clearTimeout(cid);
  274. console.log(223);
  275.  
  276. let endTime = Date.now();
  277. cid = setTimeout(() => {
  278. cid = 0;
  279. if (lastDragIn > endTime) return;
  280. if (fixedDiv.style.display !== 'none' && !moused) {
  281. // focusElement = null;
  282.  
  283. fixedDiv.style.display = 'none';
  284. fixedDiv.style.opacity = '0';
  285. }
  286. }, 80)
  287.  
  288.  
  289. }, true);
  290.  
  291.  
  292.  
  293. window.addEventListener('message', event => {
  294. if (!fixedDiv) return;
  295.  
  296. let data = (((event || 0).data || 0));
  297.  
  298.  
  299. if (data === 'pNwjxjQi-top-uploader-ready') {
  300.  
  301. let fixedDiv = document.querySelector('#ewIMf5Dw');
  302. let iframe = fixedDiv.querySelector('iframe');
  303.  
  304. iframe.style.transform = '';
  305. fixedDiv.style.transform = '';
  306.  
  307. }
  308.  
  309. if (data === 'pNwjxjQi-top-dragenter') {
  310. moused = true;
  311. fixedDiv.style.opacity = '1';
  312. }
  313. if (data === 'pNwjxjQi-top-dragleave') {
  314. moused = false;
  315. fixedDiv.style.opacity = '0.4';
  316. }
  317.  
  318. if (data === 'pNwjxjQi-top-dragenter') {
  319.  
  320. if (cid > 0) cid = clearTimeout(cid);
  321. }
  322.  
  323. if (data === 'pNwjxjQi-top-dragleave') {
  324.  
  325. let endTime = Date.now();
  326. if (cid > 0) cid = clearTimeout(cid);
  327. cid = setTimeout(() => {
  328. cid = 0;
  329. requestAnimationFrame(() => {
  330. if (lastDragIn > endTime) return;
  331.  
  332. if (fixedDiv.style.display !== 'none' && !moused) {
  333.  
  334. // focusElement = null;
  335. fixedDiv.style.display = 'none';
  336. fixedDiv.style.opacity = '0';
  337. }
  338. });
  339. }, 80)
  340.  
  341. }
  342.  
  343. if (data.p === 'pNwjxjQi-top-finish-upload') {
  344. let url = event.data.url;
  345. focusElement.focus();
  346. document.execCommand("insertText", false, url)
  347. }
  348.  
  349. if (data === 'pNwjxjQi-top-drop') {
  350. moused = false;
  351.  
  352. let endTime = Date.now();
  353. cid = setTimeout(() => {
  354. cid = 0;
  355. if (lastDragIn > endTime) return;
  356. if (fixedDiv.style.display !== 'none' && !moused) {
  357. // focusElement = null;
  358.  
  359. fixedDiv.style.display = 'none';
  360. fixedDiv.style.opacity = '0';
  361. }
  362. }, 80)
  363. }
  364.  
  365. })
  366.  
  367. }
  368. if (document.readyState !== 'loading') {
  369. onReady();
  370. } else {
  371. document.addEventListener('DOMContentLoaded', onReady, false);
  372. }
  373.  
  374.  
  375.  
  376. }
  377. })();