Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 // **********
6 // Title: drag.js
8 // ----------
9 // Variable: drag
10 // The Drag that's currently in process.
11 var drag = {
12 info: null,
13 zIndex: 100,
14 lastMoveTime: 0
15 };
17 //----------
18 //Variable: resize
19 //The resize (actually a Drag) that is currently in process
20 var resize = {
21 info: null,
22 lastMoveTime: 0
23 };
25 // ##########
26 // Class: Drag (formerly DragInfo)
27 // Helper class for dragging <Item>s
28 //
29 // ----------
30 // Constructor: Drag
31 // Called to create a Drag in response to an <Item> draggable "start" event.
32 // Note that it is also used partially during <Item>'s resizable method as well.
33 //
34 // Parameters:
35 // item - The <Item> being dragged
36 // event - The DOM event that kicks off the drag
37 function Drag(item, event) {
38 Utils.assert(item && (item.isAnItem || item.isAFauxItem),
39 'must be an item, or at least a faux item');
41 this.item = item;
42 this.el = item.container;
43 this.$el = iQ(this.el);
44 this.parent = this.item.parent;
45 this.startPosition = new Point(event.clientX, event.clientY);
46 this.startTime = Date.now();
48 this.item.isDragging = true;
49 this.item.setZ(999999);
51 this.safeWindowBounds = Items.getSafeWindowBounds();
53 Trenches.activateOthersTrenches(this.el);
54 };
56 Drag.prototype = {
57 // ----------
58 // Function: toString
59 // Prints [Drag (item)] for debug use
60 toString: function Drag_toString() {
61 return "[Drag (" + this.item + ")]";
62 },
64 // ----------
65 // Function: snapBounds
66 // Adjusts the given bounds according to the currently active trenches. Used by <Drag.snap>
67 //
68 // Parameters:
69 // bounds - (<Rect>) bounds
70 // stationaryCorner - which corner is stationary? by default, the top left in LTR mode,
71 // and top right in RTL mode.
72 // "topleft", "bottomleft", "topright", "bottomright"
73 // assumeConstantSize - (boolean) whether the bounds' dimensions are sacred or not.
74 // keepProportional - (boolean) if assumeConstantSize is false, whether we should resize
75 // proportionally or not
76 // checkItemStatus - (boolean) make sure this is a valid item which should be snapped
77 snapBounds: function Drag_snapBounds(bounds, stationaryCorner, assumeConstantSize, keepProportional, checkItemStatus) {
78 if (!stationaryCorner)
79 stationaryCorner = UI.rtl ? 'topright' : 'topleft';
80 var update = false; // need to update
81 var updateX = false;
82 var updateY = false;
83 var newRect;
84 var snappedTrenches = {};
86 // OH SNAP!
88 // if we aren't holding down the meta key or have trenches disabled...
89 if (!Keys.meta && !Trenches.disabled) {
90 // snappable = true if we aren't a tab on top of something else, and
91 // there's no active drop site...
92 let snappable = !(this.item.isATabItem &&
93 this.item.overlapsWithOtherItems()) &&
94 !iQ(".acceptsDrop").length;
95 if (!checkItemStatus || snappable) {
96 newRect = Trenches.snap(bounds, stationaryCorner, assumeConstantSize,
97 keepProportional);
98 if (newRect) { // might be false if no changes were made
99 update = true;
100 snappedTrenches = newRect.snappedTrenches || {};
101 bounds = newRect;
102 }
103 }
104 }
106 // make sure the bounds are in the window.
107 newRect = this.snapToEdge(bounds, stationaryCorner, assumeConstantSize,
108 keepProportional);
109 if (newRect) {
110 update = true;
111 bounds = newRect;
112 Utils.extend(snappedTrenches, newRect.snappedTrenches);
113 }
115 Trenches.hideGuides();
116 for (var edge in snappedTrenches) {
117 var trench = snappedTrenches[edge];
118 if (typeof trench == 'object') {
119 trench.showGuide = true;
120 trench.show();
121 }
122 }
124 return update ? bounds : false;
125 },
127 // ----------
128 // Function: snap
129 // Called when a drag or mousemove occurs. Set the bounds based on the mouse move first, then
130 // call snap and it will adjust the item's bounds if appropriate. Also triggers the display of
131 // trenches that it snapped to.
132 //
133 // Parameters:
134 // stationaryCorner - which corner is stationary? by default, the top left in LTR mode,
135 // and top right in RTL mode.
136 // "topleft", "bottomleft", "topright", "bottomright"
137 // assumeConstantSize - (boolean) whether the bounds' dimensions are sacred or not.
138 // keepProportional - (boolean) if assumeConstantSize is false, whether we should resize
139 // proportionally or not
140 snap: function Drag_snap(stationaryCorner, assumeConstantSize, keepProportional) {
141 var bounds = this.item.getBounds();
142 bounds = this.snapBounds(bounds, stationaryCorner, assumeConstantSize, keepProportional, true);
143 if (bounds) {
144 this.item.setBounds(bounds, true);
145 return true;
146 }
147 return false;
148 },
150 // --------
151 // Function: snapToEdge
152 // Returns a version of the bounds snapped to the edge if it is close enough. If not,
153 // returns false. If <Keys.meta> is true, this function will simply enforce the
154 // window edges.
155 //
156 // Parameters:
157 // rect - (<Rect>) current bounds of the object
158 // stationaryCorner - which corner is stationary? by default, the top left in LTR mode,
159 // and top right in RTL mode.
160 // "topleft", "bottomleft", "topright", "bottomright"
161 // assumeConstantSize - (boolean) whether the rect's dimensions are sacred or not
162 // keepProportional - (boolean) if we are allowed to change the rect's size, whether the
163 // dimensions should scaled proportionally or not.
164 snapToEdge: function Drag_snapToEdge(rect, stationaryCorner, assumeConstantSize, keepProportional) {
166 var swb = this.safeWindowBounds;
167 var update = false;
168 var updateX = false;
169 var updateY = false;
170 var snappedTrenches = {};
172 var snapRadius = (Keys.meta ? 0 : Trenches.defaultRadius);
173 if (rect.left < swb.left + snapRadius ) {
174 if (stationaryCorner.indexOf('right') > -1 && !assumeConstantSize)
175 rect.width = rect.right - swb.left;
176 rect.left = swb.left;
177 update = true;
178 updateX = true;
179 snappedTrenches.left = 'edge';
180 }
182 if (rect.right > swb.right - snapRadius) {
183 if (updateX || !assumeConstantSize) {
184 var newWidth = swb.right - rect.left;
185 if (keepProportional)
186 rect.height = rect.height * newWidth / rect.width;
187 rect.width = newWidth;
188 update = true;
189 } else if (!updateX || !Trenches.preferLeft) {
190 rect.left = swb.right - rect.width;
191 update = true;
192 }
193 snappedTrenches.right = 'edge';
194 delete snappedTrenches.left;
195 }
196 if (rect.top < swb.top + snapRadius) {
197 if (stationaryCorner.indexOf('bottom') > -1 && !assumeConstantSize)
198 rect.height = rect.bottom - swb.top;
199 rect.top = swb.top;
200 update = true;
201 updateY = true;
202 snappedTrenches.top = 'edge';
203 }
204 if (rect.bottom > swb.bottom - snapRadius) {
205 if (updateY || !assumeConstantSize) {
206 var newHeight = swb.bottom - rect.top;
207 if (keepProportional)
208 rect.width = rect.width * newHeight / rect.height;
209 rect.height = newHeight;
210 update = true;
211 } else if (!updateY || !Trenches.preferTop) {
212 rect.top = swb.bottom - rect.height;
213 update = true;
214 }
215 snappedTrenches.top = 'edge';
216 delete snappedTrenches.bottom;
217 }
219 if (update) {
220 rect.snappedTrenches = snappedTrenches;
221 return rect;
222 }
223 return false;
224 },
226 // ----------
227 // Function: drag
228 // Called in response to an <Item> draggable "drag" event.
229 drag: function Drag_drag(event) {
230 this.snap(UI.rtl ? 'topright' : 'topleft', true);
232 if (this.parent && this.parent.expanded) {
233 var distance = this.startPosition.distance(new Point(event.clientX, event.clientY));
234 if (distance > 100) {
235 this.parent.remove(this.item);
236 this.parent.collapse();
237 }
238 }
239 },
241 // ----------
242 // Function: stop
243 // Called in response to an <Item> draggable "stop" event.
244 //
245 // Parameters:
246 // immediately - bool for doing the pushAway immediately, without animation
247 stop: function Drag_stop(immediately) {
248 Trenches.hideGuides();
249 this.item.isDragging = false;
251 if (this.parent && this.parent != this.item.parent)
252 this.parent.closeIfEmpty();
254 if (this.parent && this.parent.expanded)
255 this.parent.arrange();
257 if (this.item.parent)
258 this.item.parent.arrange();
260 if (this.item.isAGroupItem) {
261 this.item.setZ(drag.zIndex);
262 drag.zIndex++;
264 this.item.pushAway(immediately);
265 }
267 Trenches.disactivate();
268 }
269 };