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

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

Issue 15643006: Files.app: Added DragSelector class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments. Created 7 years, 6 months 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 (c) 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_ = null;
yoshiki 2013/06/04 01:16:01 nit: I think it is better to assign '[]' instead o
hirono 2013/06/04 02:16:10 Done.
47
48 /**
49 * Indexes of selected items at the start of dragging.
50 * @type {Array.<number>}
51 * @private
52 */
53 this.originalSelection_ = null;
yoshiki 2013/06/04 01:16:01 ditto
hirono 2013/06/04 02:16:10 Done.
54
55 // Bind handlers to make them removable.
56 this.onMouseMoveBound_ = this.onMouseMove_.bind(this);
57 this.onMouseUpBound_ = this.onMouseUp_.bind(this);
58 }
59
60 /**
61 * Flag that shows whether the item is included in the selection or not.
62 * @enum {number}
63 * @private
64 */
65 DragSelector.SelectionFlag_ = {
66 IN_LAST_SELECTION: 1 << 0,
67 IN_CURRENT_SELECTION: 1 << 1
68 };
69
70 /**
71 * Starts drag selection by reacting dragstart event.
72 * This function must be called from handlers of dragstart event.
73 *
74 * @this {DragSelector}
75 * @param {cr.ui.List} list List where the drag selection starts.
76 * @param {Event} event The dragstart event.
77 */
78 DragSelector.prototype.startDragSelection = function(list, event) {
79 // Precondition check
80 if (!list.selectionModel_.multiple || this.target_)
81 return;
82
83 // Set the target of the drag selection
84 this.target_ = list;
85
86 // Create and add the border element
87 if (!this.border_) {
88 this.border_ = this.target_.ownerDocument.createElement('div');
89 this.border_.className = 'drag-selection-border';
90 }
91 list.appendChild(this.border_);
92
93 // Prevent default action.
94 event.preventDefault();
95
96 // If no modifier key is pressed, clear the original selection.
97 if (!event.shiftKey && !event.ctrlKey) {
98 this.target_.selectionModel_.unselectAll();
99 }
100
101 // Save the start state.
102 var rect = list.getBoundingClientRect();
103 this.startX_ = event.clientX - rect.left + list.scrollLeft;
104 this.startY_ = event.clientY - rect.top + list.scrollTop;
105 this.border_.style.left = this.startX_ + 'px';
106 this.border_.style.top = this.startY_ + 'px';
107 this.lastSelection_ = [];
108 this.originalSelection_ = this.target_.selectionModel_.selectedIndexes;
109
110 // Register event handlers.
111 // The handlers are bounded at the constructor.
112 this.target_.ownerDocument.addEventListener(
113 'mousemove', this.onMouseMoveBound_, true);
114 this.target_.ownerDocument.addEventListener(
115 'mouseup', this.onMouseUpBound_, true);
116 };
117
118 /**
119 * Handle the mousemove event.
120 * @private
121 * @param {MouseEvent} event The mousemove event.
122 */
123 DragSelector.prototype.onMouseMove_ = function(event) {
124 // Get the selection bounds.
125 var inRect = this.target_.getBoundingClientRect();
126 var x = event.clientX - inRect.left + this.target_.scrollLeft;
127 var y = event.clientY - inRect.top + this.target_.scrollTop;
128 var borderBounds = {
129 left: Math.max(Math.min(this.startX_, x), 0),
130 top: Math.max(Math.min(this.startY_, y), 0),
131 right: Math.min(Math.max(this.startX_, x), this.target_.scrollWidth),
132 bottom: Math.min(Math.max(this.startY_, y), this.target_.scrollHeight)
133 };
134 borderBounds.width = borderBounds.right - borderBounds.left;
135 borderBounds.height = borderBounds.bottom - borderBounds.top;
136 this.border_.style.left = borderBounds.left + 'px';
137 this.border_.style.top = borderBounds.top + 'px';
138 this.border_.style.width = borderBounds.width + 'px';
139 this.border_.style.height = borderBounds.height + 'px';
140
141 // Collect items within the selection rect.
142 var currentSelection = [];
143 var leadIndex = -1;
144 for (var i = 0; i < this.target_.selectionModel_.length; i++) {
145 var itemMetrics = this.target_.getHeightsForIndex_(i);
yoshiki 2013/06/04 01:16:01 getHeightsForIndex_() is private. Please make it p
yoshiki 2013/06/04 01:50:42 Sorry, I was wrong. I did grep 'getHeightForIndex_
hirono 2013/06/04 02:16:10 I added a TODO comment.
146 itemMetrics.bottom = itemMetrics.top + itemMetrics.height;
147 if (itemMetrics.top < borderBounds.bottom &&
148 itemMetrics.bottom >= borderBounds.top) {
149 currentSelection.push(i);
150 }
151 var pointed = itemMetrics.top <= y && y < itemMetrics.bottom;
152 if (pointed)
153 leadIndex = i;
154 }
155
156 // Diff the selection between currentSelection and this.lastSelection_.
157 var selectionFlag = [];
158 for (var i = 0; i < this.lastSelection_.length; i++) {
159 var index = this.lastSelection_[i];
160 // Bit operator can be used for undefined value.
161 selectionFlag[index] =
162 selectionFlag[index] | DragSelector.SelectionFlag_.IN_LAST_SELECTION;
163 }
164 for (var i = 0; i < currentSelection.length; i++) {
165 var index = currentSelection[i];
166 // Bit operator can be used for undefined value.
167 selectionFlag[index] =
168 selectionFlag[index] | DragSelector.SelectionFlag_.IN_CURRENT_SELECTION;
169 }
170
171 // Update the selection
172 this.target_.selectionModel_.beginChange();
173 for (var name in selectionFlag) {
174 var index = parseInt(name);
175 var flag = selectionFlag[name];
176 // flag may be one of followings:
mtomasz 2013/06/04 01:01:21 nit: flag -> Flag / The flag
hirono 2013/06/04 01:08:08 Done.
177 // - IN_LAST_SELECTION | IN_CURRENT_SELECTION
178 // - IN_LAST_SELECTION
179 // - IN_CURRENT_SELECTION
180 // - undefined
181
182 // If flag equals to (IN_LAST_SELECTION | IN_CURRENT_SELECTION),
mtomasz 2013/06/04 01:01:21 nit: flag -> the flag
hirono 2013/06/04 01:08:08 Done.
183 // this is included in both the last selection and the current selection.
mtomasz 2013/06/04 01:01:21 nit: this -> then this item / then the item
hirono 2013/06/04 01:08:08 Done.
184 // We have nothing to do for this item.
185
186 if (flag == DragSelector.SelectionFlag_.IN_LAST_SELECTION) {
187 // If flag equals to IN_LAST_SELECTION,
mtomasz 2013/06/04 01:01:21 nit: flag -> the flag
hirono 2013/06/04 01:08:08 Done.
188 // this is included in lastSelection but not in currentSelection.
189 // Revert the selection state to this.originalSelection_.
190 this.target_.selectionModel_.setIndexSelected(
191 index, this.originalSelection_.indexOf(index) != -1);
192 } else if (flag == DragSelector.SelectionFlag_.IN_CURRENT_SELECTION) {
193 // If flag equals to IN_CURRENT_SELECTION,
194 // this is included in currentSelection but no in lastSelection.
mtomasz 2013/06/04 01:01:21 nit: no in -> not in
hirono 2013/06/04 01:08:08 Done.
195 this.target_.selectionModel_.setIndexSelected(index, true);
196 }
197 }
198 if (leadIndex != -1) {
199 this.target_.selectionModel_.leadIndex = leadIndex;
200 this.target_.selectionModel_.anchorIndex = leadIndex;
201 }
202 this.target_.selectionModel_.endChange();
203 this.lastSelection_ = currentSelection;
204 };
205
206 /**
207 * Handle the mouseup event.
208 * @private
209 * @param {MouseEvent} event The mouseup event.
210 */
211 DragSelector.prototype.onMouseUp_ = function(event) {
212 this.onMouseMove_(event);
213 this.target_.removeChild(this.border_);
214 this.target_.ownerDocument.removeEventListener(
215 'mousemove', this.onMouseMoveBound_, true);
216 this.target_.ownerDocument.removeEventListener(
217 'mouseup', this.onMouseUpBound_, true);
218 event.stopPropagation();
219 this.target_ = null;
220 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/file_manager/css/file_manager.css ('k') | chrome/browser/resources/file_manager/js/main_scripts.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698