OLD | NEW |
---|---|
(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 * @private | |
16 * @type {cr.ui.list?} | |
mtomasz
2013/05/31 08:15:31
Shouldn't be list? -> List
hirono
2013/06/03 04:40:33
Done.
| |
17 */ | |
18 this.target_ = null; | |
19 | |
20 /** | |
21 * Border element of drag handle. | |
22 * @private | |
mtomasz
2013/05/31 08:15:31
@private after @type
hirono
2013/06/03 04:40:33
Done.
| |
23 * @type {HtmlElement?} | |
mtomasz
2013/05/31 08:15:31
Isn't '?' redundant? Objects do not need ? for nul
hirono
2013/06/03 04:40:33
Done.
| |
24 */ | |
25 this.border_ = null; | |
26 | |
27 /** | |
28 * Start point of dragging. | |
29 * @private | |
30 * @type {number?} | |
31 */ | |
32 this.startX_ = null; | |
33 | |
34 /** | |
35 * Start point of dragging. | |
36 * @private | |
37 * @type {number?} | |
mtomasz
2013/05/31 08:15:31
For example, here ? is necessary, since it is not
hirono
2013/06/03 04:40:33
Done.
| |
38 */ | |
39 this.startY_ = null; | |
40 | |
41 /** | |
42 * Indexes of selected items by dragging at the last update. | |
43 * @private | |
44 * @type {Array.<number>?} | |
45 */ | |
46 this.lastSelection_ = null; | |
47 | |
48 /** | |
49 * Indexes of selected items at the start of dragging. | |
50 * @private | |
51 * @type {Array.<number>?} | |
52 */ | |
53 this.originalSelection_ = null; | |
54 | |
55 // Bind handlers to make them removable. | |
56 this.onMouseMove_ = DragSelector.prototype.onMouseMove_.bind(this); | |
mtomasz
2013/05/31 08:15:31
This looks tricky. For that we use:
this.onMouseMo
hirono
2013/06/03 04:40:33
Done.
| |
57 this.onMouseUp_ = DragSelector.prototype.onMouseUp_.bind(this); | |
58 } | |
59 | |
60 /** | |
61 * Starts drag selection by reacting dragstart event. | |
62 * This function must be called from handlers of dragstart event. | |
mtomasz
2013/05/31 08:15:31
When @jsdoc is long, you may want to add an empty
hirono
2013/06/03 04:40:33
Done.
| |
63 * @this {DragSelector} | |
64 * @param {cr.ui.list} list List where the drag selection starts. | |
65 * @param {Event} event The dragstart event. | |
66 */ | |
67 DragSelector.prototype.startDragSelection = function(list, event) { | |
68 // Precondition check | |
69 if (!list.selectionModel_.multiple || this.target_) | |
70 return; | |
71 // Set the target of drag selection | |
mtomasz
2013/05/31 08:15:31
of -> of the
hirono
2013/06/03 04:40:33
Done.
| |
72 this.target_ = list; | |
mtomasz
2013/05/31 08:15:31
Please add empty lines in large blocks of code for
hirono
2013/06/03 04:40:33
Done.
| |
73 // Create and add the border element | |
74 if (!this.border_) { | |
75 this.border_ = this.target_.ownerDocument.createElement('div'); | |
76 this.border_.className = 'drag-selection-border'; | |
77 } | |
78 list.appendChild(this.border_); | |
79 // Prevent default action | |
mtomasz
2013/05/31 08:15:31
Add periods at the end of sentences.
hirono
2013/06/03 04:40:33
Done.
| |
80 event.preventDefault(); | |
81 // Handle modifier keys. | |
mtomasz
2013/05/31 08:15:31
Please change to more descriptive comment, eg. wha
hirono
2013/06/03 04:40:33
Done.
| |
82 if (!event.modifiers & Event.SHIFT_MASK && | |
mtomasz
2013/05/31 08:15:31
Does it work as intended? I can start selection us
hirono
2013/06/03 04:40:33
These modifier keys just specified that this selec
| |
83 !event.modifiers & Event.CONTROL_MASK) { | |
84 this.target_.selectionModel_.unselectAll(); | |
85 } | |
86 // Save the start state. | |
87 var rect = list.getBoundingClientRect(); | |
88 this.startX_ = event.clientX - rect.left + list.scrollLeft; | |
89 this.startY_ = event.clientY - rect.top + list.scrollTop; | |
90 this.border_.style.left = this.startX_ + 'px'; | |
91 this.border_.style.top = this.startY_ + 'px'; | |
92 this.lastSelection_ = []; | |
93 this.originalSelection_ = this.target_.selectionModel_.selectedIndexes; | |
94 // Register evnet handlers. | |
95 // The handlers are bounded at the constructor. | |
96 this.target_.ownerDocument.addEventListener( | |
97 'mousemove', this.onMouseMove_, true); | |
98 this.target_.ownerDocument.addEventListener( | |
99 'mouseup', this.onMouseUp_, true); | |
100 }; | |
101 | |
102 /** | |
103 * Handle the mousemove evnet. | |
mtomasz
2013/05/31 08:15:31
evnet -> event
hirono
2013/06/03 04:40:33
Done.
| |
104 * @private | |
105 * @param {MouseEvent} event The mousemove event. | |
106 */ | |
107 DragSelector.prototype.onMouseMove_ = function(event) { | |
108 // Get current selection and leadIndex from geometry. | |
109 var inRect = this.target_.getBoundingClientRect(); | |
110 var x = event.clientX - inRect.left + this.target_.scrollLeft; | |
111 var y = event.clientY - inRect.top + this.target_.scrollTop; | |
112 var borderMetrics = { | |
mtomasz
2013/05/31 08:15:31
Metrics -> Bounds / Rect / Geometry?
(optional) bo
hirono
2013/06/03 04:40:33
Done.
| |
113 left: Math.max(Math.min(this.startX_, x), 0), | |
114 top: Math.max(Math.min(this.startY_, y), 0), | |
115 right: Math.min(Math.max(this.startX_, x), this.target_.scrollWidth), | |
116 bottom: Math.min(Math.max(this.startY_, y), this.target_.scrollHeight) | |
117 }; | |
118 borderMetrics.width = borderMetrics.right - borderMetrics.left; | |
119 borderMetrics.height = borderMetrics.bottom - borderMetrics.top; | |
120 this.border_.style.left = borderMetrics.left + 'px'; | |
121 this.border_.style.top = borderMetrics.top + 'px'; | |
122 this.border_.style.width = borderMetrics.width + 'px'; | |
123 this.border_.style.height = borderMetrics.height + 'px'; | |
124 var currentSelection = []; | |
125 var leadIndex = -1; | |
mtomasz
2013/05/31 08:15:31
Can we add a comment, eg. Collect items within the
hirono
2013/06/03 04:40:33
Done.
| |
126 for (var i = 0; i < this.target_.selectionModel_.length; i++) { | |
127 var itemMetrics = this.target_.getHeightsForIndex_(i); | |
128 itemMetrics.bottom = itemMetrics.top + itemMetrics.height; | |
129 if (itemMetrics.top < borderMetrics.bottom && | |
130 itemMetrics.bottom >= borderMetrics.top) { | |
131 currentSelection.push(i); | |
132 } | |
133 var pointed = itemMetrics.top <= y && y < itemMetrics.bottom; | |
134 if (pointed) | |
135 leadIndex = i; | |
136 } | |
137 // Diff the selection between currentSelection and this.lastSelection_. | |
138 var selectionFlag = []; | |
139 for (var i = 0; i < this.lastSelection_.length; i++) { | |
140 var index = this.lastSelection_[i]; | |
141 // Bit operator can be used for undefined value. | |
142 selectionFlag[index] = selectionFlag[index] | 1; | |
mtomasz
2013/05/31 08:15:31
1, 2 -> enum?
hirono
2013/06/03 04:40:33
Done.
| |
143 } | |
144 for (var i = 0; i < currentSelection.length; i++) { | |
145 var index = currentSelection[i]; | |
146 // Bit operator can be used for undefined value. | |
147 selectionFlag[index] = selectionFlag[index] | 2; | |
148 } | |
149 // Update selection | |
mtomasz
2013/05/31 08:15:31
selection -> the selection
hirono
2013/06/03 04:40:33
Done.
| |
150 this.target_.selectionModel_.beginChange(); | |
151 for (var name in selectionFlag) { | |
152 var index = parseInt(name); | |
mtomasz
2013/05/31 08:15:31
Is parseInt necessary here?
hirono
2013/06/03 04:40:33
Yes, actually, I had used the name directly at fir
| |
153 var flag = selectionFlag[name]; | |
154 if (flag == 1) { | |
155 // This is included in lastSelection but currentSelection. | |
156 // Revert the selection state to this.originalSelection_. | |
157 this.target_.selectionModel_.setIndexSelected( | |
158 index, this.originalSelection_.indexOf(index) != -1); | |
159 } else if (flag == 2) { | |
160 // This is included in currentSelection but lastSelection. | |
161 this.target_.selectionModel_.setIndexSelected(index, true); | |
162 } | |
163 } | |
164 this.target_.selectionModel_.leadIndex = leadIndex; | |
165 this.target_.selectionModel_.anchorIndex = leadIndex; | |
166 this.target_.selectionModel_.endChange(); | |
167 this.lastSelection_ = currentSelection; | |
168 }; | |
169 | |
170 /** | |
171 * Handle the mouseup event. | |
172 * @private | |
173 * @param {MouseEvent} event The mouseup event. | |
174 */ | |
175 DragSelector.prototype.onMouseUp_ = function(event) { | |
176 this.onMouseMove_(event); | |
177 this.target_.removeChild(this.border_); | |
178 this.target_.ownerDocument.removeEventListener( | |
179 'mousemove', this.onMouseMove_, true); | |
180 this.target_.ownerDocument.removeEventListener( | |
181 'mouseup', this.onMouseUp_, true); | |
182 event.stopPropagation(); | |
183 this.target_ = null; | |
184 }; | |
OLD | NEW |