Assumption: A local HTML/Javascript webpage that has access to file://
At the start of a drag on a draggable HTML element, in the event handler function dragStart(e)
, how do I add a File object so that it is recognized as a file and ends up in the dataTransfer.files
list?
Ex:
function dragStart(e){
var file = getSomeFileObjFromSomewhere();
e.originalEvent.dataTransfer.effectAllowed = "all";
e.originalEvent.dataTransfer.setData("file", file);
console.log("\nFiles:");
i = 0;
var files = e.originalEvent.dataTransfer.files,
len = files.length;
for (; i < len; i++) {
console.log("\nIndex: " + i + "\nFilename: " + files[i].name);
console.log("Type: " + files[i].type);
console.log("Size: " + files[i].size + " bytes");
console.dir(files[i]);
}
}
Specifically, it needs to work on Chrome/Chromium. And, we can assume that the file exists on the local drive. Basically, I want the same data available then when a file is dragged from Windows Explorer to a HTML page on an element that is droppable.
I know that this exists in Chrome:
e.originalEvent.dataTransfer.setData("DownloadURL", fileType + ":" + name + ":" + filePath);
which downloads the file. But this is not what I want, because I want to assume that this is an existing file and that the original file must be accessed.
You can use the approach posted by @kol at Simulate drop file event
That is, we have to pass an argument to ondrop, which
- has a
dataTransfer
field with afiles
array subfield, which contains the selectedFile
, and- a
preventDefault
method (a function with no body will do).
adjusted below to attach .addEventListener("drop")
to drop
element at dragstart
event, with File
objects passed to a bound function with Function.prototype.bind()
which returns the appropriate object described above, with once:true
passed at third parameter to .addEventListener()
, to call drop
event at most once for each dragstart
event where File
objects are accessed or created.
FileList
object is read only, an Array
is used to store File
object at dataTransfer.files
property within a plain javascript
object at event handlers.
Note: The
FileList
interface should be considered "at risk" since the general trend on the Web Platform is to replace such interfaces with theArray
platform object in ECMAScript [ECMA-262]. In particular, this means syntax of the sortfilelist.item(0)
is at risk; most other programmatic use ofFileList
is unlikely to be affected by the eventual migration to anArray
type.
If event.dataTransfer.files
at dragstart
event contains File
objects, iterate FileList
and push each File
object to files
array.
var drag = document.getElementById("drag")
var drop = document.getElementById("drop")
function handleDrop(evt) {
evt.preventDefault();
console.log(evt.dataTransfer.files);
}
function getSomeFileObjFromSomewhere() {
var data = ["abc", "def"];
var files = [];
for (var i = 0; i < data.length; i++) {
files.push(new File([data[i]], data[i] + ".text", {
type: "text/plain",
lastModified: new Date().getTime()
}));
}
return files
}
function dataTransferFileObject(files) {
return {
preventDefault: function() {},
dataTransfer: {
files: Array.isArray(files) ? files : [files]
}
}
}
drag.addEventListener("dragstart", function dragStart(e) {
var files = getSomeFileObjFromSomewhere();
e.dataTransfer.effectAllowed = "all";
console.log("\nFiles:");
for (let i = 0; i < files.length; i++) {
var {name, size, type} = files[i];
console.log("\nFilename: " + name);
console.log("Type: " + type);
console.log("Size: " + size + " bytes");
}
// if `e.dataTransfer.files`, push `File` objects dragged
// to `files` array
if (e.dataTransfer.files) {
for (let file of e.dataTransfer.files) {
files.push(file);
}
}
drop.addEventListener("drop"
, handleDrop.bind(drop, dataTransferFileObject(files))
, {once: true});
});
drop.addEventListener("dragover", function(evt) {
evt.preventDefault()
});
div {
width: 50px;
height: 50px;
padding: 10px;
margin: 10px;
}
div:nth-child(1) {
border: 2px dotted blue;
}
div:nth-child(2) {
border: 2px dotted green;
}
<div draggable="true" id="drag">drag</div>
<div droppable="true" id="drop" webkitdropzone="webkitdropzone">drop</div>
plnkr http://plnkr.co/edit/ihQqs4t2zOg2XhIuNwal?p=preview
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With