Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: chrome/browser/resources/file_manager/js/drag_selector.js

Issue 39123003: [Files.app] Split the JavaScript files into subdirectories: common, background, and foreground (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed test failure. Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 /**
8 * Drag selector used on the file list or the grid table.
9 * TODO(hirono): Support drag selection for grid view. crbug.com/224832
10 * @constructor
11 */
12 function DragSelector() {
13 /**
14 * Target list of drag selection.
15 * @type {cr.ui.List}
16 * @private
17 */
18 this.target_ = null;
19
20 /**
21 * Border element of drag handle.
22 * @type {HtmlElement}
23 * @private
24 */
25 this.border_ = null;
26
27 /**
28 * Start point of dragging.
29 * @type {number?}
30 * @private
31 */
32 this.startX_ = null;
33
34 /**
35 * Start point of dragging.
36 * @type {number?}
37 * @private
38 */
39 this.startY_ = null;
40
41 /**
42 * Indexes of selected items by dragging at the last update.
43 * @type {Array.<number>!}
44 * @private
45 */
46 this.lastSelection_ = [];
47
48 /**
49 * Indexes of selected items at the start of dragging.
50 * @type {Array.<number>!}
51 * @private
52 */
53 this.originalSelection_ = [];
54
55 // Bind handlers to make them removable.
56 this.onMouseMoveBound_ = this.onMouseMove_.bind(this);
57 this.onMouseUpBound_ = this.onMouseUp_.bind(this);
58
59 Object.seal(this);
60 }
61
62 /**
63 * Flag that shows whether the item is included in the selection or not.
64 * @enum {number}
65 * @private
66 */
67 DragSelector.SelectionFlag_ = {
68 IN_LAST_SELECTION: 1 << 0,
69 IN_CURRENT_SELECTION: 1 << 1
70 };
71
72 /**
73 * Obtains the scrolled position in the element of mouse pointer from the mouse
74 * event.
75 *
76 * @param {HTMLElement} element Element that has the scroll bars.
77 * @param {Event} event The mouse event.
78 * @return {object} Scrolled position.
79 */
80 DragSelector.getScrolledPosition = function(element, event) {
81 if (!element.cachedBounds) {
82 element.cachedBounds = element.getBoundingClientRect();
83 if (!element.cachedBounds)
84 return null;
85 }
86 var rect = element.cachedBounds;
87 return {
88 x: event.clientX - rect.left + element.scrollLeft,
89 y: event.clientY - rect.top + element.scrollTop
90 };
91 };
92
93 /**
94 * Starts drag selection by reacting dragstart event.
95 * This function must be called from handlers of dragstart event.
96 *
97 * @this {DragSelector}
98 * @param {cr.ui.List} list List where the drag selection starts.
99 * @param {Event} event The dragstart event.
100 */
101 DragSelector.prototype.startDragSelection = function(list, event) {
102 // Precondition check
103 if (!list.selectionModel_.multiple || this.target_)
104 return;
105
106 // Set the target of the drag selection
107 this.target_ = list;
108
109 // Prevent the default action.
110 event.preventDefault();
111
112 // Save the start state.
113 var startPos = DragSelector.getScrolledPosition(list, event);
114 if (!startPos)
115 return;
116 this.startX_ = startPos.x;
117 this.startY_ = startPos.y;
118 this.lastSelection_ = [];
119 this.originalSelection_ = this.target_.selectionModel_.selectedIndexes;
120
121 // Create and add the border element
122 if (!this.border_) {
123 this.border_ = this.target_.ownerDocument.createElement('div');
124 this.border_.className = 'drag-selection-border';
125 }
126 this.border_.style.left = this.startX_ + 'px';
127 this.border_.style.top = this.startY_ + 'px';
128 this.border_.style.width = '0';
129 this.border_.style.height = '0';
130 list.appendChild(this.border_);
131
132 // If no modifier key is pressed, clear the original selection.
133 if (!event.shiftKey && !event.ctrlKey)
134 this.target_.selectionModel_.unselectAll();
135
136 // Register event handlers.
137 // The handlers are bounded at the constructor.
138 this.target_.ownerDocument.addEventListener(
139 'mousemove', this.onMouseMoveBound_, true);
140 this.target_.ownerDocument.addEventListener(
141 'mouseup', this.onMouseUpBound_, true);
142 };
143
144 /**
145 * Handles the mousemove event.
146 * @private
147 * @param {MouseEvent} event The mousemove event.
148 */
149 DragSelector.prototype.onMouseMove_ = function(event) {
150 // Get the selection bounds.
151 var pos = DragSelector.getScrolledPosition(this.target_, event);
152 var borderBounds = {
153 left: Math.max(Math.min(this.startX_, pos.x), 0),
154 top: Math.max(Math.min(this.startY_, pos.y), 0),
155 right: Math.min(Math.max(this.startX_, pos.x), this.target_.scrollWidth),
156 bottom: Math.min(Math.max(this.startY_, pos.y), this.target_.scrollHeight)
157 };
158 borderBounds.width = borderBounds.right - borderBounds.left;
159 borderBounds.height = borderBounds.bottom - borderBounds.top;
160
161 // Collect items within the selection rect.
162 var currentSelection = this.target_.getHitElements(
163 borderBounds.left,
164 borderBounds.top,
165 borderBounds.width,
166 borderBounds.height);
167 var pointedElements = this.target_.getHitElements(pos.x, pos.y);
168 var leadIndex = pointedElements.length ? pointedElements[0] : -1;
169
170 // Diff the selection between currentSelection and this.lastSelection_.
171 var selectionFlag = [];
172 for (var i = 0; i < this.lastSelection_.length; i++) {
173 var index = this.lastSelection_[i];
174 // Bit operator can be used for undefined value.
175 selectionFlag[index] =
176 selectionFlag[index] | DragSelector.SelectionFlag_.IN_LAST_SELECTION;
177 }
178 for (var i = 0; i < currentSelection.length; i++) {
179 var index = currentSelection[i];
180 // Bit operator can be used for undefined value.
181 selectionFlag[index] =
182 selectionFlag[index] | DragSelector.SelectionFlag_.IN_CURRENT_SELECTION;
183 }
184
185 // Update the selection
186 this.target_.selectionModel_.beginChange();
187 for (var name in selectionFlag) {
188 var index = parseInt(name);
189 var flag = selectionFlag[name];
190 // The flag may be one of followings:
191 // - IN_LAST_SELECTION | IN_CURRENT_SELECTION
192 // - IN_LAST_SELECTION
193 // - IN_CURRENT_SELECTION
194 // - undefined
195
196 // If the flag equals to (IN_LAST_SELECTION | IN_CURRENT_SELECTION),
197 // this is included in both the last selection and the current selection.
198 // We have nothing to do for this item.
199
200 if (flag == DragSelector.SelectionFlag_.IN_LAST_SELECTION) {
201 // If the flag equals to IN_LAST_SELECTION,
202 // then the item is included in lastSelection but not in currentSelection.
203 // Revert the selection state to this.originalSelection_.
204 this.target_.selectionModel_.setIndexSelected(
205 index, this.originalSelection_.indexOf(index) != -1);
206 } else if (flag == DragSelector.SelectionFlag_.IN_CURRENT_SELECTION) {
207 // If the flag equals to IN_CURRENT_SELECTION,
208 // this is included in currentSelection but not in lastSelection.
209 this.target_.selectionModel_.setIndexSelected(index, true);
210 }
211 }
212 if (leadIndex != -1) {
213 this.target_.selectionModel_.leadIndex = leadIndex;
214 this.target_.selectionModel_.anchorIndex = leadIndex;
215 }
216 this.target_.selectionModel_.endChange();
217 this.lastSelection_ = currentSelection;
218
219 // Update the size of border
220 this.border_.style.left = borderBounds.left + 'px';
221 this.border_.style.top = borderBounds.top + 'px';
222 this.border_.style.width = borderBounds.width + 'px';
223 this.border_.style.height = borderBounds.height + 'px';
224 };
225
226 /**
227 * Handle the mouseup event.
228 * @private
229 * @param {MouseEvent} event The mouseup event.
230 */
231 DragSelector.prototype.onMouseUp_ = function(event) {
232 this.onMouseMove_(event);
233 this.target_.removeChild(this.border_);
234 this.target_.ownerDocument.removeEventListener(
235 'mousemove', this.onMouseMoveBound_, true);
236 this.target_.ownerDocument.removeEventListener(
237 'mouseup', this.onMouseUpBound_, true);
238 cr.dispatchSimpleEvent(this.target_, 'dragselectionend');
239 this.target_.cachedBounds = null;
240 this.target_ = null;
241 // The target may select an item by reacting to the mouseup event.
242 // This suppress to the selecting behavior.
243 event.stopPropagation();
244 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/file_manager/js/directory_tree.js ('k') | chrome/browser/resources/file_manager/js/drive_banners.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698