react-dnd-html5-backend
react-dnd-html5-backend copied to clipboard
Feature request: Include DataTransferItems in native sources.
The DataTransferItems
interface is the successor to the FilesList
interface of DataTransfer
objects. It's only currently supported by Chrome.
https://www.w3.org/TR/html51/editing.html#the-datatransfer-interface https://www.w3.org/TR/html51/editing.html#the-datatransferitemlist-interface
While the files
property is not accessible on event.dataTransfer
during drag events event, the items
property is. This lets us respond to native drag data much earlier stage.
monkey patch 🙉
import HTML5Backend from 'react-dnd-html5-backend/lib/HTML5Backend';
import {isFirefox} from 'react-dnd-html5-backend/lib/BrowserDetector';
import {createNativeDragSource, matchNativeItemType}
from 'react-dnd-html5-backend/lib/NativeDragSources';
HTML5Backend.prototype.updateCurrentNativeSourceItem = function(dataTransfer) {
const items = Array.prototype.slice.call(dataTransfer.items || []);
this.currentNativeSource.item.items = items;
};
// Wrapped methods:
const {handleTopDrop} = HTML5Backend.prototype;
HTML5Backend.prototype.handleTopDrop = function(e) {
if (this.isDraggingNativeItem()) {
this.updateCurrentNativeSourceItem(e.dataTransfer);
}
return handleTopDrop.call(this, e);
};
const {handleTopDragEnter} = HTML5Backend.prototype;
HTML5Backend.prototype.handleTopDragEnter = function(e) {
if (this.isDraggingNativeItem()) {
this.updateCurrentNativeSourceItem(e.dataTransfer);
}
return handleTopDragEnter.call(this, e);
};
const {handleTopDragOver} = HTML5Backend.prototype;
HTML5Backend.prototype.handleTopDragOver = function(e) {
if (this.isDraggingNativeItem()) {
this.updateCurrentNativeSourceItem(e.dataTransfer);
}
return handleTopDragOver.call(this, e);
};
// Patched methods:
HTML5Backend.prototype.handleTopDragEnterCapture = function(e) {
this.dragEnterTargetIds = [];
const isFirstEnter = this.enterLeaveCounter.enter(e.target);
if (!isFirstEnter || this.monitor.isDragging()) {
return;
}
const {dataTransfer} = e;
const nativeType = matchNativeItemType(dataTransfer);
if (nativeType) {
this.beginDragNativeItem(nativeType/* PATCH */, dataTransfer/* END PATCH */);
}
};
HTML5Backend.prototype.beginDragNativeItem = function(type, dataTransfer) {
this.clearCurrentDragSourceNode();
const SourceType = createNativeDragSource(type);
this.currentNativeSource = new SourceType();
/* PATCH */
this.updateCurrentNativeSourceItem(dataTransfer);
/* END PATCH*/
this.currentNativeHandle = this.registry.addSource(type, this.currentNativeSource);
this.actions.beginDrag([this.currentNativeHandle]);
// On Firefox, if mousemove fires, the drag is over but browser failed to tell us.
// This is not true for other browsers.
if (isFirefox()) {
window.addEventListener('mousemove', this.endDragNativeItem, true);
}
};