diff options
Diffstat (limited to 'application/palemoon/base/content/newtab/dropTargetShim.js')
-rw-r--r-- | application/palemoon/base/content/newtab/dropTargetShim.js | 154 |
1 files changed, 99 insertions, 55 deletions
diff --git a/application/palemoon/base/content/newtab/dropTargetShim.js b/application/palemoon/base/content/newtab/dropTargetShim.js index 046dbea1eb..57a97fa00a 100644 --- a/application/palemoon/base/content/newtab/dropTargetShim.js +++ b/application/palemoon/base/content/newtab/dropTargetShim.js @@ -23,27 +23,53 @@ var gDropTargetShim = { /** * Initializes the drop target shim. */ - init: function DropTargetShim_init() { - let node = gGrid.node; + init: function () { + gGrid.node.addEventListener("dragstart", this, true); + }, + + /** + * Add all event listeners needed during a drag operation. + */ + _addEventListeners: function () { + gGrid.node.addEventListener("dragend", this); - // Add drag event handlers. - node.addEventListener("dragstart", this, true); - node.addEventListener("dragend", this, true); + let docElement = document.documentElement; + docElement.addEventListener("dragover", this); + docElement.addEventListener("dragenter", this); + docElement.addEventListener("drop", this); + }, + + /** + * Remove all event listeners that were needed during a drag operation. + */ + _removeEventListeners: function () { + gGrid.node.removeEventListener("dragend", this); + + let docElement = document.documentElement; + docElement.removeEventListener("dragover", this); + docElement.removeEventListener("dragenter", this); + docElement.removeEventListener("drop", this); }, /** * Handles all shim events. */ - handleEvent: function DropTargetShim_handleEvent(aEvent) { + handleEvent: function (aEvent) { switch (aEvent.type) { case "dragstart": - this._start(aEvent); + this._dragstart(aEvent); + break; + case "dragenter": + aEvent.preventDefault(); break; case "dragover": this._dragover(aEvent); break; + case "drop": + this._drop(aEvent); + break; case "dragend": - this._end(aEvent); + this._dragend(aEvent); break; } }, @@ -52,69 +78,63 @@ var gDropTargetShim = { * Handles the 'dragstart' event. * @param aEvent The 'dragstart' event. */ - _start: function DropTargetShim_start(aEvent) { + _dragstart: function (aEvent) { if (aEvent.target.classList.contains("newtab-link")) { gGrid.lock(); - - // XXX bug 505521 - Listen for dragover on the document. - document.documentElement.addEventListener("dragover", this, false); + this._addEventListeners(); } }, /** - * Handles the 'drag' event and determines the current drop target. - * @param aEvent The 'drag' event. + * Handles the 'dragover' event. + * @param aEvent The 'dragover' event. */ - _drag: function DropTargetShim_drag(aEvent) { - // Let's see if we find a drop target. - let target = this._findDropTarget(aEvent); - - if (target != this._lastDropTarget) { - if (this._lastDropTarget) - // We left the last drop target. - this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget); - - if (target) - // We're now hovering a (new) drop target. - this._dispatchEvent(aEvent, "dragenter", target); + _dragover: function (aEvent) { + // XXX bug 505521 - Use the dragover event to retrieve the + // current mouse coordinates while dragging. + let sourceNode = aEvent.dataTransfer.mozSourceNode.parentNode; + gDrag.drag(sourceNode._newtabSite, aEvent); - if (this._lastDropTarget) - // We left the last drop target. - this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget); + // Find the current drop target, if there's one. + this._updateDropTarget(aEvent); - this._lastDropTarget = target; + // If we have a valid drop target, + // let the drag-and-drop service know. + if (this._lastDropTarget) { + aEvent.preventDefault(); } }, /** - * Handles the 'dragover' event as long as bug 505521 isn't fixed to get - * current mouse cursor coordinates while dragging. - * @param aEvent The 'dragover' event. + * Handles the 'drop' event. + * @param aEvent The 'drop' event. */ - _dragover: function DropTargetShim_dragover(aEvent) { - let sourceNode = aEvent.dataTransfer.mozSourceNode.parentNode; - gDrag.drag(sourceNode._newtabSite, aEvent); + _drop: function (aEvent) { + // We're accepting all drops. + aEvent.preventDefault(); - this._drag(aEvent); + // remember that drop event was seen, this explicitly + // assumes that drop event preceeds dragend event + this._dropSeen = true; + + // Make sure to determine the current drop target + // in case the dragover event hasn't been fired. + this._updateDropTarget(aEvent); + + // A site was successfully dropped. + this._dispatchEvent(aEvent, "drop", this._lastDropTarget); }, /** * Handles the 'dragend' event. * @param aEvent The 'dragend' event. */ - _end: function DropTargetShim_end(aEvent) { - // Make sure to determine the current drop target in case the dragenter - // event hasn't been fired. - this._drag(aEvent); - + _dragend: function (aEvent) { if (this._lastDropTarget) { - if (aEvent.dataTransfer.mozUserCancelled) { - // The drag operation was cancelled. + if (aEvent.dataTransfer.mozUserCancelled || !this._dropSeen) { + // The drag operation was cancelled or no drop event was generated this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget); this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget); - } else { - // A site was successfully dropped. - this._dispatchEvent(aEvent, "drop", this._lastDropTarget); } // Clean up. @@ -122,10 +142,35 @@ var gDropTargetShim = { this._cellPositions = null; } + this._dropSeen = false; gGrid.unlock(); + this._removeEventListeners(); + }, - // XXX bug 505521 - Remove the document's dragover listener. - document.documentElement.removeEventListener("dragover", this, false); + /** + * Tries to find the current drop target and will fire + * appropriate dragenter, dragexit, and dragleave events. + * @param aEvent The current drag event. + */ + _updateDropTarget: function (aEvent) { + // Let's see if we find a drop target. + let target = this._findDropTarget(aEvent); + + if (target != this._lastDropTarget) { + if (this._lastDropTarget) + // We left the last drop target. + this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget); + + if (target) + // We're now hovering a (new) drop target. + this._dispatchEvent(aEvent, "dragenter", target); + + if (this._lastDropTarget) + // We left the last drop target. + this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget); + + this._lastDropTarget = target; + } }, /** @@ -133,7 +178,7 @@ var gDropTargetShim = { * against all cells in the grid. * @return The currently hovered drop target or null. */ - _findDropTarget: function DropTargetShim_findDropTarget() { + _findDropTarget: function () { // These are the minimum intersection values - we want to use the cell if // the site is >= 50% hovering its position. let minWidth = gDrag.cellWidth / 2; @@ -174,13 +219,12 @@ var gDropTargetShim = { * @param aType The event type. * @param aTarget The target node that receives the event. */ - _dispatchEvent: - function DropTargetShim_dispatchEvent(aEvent, aType, aTarget) { - + _dispatchEvent: function (aEvent, aType, aTarget) { let node = aTarget.node; - let event = document.createEvent("DragEvents"); + let event = document.createEvent("DragEvent"); - event.initDragEvent(aType, true, true, window, 0, 0, 0, 0, 0, false, false, + // The event should not bubble to prevent recursion. + event.initDragEvent(aType, false, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, node, aEvent.dataTransfer); node.dispatchEvent(event); |