tl;dr Github link (raw)
Motivation
I really like to accompany my questions with images, especially on sites like Graphic Design or Chemistry.
Very often, my images are just annotated screenshots or minimalistic gesticulations. Still, for every single one, I have to go through this horrible process:
- Create the image in mspaint or other. OR Resize big photo to small photo
- Save the file (usially, I just create "deleteme" file somewhere)
- Select that file in the SE upload image dialog (my OS is somehow broken and the system file dialog always laggs)
- Wait before the image uploads, being unable to type any text
I recently played with some image processing and to sip the pain of file dialog, I implemented paste and drag'n'drop for that script.
Now I decided to apply this feature to stack exchange. Please note that this is my first userscript for the site and I'm unaware of any API functions I could've used. The script is also quite messy, because I made it in quite a short time.
This is why pull requests are very welcome!
How does it work (user level)
Copy an image from your image editor into clipboard. Paste it in the textbox. If you highlight any text it will be used as the image description. As soon as you paste, this appears in the text field:
![your description (or nothing)](loading url...)
If the image is very large (specifically, wider than 650 pixels, maximum size of the question div) you will be prompted if you want to resize it. This results in much faster upload, while the rendered size will be the same.
If you decline image will not be changed.
You can now continue typing as the image is uploading in the background. As soon as the image is loaded, it will appear in brackets. Do not type anything important in round brackets as your input will be replaced by the URL when the image is loaded.
In Firefox, you may also paste files. Note that I didn't implement any kind of file type checking. This version is quite unstable.
Notable limitations
- You can't paste image that was directly copied form other site due to CORS. This will get fixed using CORS proxy (effectively rendering CORS just useless annoyance)
- The image markup doesn't use the normal link referencing (
...[i]
), because I didn't figure out how to call editor internal commands. - If you just paste the image, you must type one character before the prewiev below is updated
- File pasting doesn't work in Google Chrome (but image data pasting is OK)
Only `/questions/ask is currently included. This script therefore only works when asking a question- fixed
How does it work (programer level)
Pasting
When you press Ctrl+V, focus on the textarea is stolen by a hidden <div conntenteditable>
. When the paste operation happens (onpaste
event), the <div>
checks for the files in the clipboard (firefox only). Only first file will be picked. If file is found, the event is canceled.
Getting pasted data
Usually, no files are found. But soon enough, input
event fires on <div>
and if there's any image data in the clipboard, browser will interpret it as <img>
element. If any images are found, they will be uploaded.
How normal text/plain
pasting works witht he script
If no image data are found, the original text/plain
clipboard data will be inserted in the <textarea>
on the current caret selection. Unfortunately, it's not possible to fire real paste event to leave the pasting on the browser implementation. However my script implementation seems to be flawless regarding this task.
Upload
There's a big problem with CORS regarding images copied from other sites. They are still referenced by their URL.
Whatever file was retrieved will be then converted to canvas, eventually resized and from canvas to blob. The upload function is pretty straightforward then, since I just looked up POST fields in firebug. There's just a strange token called fkey
that's used using upload.
Url replacing
When you paste the file and the link markup code is inserted an abstract selection node is created around it. This is most complex part of the program. The script is poorly documented and quite complicated.