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 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Drag-Drop Image Uploader
// @namespace           http://tampermonkey.net/
// @version      0.1.0
// @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.
// @match        https://*/*
// @grant        none
// @license             MIT License
// @author              CY Fung
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    if (location.hostname === 'lihkg.com') {

        window.addEventListener('message', (e) => {

            if ((((e || 0).data || 0).p || 0) === 'semmr') {
                // console.log(e)

                // uploadImage(e.data.detail);
            }


        });




        function uploadImage(file) {
            // Upload the file using the provided function
            T(file)
                .then(function (url) {
                    // focusElement.focus();
                    // document.execCommand("insertText", false, url)
                    console.log('Uploaded image URL:', url);
                })
                .catch(function (error) {
                    console.error('Upload failed:', error);
                });
        }

        function T(e) {
            return new Promise(function (resolve, reject) {
                window.history.replaceState(null, '', 'https://lihkg.com');
                var xhr = new XMLHttpRequest();
                var formData = new FormData();
                formData.append('image', e);
                xhr.open('POST', 'https://api.na.cx/upload');

// Set the Referer header to an empty string
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        if (xhr.status === 200) {
                            var response = JSON.parse(xhr.responseText);
                            var status = response.status;
                            var url = response.url;
                            var error = response.error;

                            if (status === 200) {
                                resolve(url);
                            } else {
                                reject(new Error(error));
                            }
                        } else {
                            reject(new Error('Status is not 200'));
                        }
                    }
                };

                xhr.send(formData);
            });
        }





        let iframe = document;

        // Function to handle the dragenter event
        function handleDragEnter(e) {
            top.postMessage('top-dragenter', '*');
            // Add a class to visually indicate the drag over the iframe
            //iframe.classList.add("drag-over");
        }

        // Function to handle the dragover event
        function handleDragOver(e) {
            // top.postMessage('top-dragover','*');
            e.preventDefault();

            e.dataTransfer.dropEffect = 'copy';
        }

        // Function to handle the dragleave event
        function handleDragLeave(e) {
            top.postMessage('top-dragleave', '*');
            // Remove the class when the drag leaves the iframe
            //iframe.classList.remove("drag-over");
        }

        async function goUpload(e) {

            var files = e.dataTransfer.files;
            let images = [...files].filter(file => file.type == "image/png" || file.type == "image/jpg" || file.type == "image/jpeg" || file.type == "image/gif")
            console.log(images);


            for (const image of images) {
                await T(image)
                    .then(function (url) {
                        // focusElement.focus();
                        // document.execCommand("insertText", false, url)
                        top.postMessage({ p: 'finish-upload', url: url }, '*')
                        console.log('Uploaded image URL:', url);
                    })
                    .catch(function (error) {
                        console.error('Upload failed:', error);
                    });
            }

        }

        // Function to handle the drop event
        function handleDrop(e) {
            e.preventDefault();
            top.postMessage('top-drop', '*');

            // Remove the class when the drop occurs
            //iframe.classList.remove("drag-over");

            // Access the dropped files or data



            goUpload(e);


            // Process the dropped files or data as needed
            // ...
        }
        // Add event listeners for drag and drop events
        iframe.addEventListener("dragenter", handleDragEnter, false);
        iframe.addEventListener("dragover", handleDragOver, false);
        iframe.addEventListener("dragleave", handleDragLeave, false);
        iframe.addEventListener("drop", handleDrop, false);

        /*
        // Prevent the default behavior for dragover and drop events
        iframe.addEventListener("dragover", function (e) {
          e.preventDefault();
        });
        iframe.addEventListener("drop", function (e) {
          e.preventDefault();
        });*/


        top.postMessage('top-uploader-ready','*');


    } else {



        function onReady() {



            // Create the fixed div element
            var fixedDiv = document.createElement('div');
            fixedDiv.style.position = 'fixed';
            fixedDiv.style.zIndex = '8888';
            fixedDiv.style.bottom = '10px';
            fixedDiv.style.right = '10px';
            fixedDiv.style.width = '200px';
            fixedDiv.style.height = '200px';
            fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
            fixedDiv.style.border = '2px solid white';
            fixedDiv.style.borderRadius = '5px';
            fixedDiv.style.padding = '0px';
            fixedDiv.style.color = 'white';
            fixedDiv.style.fontSize = '14px';
            fixedDiv.style.textAlign = 'center';
            //    fixedDiv.style.cursor = 'move';
            // fixedDiv.draggable = true;
            fixedDiv.style.opacity = '0'; // Set initial opacity to 0 (hidden)
            fixedDiv.style.display = 'none';
            fixedDiv.id = 'maksdmksrnvj';
            fixedDiv.style.background = 'url(https://static.thenounproject.com/png/3905046-200.png)';
            fixedDiv.style.backgroundPosition = 'center';
            fixedDiv.style.backgroundSize = 'cover';
            fixedDiv.style.backgroundRepeat = 'no-repeat';

            fixedDiv.style.pointerEvents = 'none';

            let focusElement = null;


            let moused = false;




            let lastDragIn = 0;
            let cid = 0;
            function setupIframe(iframe) {

                iframe.style.position = 'relative';
                iframe.style.width = '100%';
                iframe.style.height = '100%';
                iframe.style.opacity = '0';
                iframe.style.pointerEvents = 'all';
                    iframe.style.transform='translateY(-300vh)';
                fixedDiv.style.transform='translateY(-300vh)';

                window.addEventListener('message',e=>{
                if(e.data==='top-uploader-ready'){

                    iframe.style.transform='';
                fixedDiv.style.transform='';

                }
                })


                // iframe.id='maksdmksrnvj';

                /*
                // Function to handle the dragenter event
                function handleDragEnter(e) {
                  // Add a class to visually indicate the drag over the iframe
                  iframe.classList.add("drag-over");
                }

                // Function to handle the dragover event
                function handleDragOver(e) {
                  e.preventDefault();
                }

                // Function to handle the dragleave event
                function handleDragLeave(e) {
                  // Remove the class when the drag leaves the iframe
                  iframe.classList.remove("drag-over");
                }

                // Function to handle the drop event
                function handleDrop(e) {
                  e.preventDefault();

                  // Remove the class when the drop occurs
                  iframe.classList.remove("drag-over");

                  // Access the dropped files or data
                  var files = e.dataTransfer.files;
                  var data = e.dataTransfer.getData("text/plain");

                  // Process the dropped files or data as needed
                  // ...
                }
                // Add event listeners for drag and drop events
                iframe.addEventListener("dragenter", handleDragEnter, false);
                iframe.addEventListener("dragover", handleDragOver, false);
                iframe.addEventListener("dragleave", handleDragLeave, false);
                iframe.addEventListener("drop", handleDrop, false);

                // Prevent the default behavior for dragover and drop events
                iframe.addEventListener("dragover", function (e) {
                  e.preventDefault();
                });
                iframe.addEventListener("drop", function (e) {
                  e.preventDefault();
                });
                */


            }

            // Create the Intersection Observer
            var observer = new IntersectionObserver(function (entries) {
                entries.forEach(function (entry) {
                    if (entry.isIntersecting) {
                        // When fixedDiv appears, check if it has an iframe inside
                        var iframe = fixedDiv.querySelector('iframe');
                        if (!iframe) {
                            // If no iframe inside, create and append one
                            iframe = document.createElement('iframe');

                            setupIframe(iframe)

                            /*
                            iframe.style.position = 'fixed';

                            iframe.style.zIndex = '8888';
                            iframe.style.left = '-1000px';
                            iframe.style.top = '-1000px';
                            iframe.style.width = '200px';
                            iframe.style.height = '200px';
        */
                            iframe.src = 'https://lihkg.com/robots.txt';
                            fixedDiv.appendChild(iframe);
                        }
                    }
                });
            });

            // Observe the fixedDiv element
            observer.observe(fixedDiv);

            /*




            fixedDiv.addEventListener('dragenter', function () {
                if (event.relatedTarget && event.relatedTarget.closest('#maksdmksrnvj')) return;
                if (event.target && event.target.closest('iframe')) return;
                moused = true;
            })*/

            window.addEventListener('message', e => {
                if (e.data === 'top-dragenter') {
                    moused = true;
                    fixedDiv.style.opacity = '1';
                }
                if (e.data === 'top-dragleave') {
                    moused = false;
                    fixedDiv.style.opacity = '0.4';
                }

            })
            /*

            fixedDiv.addEventListener('dragleave', function () {
                if (event.relatedTarget && event.relatedTarget.closest('#maksdmksrnvj')) return;
                if (event.target && event.target.closest('iframe')) return;
                moused = false;
            })

            fixedDiv.addEventListener('dragenter', function (event) {
                if (event.target && event.target.closest('iframe')) return;
                if (cid > 0) cid = clearTimeout(cid);
                if (+fixedDiv.style.opacity > 0.9) return;
                event.preventDefault();
                fixedDiv.style.opacity = '1'; // Show the div when cursor enters by setting opacity to 1
            });

            */

            window.addEventListener('message', event => {
                if (event.data === 'top-dragenter') {

                    if (cid > 0) cid = clearTimeout(cid);
                }

            })
            /*

            fixedDiv.addEventListener('dragleave', function (event) {
                if (event.target && event.target.closest('iframe')) return;
                if (+fixedDiv.style.opacity < 0.9) return;
                if (event.target.closest('#maksdmksrnvj')) return;
                console.log(124);
                event.preventDefault();
                fixedDiv.style.opacity = '0.4'; // Hide the div when cursor leaves by setting opacity to 0
            });

            fixedDiv.addEventListener('drop', function (event) {
                moused = false;
                if (event.target && event.target.closest('iframe')) return;
                console.log(126);
                event.preventDefault();
                fixedDiv.style.opacity = '0.4'; // Hide the div after the drop by setting opacity to 0

                var files = event.dataTransfer.files;
                if (files.length > 0) {
                    var file = files[0];
                    uploadImage(file);
                }
            });

            fixedDiv.addEventListener('dragover', function (event) {
                if (event.target && event.target.closest('iframe')) return;
                if (cid > 0) cid = clearTimeout(cid);
                event.preventDefault();
                event.dataTransfer.dropEffect = 'copy';
            });
            */



            document.addEventListener('dragleave', function (event) {
                if (moused) return;

                if (cid > 0) cid = clearTimeout(cid);
                if (event.relatedTarget) return;
                console.log(221);

                let endTime = Date.now();
                cid = setTimeout(() => {
                    cid = 0;
                    requestAnimationFrame(() => {
                        if (lastDragIn > endTime) return;

                        if (fixedDiv.style.display !== 'none' && !moused) {

                            // focusElement = null;
                            fixedDiv.style.display = 'none';
                            fixedDiv.style.opacity = '0';
                        }
                    });
                }, 80)

                event.preventDefault();

            });

            window.addEventListener('message', e => {

                if (e.data === 'top-dragleave') {

                    let endTime = Date.now();
                    if (cid > 0) cid = clearTimeout(cid);
                    cid = setTimeout(() => {
                        cid = 0;
                        requestAnimationFrame(() => {
                            if (lastDragIn > endTime) return;

                            if (fixedDiv.style.display !== 'none' && !moused) {

                                // focusElement = null;
                                fixedDiv.style.display = 'none';
                                fixedDiv.style.opacity = '0';
                            }
                        });
                    }, 80)

                }
            })

            document.addEventListener('dragenter', function (event) {
                if (moused) return;
                if (cid > 0) cid = clearTimeout(cid);
                if (event.relatedTarget) return;
                console.log(222);


                lastDragIn = Date.now();

                let activeNode = document.activeElement || 0;
                let activeNodeName = activeNode.nodeName;
                if (activeNodeName === 'TEXTAREA' || (activeNodeName === 'INPUT' && (!activeNode.type || activeNode.type == 'text'))) {
                    if (fixedDiv.style.display === 'none') {
                        fixedDiv.style.display = 'block';
                        fixedDiv.style.opacity = '0.4';
                        focusElement = activeNode;
                        console.log(focusElement)
                    }
                }

                requestAnimationFrame(() => {

                    lastDragIn = Date.now();
                });
            }, true);

            document.addEventListener('drop', function (event) {
                moused = false;
                if (moused) return;
                if (cid > 0) cid = clearTimeout(cid);
                console.log(223);

                let endTime = Date.now();
                cid = setTimeout(() => {
                    cid = 0;
                    if (lastDragIn > endTime) return;
                    if (fixedDiv.style.display !== 'none' && !moused) {
                        // focusElement = null;

                        fixedDiv.style.display = 'none';
                        fixedDiv.style.opacity = '0';
                    }
                }, 80)


            }, true);

            window.addEventListener('message', event => {

                if (event.data === 'top-drop') {
                    moused = false;

                    let endTime = Date.now();
                    cid = setTimeout(() => {
                        cid = 0;
                        if (lastDragIn > endTime) return;
                        if (fixedDiv.style.display !== 'none' && !moused) {
                            // focusElement = null;

                            fixedDiv.style.display = 'none';
                            fixedDiv.style.opacity = '0';
                        }
                    }, 80)
                }

            })


            // fixedDiv.innerText = 'Drag and drop images here';

            // Append the div to the document body
            document.body.appendChild(fixedDiv);


            /*

            // Create the fixed div element
            var fixedDiv = document.createElement('div');
            fixedDiv.style.position = 'fixed';
            fixedDiv.style.bottom = '10px';
            fixedDiv.style.right = '10px';
            fixedDiv.style.width = '200px';
            fixedDiv.style.height = '200px';
            fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
            fixedDiv.style.border = '2px solid white';
            fixedDiv.style.borderRadius = '5px';
            fixedDiv.style.padding = '10px';
            fixedDiv.style.color = 'white';
            fixedDiv.style.fontSize = '14px';
            fixedDiv.style.textAlign = 'center';
            fixedDiv.style.cursor = 'move';
            fixedDiv.draggable = true;
            fixedDiv.setAttribute('ondragstart', 'event.dataTransfer.setData("text/plain",null)');

            fixedDiv.innerText = 'Drag and drop images here';

            // Append the div to the document body
            document.body.appendChild(fixedDiv);

            // Implement drag and drop event handlers
            fixedDiv.addEventListener('dragover', function(e) {
                e.preventDefault();
                e.dataTransfer.dropEffect = 'copy';
                fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
            });

            fixedDiv.addEventListener('dragleave', function(e) {
                e.preventDefault();
                fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
            });

            fixedDiv.addEventListener('drop', function(e) {
                e.preventDefault();
                fixedDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';

                var files = e.dataTransfer.files;
                if (files.length > 0) {
                    var file = files[0];
                    uploadImage(file);
                }
            });
            */

            window.addEventListener('message', (event) => {
                if ((((event || 0).data || 0).p) === 'finish-upload') {
                    let url = event.data.url;
                    focusElement.focus();
                    document.execCommand("insertText", false, url)

                }
            })

            function uploadImage(file) {
                // Upload the file using the provided function
                T(file)
                    .then(function (url) {
                        focusElement.focus();
                        document.execCommand("insertText", false, url)
                        console.log('Uploaded image URL:', url);
                    })
                    .catch(function (error) {
                        console.error('Upload failed:', error);
                    });
            }

            function T(e) {
                return new Promise(function (resolve, reject) {
                    var xhr = new XMLHttpRequest();
                    var formData = new FormData();
                    formData.append('image', e);

                    /*
                    xhr.open('POST', 'https://api.na.cx/upload');
                    xhr.onreadystatechange = function() {
                        if (xhr.readyState === 4) {
                            if (xhr.status === 200) {
                                var response = JSON.parse(xhr.responseText);
                                var status = response.status;
                                var url = response.url;
                                var error = response.error;

                                if (status === 200) {
                                    resolve(url);
                                } else {
                                    reject(new Error(error));
                                }
                            } else {
                                reject(new Error('Status is not 200'));
                            }
                        }
                    };

                    xhr.send(formData);
                    */

                    fixedDiv.querySelector('iframe').contentWindow.postMessage({ p: 'semmr', detail: e }, '*')
                });
            }
        }
        if (document.readyState !== 'loading') {
            onReady();
        } else {
            document.addEventListener('DOMContentLoaded', onReady, false);
        }



    }
})();