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.0
  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. window.addEventListener('message', (e) => {
  19.  
  20. if ((((e || 0).data || 0).p || 0) === 'semmr') {
  21. // console.log(e)
  22.  
  23. // uploadImage(e.data.detail);
  24. }
  25.  
  26.  
  27. });
  28.  
  29.  
  30.  
  31.  
  32. function uploadImage(file) {
  33. // Upload the file using the provided function
  34. T(file)
  35. .then(function (url) {
  36. // focusElement.focus();
  37. // document.execCommand("insertText", false, url)
  38. console.log('Uploaded image URL:', url);
  39. })
  40. .catch(function (error) {
  41. console.error('Upload failed:', error);
  42. });
  43. }
  44.  
  45. function T(e) {
  46. return new Promise(function (resolve, reject) {
  47. window.history.replaceState(null, '', 'https://lihkg.com');
  48. var xhr = new XMLHttpRequest();
  49. var formData = new FormData();
  50. formData.append('image', e);
  51. xhr.open('POST', 'https://api.na.cx/upload');
  52.  
  53. // Set the Referer header to an empty string
  54. xhr.onreadystatechange = function () {
  55. if (xhr.readyState === 4) {
  56. if (xhr.status === 200) {
  57. var response = JSON.parse(xhr.responseText);
  58. var status = response.status;
  59. var url = response.url;
  60. var error = response.error;
  61.  
  62. if (status === 200) {
  63. resolve(url);
  64. } else {
  65. reject(new Error(error));
  66. }
  67. } else {
  68. reject(new Error('Status is not 200'));
  69. }
  70. }
  71. };
  72.  
  73. xhr.send(formData);
  74. });
  75. }
  76.  
  77.  
  78.  
  79.  
  80.  
  81. let iframe = document;
  82.  
  83. // Function to handle the dragenter event
  84. function handleDragEnter(e) {
  85. top.postMessage('top-dragenter', '*');
  86. // Add a class to visually indicate the drag over the iframe
  87. //iframe.classList.add("drag-over");
  88. }
  89.  
  90. // Function to handle the dragover event
  91. function handleDragOver(e) {
  92. // top.postMessage('top-dragover','*');
  93. e.preventDefault();
  94.  
  95. e.dataTransfer.dropEffect = 'copy';
  96. }
  97.  
  98. // Function to handle the dragleave event
  99. function handleDragLeave(e) {
  100. top.postMessage('top-dragleave', '*');
  101. // Remove the class when the drag leaves the iframe
  102. //iframe.classList.remove("drag-over");
  103. }
  104.  
  105. async function goUpload(e) {
  106.  
  107. var files = e.dataTransfer.files;
  108. let images = [...files].filter(file => file.type == "image/png" || file.type == "image/jpg" || file.type == "image/jpeg" || file.type == "image/gif")
  109. console.log(images);
  110.  
  111.  
  112. for (const image of images) {
  113. await T(image)
  114. .then(function (url) {
  115. // focusElement.focus();
  116. // document.execCommand("insertText", false, url)
  117. top.postMessage({ p: 'finish-upload', url: url }, '*')
  118. console.log('Uploaded image URL:', url);
  119. })
  120. .catch(function (error) {
  121. console.error('Upload failed:', error);
  122. });
  123. }
  124.  
  125. }
  126.  
  127. // Function to handle the drop event
  128. function handleDrop(e) {
  129. e.preventDefault();
  130. top.postMessage('top-drop', '*');
  131.  
  132. // Remove the class when the drop occurs
  133. //iframe.classList.remove("drag-over");
  134.  
  135. // Access the dropped files or data
  136.  
  137.  
  138.  
  139. goUpload(e);
  140.  
  141.  
  142. // Process the dropped files or data as needed
  143. // ...
  144. }
  145. // Add event listeners for drag and drop events
  146. iframe.addEventListener("dragenter", handleDragEnter, false);
  147. iframe.addEventListener("dragover", handleDragOver, false);
  148. iframe.addEventListener("dragleave", handleDragLeave, false);
  149. iframe.addEventListener("drop", handleDrop, false);
  150.  
  151. /*
  152. // Prevent the default behavior for dragover and drop events
  153. iframe.addEventListener("dragover", function (e) {
  154. e.preventDefault();
  155. });
  156. iframe.addEventListener("drop", function (e) {
  157. e.preventDefault();
  158. });*/
  159.  
  160.  
  161. top.postMessage('top-uploader-ready','*');
  162.  
  163.  
  164. } else {
  165.  
  166.  
  167.  
  168. function onReady() {
  169.  
  170.  
  171.  
  172. // Create the fixed div element
  173. var fixedDiv = document.createElement('div');
  174. fixedDiv.style.position = 'fixed';
  175. fixedDiv.style.zIndex = '8888';
  176. fixedDiv.style.bottom = '10px';
  177. fixedDiv.style.right = '10px';
  178. fixedDiv.style.width = '200px';
  179. fixedDiv.style.height = '200px';
  180. fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
  181. fixedDiv.style.border = '2px solid white';
  182. fixedDiv.style.borderRadius = '5px';
  183. fixedDiv.style.padding = '0px';
  184. fixedDiv.style.color = 'white';
  185. fixedDiv.style.fontSize = '14px';
  186. fixedDiv.style.textAlign = 'center';
  187. // fixedDiv.style.cursor = 'move';
  188. // fixedDiv.draggable = true;
  189. fixedDiv.style.opacity = '0'; // Set initial opacity to 0 (hidden)
  190. fixedDiv.style.display = 'none';
  191. fixedDiv.id = 'maksdmksrnvj';
  192. fixedDiv.style.background = 'url(https://static.thenounproject.com/png/3905046-200.png)';
  193. fixedDiv.style.backgroundPosition = 'center';
  194. fixedDiv.style.backgroundSize = 'cover';
  195. fixedDiv.style.backgroundRepeat = 'no-repeat';
  196.  
  197. fixedDiv.style.pointerEvents = 'none';
  198.  
  199. let focusElement = null;
  200.  
  201.  
  202. let moused = false;
  203.  
  204.  
  205.  
  206.  
  207. let lastDragIn = 0;
  208. let cid = 0;
  209. function setupIframe(iframe) {
  210.  
  211. iframe.style.position = 'relative';
  212. iframe.style.width = '100%';
  213. iframe.style.height = '100%';
  214. iframe.style.opacity = '0';
  215. iframe.style.pointerEvents = 'all';
  216. iframe.style.transform='translateY(-300vh)';
  217. fixedDiv.style.transform='translateY(-300vh)';
  218.  
  219. window.addEventListener('message',e=>{
  220. if(e.data==='top-uploader-ready'){
  221.  
  222. iframe.style.transform='';
  223. fixedDiv.style.transform='';
  224.  
  225. }
  226. })
  227.  
  228.  
  229. // iframe.id='maksdmksrnvj';
  230.  
  231. /*
  232. // Function to handle the dragenter event
  233. function handleDragEnter(e) {
  234. // Add a class to visually indicate the drag over the iframe
  235. iframe.classList.add("drag-over");
  236. }
  237.  
  238. // Function to handle the dragover event
  239. function handleDragOver(e) {
  240. e.preventDefault();
  241. }
  242.  
  243. // Function to handle the dragleave event
  244. function handleDragLeave(e) {
  245. // Remove the class when the drag leaves the iframe
  246. iframe.classList.remove("drag-over");
  247. }
  248.  
  249. // Function to handle the drop event
  250. function handleDrop(e) {
  251. e.preventDefault();
  252.  
  253. // Remove the class when the drop occurs
  254. iframe.classList.remove("drag-over");
  255.  
  256. // Access the dropped files or data
  257. var files = e.dataTransfer.files;
  258. var data = e.dataTransfer.getData("text/plain");
  259.  
  260. // Process the dropped files or data as needed
  261. // ...
  262. }
  263. // Add event listeners for drag and drop events
  264. iframe.addEventListener("dragenter", handleDragEnter, false);
  265. iframe.addEventListener("dragover", handleDragOver, false);
  266. iframe.addEventListener("dragleave", handleDragLeave, false);
  267. iframe.addEventListener("drop", handleDrop, false);
  268.  
  269. // Prevent the default behavior for dragover and drop events
  270. iframe.addEventListener("dragover", function (e) {
  271. e.preventDefault();
  272. });
  273. iframe.addEventListener("drop", function (e) {
  274. e.preventDefault();
  275. });
  276. */
  277.  
  278.  
  279. }
  280.  
  281. // Create the Intersection Observer
  282. var observer = new IntersectionObserver(function (entries) {
  283. entries.forEach(function (entry) {
  284. if (entry.isIntersecting) {
  285. // When fixedDiv appears, check if it has an iframe inside
  286. var iframe = fixedDiv.querySelector('iframe');
  287. if (!iframe) {
  288. // If no iframe inside, create and append one
  289. iframe = document.createElement('iframe');
  290.  
  291. setupIframe(iframe)
  292.  
  293. /*
  294. iframe.style.position = 'fixed';
  295.  
  296. iframe.style.zIndex = '8888';
  297. iframe.style.left = '-1000px';
  298. iframe.style.top = '-1000px';
  299. iframe.style.width = '200px';
  300. iframe.style.height = '200px';
  301. */
  302. iframe.src = 'https://lihkg.com/robots.txt';
  303. fixedDiv.appendChild(iframe);
  304. }
  305. }
  306. });
  307. });
  308.  
  309. // Observe the fixedDiv element
  310. observer.observe(fixedDiv);
  311.  
  312. /*
  313.  
  314.  
  315.  
  316.  
  317. fixedDiv.addEventListener('dragenter', function () {
  318. if (event.relatedTarget && event.relatedTarget.closest('#maksdmksrnvj')) return;
  319. if (event.target && event.target.closest('iframe')) return;
  320. moused = true;
  321. })*/
  322.  
  323. window.addEventListener('message', e => {
  324. if (e.data === 'top-dragenter') {
  325. moused = true;
  326. fixedDiv.style.opacity = '1';
  327. }
  328. if (e.data === 'top-dragleave') {
  329. moused = false;
  330. fixedDiv.style.opacity = '0.4';
  331. }
  332.  
  333. })
  334. /*
  335.  
  336. fixedDiv.addEventListener('dragleave', function () {
  337. if (event.relatedTarget && event.relatedTarget.closest('#maksdmksrnvj')) return;
  338. if (event.target && event.target.closest('iframe')) return;
  339. moused = false;
  340. })
  341.  
  342. fixedDiv.addEventListener('dragenter', function (event) {
  343. if (event.target && event.target.closest('iframe')) return;
  344. if (cid > 0) cid = clearTimeout(cid);
  345. if (+fixedDiv.style.opacity > 0.9) return;
  346. event.preventDefault();
  347. fixedDiv.style.opacity = '1'; // Show the div when cursor enters by setting opacity to 1
  348. });
  349.  
  350. */
  351.  
  352. window.addEventListener('message', event => {
  353. if (event.data === 'top-dragenter') {
  354.  
  355. if (cid > 0) cid = clearTimeout(cid);
  356. }
  357.  
  358. })
  359. /*
  360.  
  361. fixedDiv.addEventListener('dragleave', function (event) {
  362. if (event.target && event.target.closest('iframe')) return;
  363. if (+fixedDiv.style.opacity < 0.9) return;
  364. if (event.target.closest('#maksdmksrnvj')) return;
  365. console.log(124);
  366. event.preventDefault();
  367. fixedDiv.style.opacity = '0.4'; // Hide the div when cursor leaves by setting opacity to 0
  368. });
  369.  
  370. fixedDiv.addEventListener('drop', function (event) {
  371. moused = false;
  372. if (event.target && event.target.closest('iframe')) return;
  373. console.log(126);
  374. event.preventDefault();
  375. fixedDiv.style.opacity = '0.4'; // Hide the div after the drop by setting opacity to 0
  376.  
  377. var files = event.dataTransfer.files;
  378. if (files.length > 0) {
  379. var file = files[0];
  380. uploadImage(file);
  381. }
  382. });
  383.  
  384. fixedDiv.addEventListener('dragover', function (event) {
  385. if (event.target && event.target.closest('iframe')) return;
  386. if (cid > 0) cid = clearTimeout(cid);
  387. event.preventDefault();
  388. event.dataTransfer.dropEffect = 'copy';
  389. });
  390. */
  391.  
  392.  
  393.  
  394. document.addEventListener('dragleave', function (event) {
  395. if (moused) return;
  396.  
  397. if (cid > 0) cid = clearTimeout(cid);
  398. if (event.relatedTarget) return;
  399. console.log(221);
  400.  
  401. let endTime = Date.now();
  402. cid = setTimeout(() => {
  403. cid = 0;
  404. requestAnimationFrame(() => {
  405. if (lastDragIn > endTime) return;
  406.  
  407. if (fixedDiv.style.display !== 'none' && !moused) {
  408.  
  409. // focusElement = null;
  410. fixedDiv.style.display = 'none';
  411. fixedDiv.style.opacity = '0';
  412. }
  413. });
  414. }, 80)
  415.  
  416. event.preventDefault();
  417.  
  418. });
  419.  
  420. window.addEventListener('message', e => {
  421.  
  422. if (e.data === 'top-dragleave') {
  423.  
  424. let endTime = Date.now();
  425. if (cid > 0) cid = clearTimeout(cid);
  426. cid = setTimeout(() => {
  427. cid = 0;
  428. requestAnimationFrame(() => {
  429. if (lastDragIn > endTime) return;
  430.  
  431. if (fixedDiv.style.display !== 'none' && !moused) {
  432.  
  433. // focusElement = null;
  434. fixedDiv.style.display = 'none';
  435. fixedDiv.style.opacity = '0';
  436. }
  437. });
  438. }, 80)
  439.  
  440. }
  441. })
  442.  
  443. document.addEventListener('dragenter', function (event) {
  444. if (moused) return;
  445. if (cid > 0) cid = clearTimeout(cid);
  446. if (event.relatedTarget) return;
  447. console.log(222);
  448.  
  449.  
  450. lastDragIn = Date.now();
  451.  
  452. let activeNode = document.activeElement || 0;
  453. let activeNodeName = activeNode.nodeName;
  454. if (activeNodeName === 'TEXTAREA' || (activeNodeName === 'INPUT' && (!activeNode.type || activeNode.type == 'text'))) {
  455. if (fixedDiv.style.display === 'none') {
  456. fixedDiv.style.display = 'block';
  457. fixedDiv.style.opacity = '0.4';
  458. focusElement = activeNode;
  459. console.log(focusElement)
  460. }
  461. }
  462.  
  463. requestAnimationFrame(() => {
  464.  
  465. lastDragIn = Date.now();
  466. });
  467. }, true);
  468.  
  469. document.addEventListener('drop', function (event) {
  470. moused = false;
  471. if (moused) return;
  472. if (cid > 0) cid = clearTimeout(cid);
  473. console.log(223);
  474.  
  475. let endTime = Date.now();
  476. cid = setTimeout(() => {
  477. cid = 0;
  478. if (lastDragIn > endTime) return;
  479. if (fixedDiv.style.display !== 'none' && !moused) {
  480. // focusElement = null;
  481.  
  482. fixedDiv.style.display = 'none';
  483. fixedDiv.style.opacity = '0';
  484. }
  485. }, 80)
  486.  
  487.  
  488. }, true);
  489.  
  490. window.addEventListener('message', event => {
  491.  
  492. if (event.data === 'top-drop') {
  493. moused = false;
  494.  
  495. let endTime = Date.now();
  496. cid = setTimeout(() => {
  497. cid = 0;
  498. if (lastDragIn > endTime) return;
  499. if (fixedDiv.style.display !== 'none' && !moused) {
  500. // focusElement = null;
  501.  
  502. fixedDiv.style.display = 'none';
  503. fixedDiv.style.opacity = '0';
  504. }
  505. }, 80)
  506. }
  507.  
  508. })
  509.  
  510.  
  511. // fixedDiv.innerText = 'Drag and drop images here';
  512.  
  513. // Append the div to the document body
  514. document.body.appendChild(fixedDiv);
  515.  
  516.  
  517. /*
  518.  
  519. // Create the fixed div element
  520. var fixedDiv = document.createElement('div');
  521. fixedDiv.style.position = 'fixed';
  522. fixedDiv.style.bottom = '10px';
  523. fixedDiv.style.right = '10px';
  524. fixedDiv.style.width = '200px';
  525. fixedDiv.style.height = '200px';
  526. fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
  527. fixedDiv.style.border = '2px solid white';
  528. fixedDiv.style.borderRadius = '5px';
  529. fixedDiv.style.padding = '10px';
  530. fixedDiv.style.color = 'white';
  531. fixedDiv.style.fontSize = '14px';
  532. fixedDiv.style.textAlign = 'center';
  533. fixedDiv.style.cursor = 'move';
  534. fixedDiv.draggable = true;
  535. fixedDiv.setAttribute('ondragstart', 'event.dataTransfer.setData("text/plain",null)');
  536.  
  537. fixedDiv.innerText = 'Drag and drop images here';
  538.  
  539. // Append the div to the document body
  540. document.body.appendChild(fixedDiv);
  541.  
  542. // Implement drag and drop event handlers
  543. fixedDiv.addEventListener('dragover', function(e) {
  544. e.preventDefault();
  545. e.dataTransfer.dropEffect = 'copy';
  546. fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
  547. });
  548.  
  549. fixedDiv.addEventListener('dragleave', function(e) {
  550. e.preventDefault();
  551. fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
  552. });
  553.  
  554. fixedDiv.addEventListener('drop', function(e) {
  555. e.preventDefault();
  556. fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
  557.  
  558. var files = e.dataTransfer.files;
  559. if (files.length > 0) {
  560. var file = files[0];
  561. uploadImage(file);
  562. }
  563. });
  564. */
  565.  
  566. window.addEventListener('message', (event) => {
  567. if ((((event || 0).data || 0).p) === 'finish-upload') {
  568. let url = event.data.url;
  569. focusElement.focus();
  570. document.execCommand("insertText", false, url)
  571.  
  572. }
  573. })
  574.  
  575. function uploadImage(file) {
  576. // Upload the file using the provided function
  577. T(file)
  578. .then(function (url) {
  579. focusElement.focus();
  580. document.execCommand("insertText", false, url)
  581. console.log('Uploaded image URL:', url);
  582. })
  583. .catch(function (error) {
  584. console.error('Upload failed:', error);
  585. });
  586. }
  587.  
  588. function T(e) {
  589. return new Promise(function (resolve, reject) {
  590. var xhr = new XMLHttpRequest();
  591. var formData = new FormData();
  592. formData.append('image', e);
  593.  
  594. /*
  595. xhr.open('POST', 'https://api.na.cx/upload');
  596. xhr.onreadystatechange = function() {
  597. if (xhr.readyState === 4) {
  598. if (xhr.status === 200) {
  599. var response = JSON.parse(xhr.responseText);
  600. var status = response.status;
  601. var url = response.url;
  602. var error = response.error;
  603.  
  604. if (status === 200) {
  605. resolve(url);
  606. } else {
  607. reject(new Error(error));
  608. }
  609. } else {
  610. reject(new Error('Status is not 200'));
  611. }
  612. }
  613. };
  614.  
  615. xhr.send(formData);
  616. */
  617.  
  618. fixedDiv.querySelector('iframe').contentWindow.postMessage({ p: 'semmr', detail: e }, '*')
  619. });
  620. }
  621. }
  622. if (document.readyState !== 'loading') {
  623. onReady();
  624. } else {
  625. document.addEventListener('DOMContentLoaded', onReady, false);
  626. }
  627.  
  628.  
  629.  
  630. }
  631. })();