summaryrefslogtreecommitdiff
path: root/application/palemoon/base/content/newtab/dropTargetShim.js
diff options
context:
space:
mode:
Diffstat (limited to 'application/palemoon/base/content/newtab/dropTargetShim.js')
-rw-r--r--application/palemoon/base/content/newtab/dropTargetShim.js154
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);