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

Unified 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: Created 7 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/file_manager/js/drag_selector.js
diff --git a/chrome/browser/resources/file_manager/js/drag_selector.js b/chrome/browser/resources/file_manager/js/drag_selector.js
new file mode 100644
index 0000000000000000000000000000000000000000..8797719b352ecff72517b290ec30fe67780a2d78
--- /dev/null
+++ b/chrome/browser/resources/file_manager/js/drag_selector.js
@@ -0,0 +1,184 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/**
+ * Drag selector used on the file list or the grid table.
+ * TODO(hirono): Support drag selection for grid view. crbug.com/224832
+ * @constructor
+ */
+function DragSelector() {
+ /**
+ * Target list of drag selection.
+ * @private
+ * @type {cr.ui.list?}
mtomasz 2013/05/31 08:15:31 Shouldn't be list? -> List
hirono 2013/06/03 04:40:33 Done.
+ */
+ this.target_ = null;
+
+ /**
+ * Border element of drag handle.
+ * @private
mtomasz 2013/05/31 08:15:31 @private after @type
hirono 2013/06/03 04:40:33 Done.
+ * @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.
+ */
+ this.border_ = null;
+
+ /**
+ * Start point of dragging.
+ * @private
+ * @type {number?}
+ */
+ this.startX_ = null;
+
+ /**
+ * Start point of dragging.
+ * @private
+ * @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.
+ */
+ this.startY_ = null;
+
+ /**
+ * Indexes of selected items by dragging at the last update.
+ * @private
+ * @type {Array.<number>?}
+ */
+ this.lastSelection_ = null;
+
+ /**
+ * Indexes of selected items at the start of dragging.
+ * @private
+ * @type {Array.<number>?}
+ */
+ this.originalSelection_ = null;
+
+ // Bind handlers to make them removable.
+ 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.
+ this.onMouseUp_ = DragSelector.prototype.onMouseUp_.bind(this);
+}
+
+/**
+ * Starts drag selection by reacting dragstart event.
+ * 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.
+ * @this {DragSelector}
+ * @param {cr.ui.list} list List where the drag selection starts.
+ * @param {Event} event The dragstart event.
+ */
+DragSelector.prototype.startDragSelection = function(list, event) {
+ // Precondition check
+ if (!list.selectionModel_.multiple || this.target_)
+ return;
+ // Set the target of drag selection
mtomasz 2013/05/31 08:15:31 of -> of the
hirono 2013/06/03 04:40:33 Done.
+ 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.
+ // Create and add the border element
+ if (!this.border_) {
+ this.border_ = this.target_.ownerDocument.createElement('div');
+ this.border_.className = 'drag-selection-border';
+ }
+ list.appendChild(this.border_);
+ // 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.
+ event.preventDefault();
+ // 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.
+ 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
+ !event.modifiers & Event.CONTROL_MASK) {
+ this.target_.selectionModel_.unselectAll();
+ }
+ // Save the start state.
+ var rect = list.getBoundingClientRect();
+ this.startX_ = event.clientX - rect.left + list.scrollLeft;
+ this.startY_ = event.clientY - rect.top + list.scrollTop;
+ this.border_.style.left = this.startX_ + 'px';
+ this.border_.style.top = this.startY_ + 'px';
+ this.lastSelection_ = [];
+ this.originalSelection_ = this.target_.selectionModel_.selectedIndexes;
+ // Register evnet handlers.
+ // The handlers are bounded at the constructor.
+ this.target_.ownerDocument.addEventListener(
+ 'mousemove', this.onMouseMove_, true);
+ this.target_.ownerDocument.addEventListener(
+ 'mouseup', this.onMouseUp_, true);
+};
+
+/**
+ * Handle the mousemove evnet.
mtomasz 2013/05/31 08:15:31 evnet -> event
hirono 2013/06/03 04:40:33 Done.
+ * @private
+ * @param {MouseEvent} event The mousemove event.
+ */
+DragSelector.prototype.onMouseMove_ = function(event) {
+ // Get current selection and leadIndex from geometry.
+ var inRect = this.target_.getBoundingClientRect();
+ var x = event.clientX - inRect.left + this.target_.scrollLeft;
+ var y = event.clientY - inRect.top + this.target_.scrollTop;
+ var borderMetrics = {
mtomasz 2013/05/31 08:15:31 Metrics -> Bounds / Rect / Geometry? (optional) bo
hirono 2013/06/03 04:40:33 Done.
+ left: Math.max(Math.min(this.startX_, x), 0),
+ top: Math.max(Math.min(this.startY_, y), 0),
+ right: Math.min(Math.max(this.startX_, x), this.target_.scrollWidth),
+ bottom: Math.min(Math.max(this.startY_, y), this.target_.scrollHeight)
+ };
+ borderMetrics.width = borderMetrics.right - borderMetrics.left;
+ borderMetrics.height = borderMetrics.bottom - borderMetrics.top;
+ this.border_.style.left = borderMetrics.left + 'px';
+ this.border_.style.top = borderMetrics.top + 'px';
+ this.border_.style.width = borderMetrics.width + 'px';
+ this.border_.style.height = borderMetrics.height + 'px';
+ var currentSelection = [];
+ 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.
+ for (var i = 0; i < this.target_.selectionModel_.length; i++) {
+ var itemMetrics = this.target_.getHeightsForIndex_(i);
+ itemMetrics.bottom = itemMetrics.top + itemMetrics.height;
+ if (itemMetrics.top < borderMetrics.bottom &&
+ itemMetrics.bottom >= borderMetrics.top) {
+ currentSelection.push(i);
+ }
+ var pointed = itemMetrics.top <= y && y < itemMetrics.bottom;
+ if (pointed)
+ leadIndex = i;
+ }
+ // Diff the selection between currentSelection and this.lastSelection_.
+ var selectionFlag = [];
+ for (var i = 0; i < this.lastSelection_.length; i++) {
+ var index = this.lastSelection_[i];
+ // Bit operator can be used for undefined value.
+ selectionFlag[index] = selectionFlag[index] | 1;
mtomasz 2013/05/31 08:15:31 1, 2 -> enum?
hirono 2013/06/03 04:40:33 Done.
+ }
+ for (var i = 0; i < currentSelection.length; i++) {
+ var index = currentSelection[i];
+ // Bit operator can be used for undefined value.
+ selectionFlag[index] = selectionFlag[index] | 2;
+ }
+ // Update selection
mtomasz 2013/05/31 08:15:31 selection -> the selection
hirono 2013/06/03 04:40:33 Done.
+ this.target_.selectionModel_.beginChange();
+ for (var name in selectionFlag) {
+ 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
+ var flag = selectionFlag[name];
+ if (flag == 1) {
+ // This is included in lastSelection but currentSelection.
+ // Revert the selection state to this.originalSelection_.
+ this.target_.selectionModel_.setIndexSelected(
+ index, this.originalSelection_.indexOf(index) != -1);
+ } else if (flag == 2) {
+ // This is included in currentSelection but lastSelection.
+ this.target_.selectionModel_.setIndexSelected(index, true);
+ }
+ }
+ this.target_.selectionModel_.leadIndex = leadIndex;
+ this.target_.selectionModel_.anchorIndex = leadIndex;
+ this.target_.selectionModel_.endChange();
+ this.lastSelection_ = currentSelection;
+};
+
+/**
+ * Handle the mouseup event.
+ * @private
+ * @param {MouseEvent} event The mouseup event.
+ */
+DragSelector.prototype.onMouseUp_ = function(event) {
+ this.onMouseMove_(event);
+ this.target_.removeChild(this.border_);
+ this.target_.ownerDocument.removeEventListener(
+ 'mousemove', this.onMouseMove_, true);
+ this.target_.ownerDocument.removeEventListener(
+ 'mouseup', this.onMouseUp_, true);
+ event.stopPropagation();
+ this.target_ = null;
+};

Powered by Google App Engine
This is Rietveld 408576698