Wed, 31 Dec 2014 06:55:46 +0100
Added tag TORBROWSER_REPLICA for changeset 6474c204b198
1 #ifdef 0
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #endif
7 /**
8 * This singleton implements site dragging functionality.
9 */
10 let gDrag = {
11 /**
12 * The site offset to the drag start point.
13 */
14 _offsetX: null,
15 _offsetY: null,
17 /**
18 * The site that is dragged.
19 */
20 _draggedSite: null,
21 get draggedSite() this._draggedSite,
23 /**
24 * The cell width/height at the point the drag started.
25 */
26 _cellWidth: null,
27 _cellHeight: null,
28 get cellWidth() this._cellWidth,
29 get cellHeight() this._cellHeight,
31 /**
32 * Start a new drag operation.
33 * @param aSite The site that's being dragged.
34 * @param aEvent The 'dragstart' event.
35 */
36 start: function Drag_start(aSite, aEvent) {
37 this._draggedSite = aSite;
39 // Mark nodes as being dragged.
40 let selector = ".newtab-site, .newtab-control, .newtab-thumbnail";
41 let parentCell = aSite.node.parentNode;
42 let nodes = parentCell.querySelectorAll(selector);
43 for (let i = 0; i < nodes.length; i++)
44 nodes[i].setAttribute("dragged", "true");
46 parentCell.setAttribute("dragged", "true");
48 this._setDragData(aSite, aEvent);
50 // Store the cursor offset.
51 let node = aSite.node;
52 let rect = node.getBoundingClientRect();
53 this._offsetX = aEvent.clientX - rect.left;
54 this._offsetY = aEvent.clientY - rect.top;
56 // Store the cell dimensions.
57 let cellNode = aSite.cell.node;
58 this._cellWidth = cellNode.offsetWidth;
59 this._cellHeight = cellNode.offsetHeight;
61 gTransformation.freezeSitePosition(aSite);
62 },
64 /**
65 * Handles the 'drag' event.
66 * @param aSite The site that's being dragged.
67 * @param aEvent The 'drag' event.
68 */
69 drag: function Drag_drag(aSite, aEvent) {
70 // Get the viewport size.
71 let {clientWidth, clientHeight} = document.documentElement;
73 // We'll want a padding of 5px.
74 let border = 5;
76 // Enforce minimum constraints to keep the drag image inside the window.
77 let left = Math.max(scrollX + aEvent.clientX - this._offsetX, border);
78 let top = Math.max(scrollY + aEvent.clientY - this._offsetY, border);
80 // Enforce maximum constraints to keep the drag image inside the window.
81 left = Math.min(left, scrollX + clientWidth - this.cellWidth - border);
82 top = Math.min(top, scrollY + clientHeight - this.cellHeight - border);
84 // Update the drag image's position.
85 gTransformation.setSitePosition(aSite, {left: left, top: top});
86 },
88 /**
89 * Ends the current drag operation.
90 * @param aSite The site that's being dragged.
91 * @param aEvent The 'dragend' event.
92 */
93 end: function Drag_end(aSite, aEvent) {
94 let nodes = gGrid.node.querySelectorAll("[dragged]")
95 for (let i = 0; i < nodes.length; i++)
96 nodes[i].removeAttribute("dragged");
98 // Slide the dragged site back into its cell (may be the old or the new cell).
99 gTransformation.slideSiteTo(aSite, aSite.cell, {unfreeze: true});
101 this._draggedSite = null;
102 },
104 /**
105 * Checks whether we're responsible for a given drag event.
106 * @param aEvent The drag event to check.
107 * @return Whether we should handle this drag and drop operation.
108 */
109 isValid: function Drag_isValid(aEvent) {
110 let link = gDragDataHelper.getLinkFromDragEvent(aEvent);
112 // Check that the drag data is non-empty.
113 // Can happen when dragging places folders.
114 if (!link || !link.url) {
115 return false;
116 }
118 // Check that we're not accepting URLs which would inherit the caller's
119 // principal (such as javascript: or data:).
120 return gLinkChecker.checkLoadURI(link.url);
121 },
123 /**
124 * Initializes the drag data for the current drag operation.
125 * @param aSite The site that's being dragged.
126 * @param aEvent The 'dragstart' event.
127 */
128 _setDragData: function Drag_setDragData(aSite, aEvent) {
129 let {url, title} = aSite;
131 let dt = aEvent.dataTransfer;
132 dt.mozCursor = "default";
133 dt.effectAllowed = "move";
134 dt.setData("text/plain", url);
135 dt.setData("text/uri-list", url);
136 dt.setData("text/x-moz-url", url + "\n" + title);
137 dt.setData("text/html", "<a href=\"" + url + "\">" + url + "</a>");
139 // Create and use an empty drag element. We don't want to use the default
140 // drag image with its default opacity.
141 let dragElement = document.createElementNS(HTML_NAMESPACE, "div");
142 dragElement.classList.add("newtab-drag");
143 let scrollbox = document.getElementById("newtab-scrollbox");
144 scrollbox.appendChild(dragElement);
145 dt.setDragImage(dragElement, 0, 0);
147 // After the 'dragstart' event has been processed we can remove the
148 // temporary drag element from the DOM.
149 setTimeout(function () scrollbox.removeChild(dragElement), 0);
150 }
151 };