"function(input){\n var files = input.files,\n dt = new DataTransfer(),\n opts = { cancelable: true, bubbles: true, dataTransfer: dt };\n input.parentElement.removeChild(input);\n if (dt.items){\n for (var i=0; i<files.length; i++){\n dt.items.add(files[i]);\n }\n } else {\n Object.defineProperty(dt, \"files\", {\n value: files,\n writable: false\n });\n }\n var dropEvent = new DragEvent('drop', opts);\n this.dispatchEvent(dropEvent);\n}\n"
"let source = arguments[0];\nconst target = arguments[1];\nconst step_delay = arguments[2] * 1000;\nconst drop_modifiers = arguments[3];\nconst key_aliases = {\n 'cmd': 'meta',\n 'command': 'meta',\n 'control': 'ctrl',\n};\n\nfunction rectCenter(rect){\n return new DOMPoint(\n (rect.left + rect.right)/2,\n (rect.top + rect.bottom)/2\n );\n}\n\nfunction pointOnRect(pt, rect) {\n var rectPt = rectCenter(rect);\n var slope = (rectPt.y - pt.y) / (rectPt.x - pt.x);\n\n if (pt.x <= rectPt.x) { // left side\n var minXy = slope * (rect.left - pt.x) + pt.y;\n if (rect.top <= minXy && minXy <= rect.bottom)\n return new DOMPoint(rect.left, minXy);\n }\n\n if (pt.x >= rectPt.x) { // right side\n var maxXy = slope * (rect.right - pt.x) + pt.y;\n if (rect.top <= maxXy && maxXy <= rect.bottom)\n return new DOMPoint(rect.right, maxXy);\n }\n\n if (pt.y <= rectPt.y) { // top side\n var minYx = (rectPt.top - pt.y) / slope + pt.x;\n if (rect.left <= minYx && minYx <= rect.right)\n return new DOMPoint(minYx, rect.top);\n }\n\n if (pt.y >= rectPt.y) { // bottom side\n var maxYx = (rect.bottom - pt.y) / slope + pt.x;\n if (rect.left <= maxYx && maxYx <= rect.right)\n return new DOMPoint(maxYx, rect.bottom);\n }\n\n return new DOMPoint(pt.x,pt.y);\n}\n\nfunction dragStart() {\n return new Promise( resolve => {\n var dragEvent = new DragEvent('dragstart', opts);\n source.dispatchEvent(dragEvent);\n setTimeout(resolve, step_delay)\n })\n}\n\nfunction dragEnter() {\n return new Promise( resolve => {\n target.scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'});\n let targetRect = target.getBoundingClientRect(),\n sourceCenter = rectCenter(source.getBoundingClientRect());\n\n drop_modifiers.map(key => key_aliases[key] || key)\n .forEach(key => opts[key + 'Key'] = true);\n\n // fire 2 dragover events to simulate dragging with a direction\n let entryPoint = pointOnRect(sourceCenter, targetRect);\n let dragOverOpts = Object.assign({clientX: entryPoint.x, clientY: entryPoint.y}, opts);\n let dragOverEvent = new DragEvent('dragover', dragOverOpts);\n target.dispatchEvent(dragOverEvent);\n setTimeout(resolve, step_delay)\n })\n}\n\nfunction dragOnto() {\n return new Promise( resolve => {\n var targetCenter = rectCenter(target.getBoundingClientRect());\n dragOverOpts = Object.assign({clientX: targetCenter.x, clientY: targetCenter.y}, opts);\n dragOverEvent = new DragEvent('dragover', dragOverOpts);\n target.dispatchEvent(dragOverEvent);\n setTimeout(resolve, step_delay, { drop: dragOverEvent.defaultPrevented, opts: dragOverOpts});\n })\n}\n\nfunction dragLeave({ drop, opts: dragOverOpts }) {\n return new Promise( resolve => {\n var dragLeaveOptions = { ...opts, ...dragOverOpts };\n var dragLeaveEvent = new DragEvent('dragleave', dragLeaveOptions);\n target.dispatchEvent(dragLeaveEvent);\n if (drop) {\n var dropEvent = new DragEvent('drop', dragLeaveOptions);\n target.dispatchEvent(dropEvent);\n }\n var dragEndEvent = new DragEvent('dragend', dragLeaveOptions);\n source.dispatchEvent(dragEndEvent);\n setTimeout(resolve, step_delay);\n })\n}\n\nconst dt = new DataTransfer();\nconst opts = { cancelable: true, bubbles: true, dataTransfer: dt };\n\nwhile (source && !source.draggable) {\n source = source.parentElement;\n}\n\nif (source.tagName == 'A'){\n dt.setData('text/uri-list', source.href);\n dt.setData('text', source.href);\n}\nif (source.tagName == 'IMG'){\n dt.setData('text/uri-list', source.src);\n dt.setData('text', source.src);\n}\n\ndragStart().then(dragEnter).then(dragOnto).then(dragLeave)\n"