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

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: Addressed Yoshiki's 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 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..3895483ff2e7d7b5c99b82de4758c02dbcd86382
--- /dev/null
+++ b/chrome/browser/resources/file_manager/js/drag_selector.js
@@ -0,0 +1,223 @@
+// 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.
+ * @type {cr.ui.List}
+ * @private
+ */
+ this.target_ = null;
+
+ /**
+ * Border element of drag handle.
+ * @type {HtmlElement}
+ * @private
+ */
+ this.border_ = null;
+
+ /**
+ * Start point of dragging.
+ * @type {number?}
+ * @private
+ */
+ this.startX_ = null;
+
+ /**
+ * Start point of dragging.
+ * @type {number?}
+ * @private
+ */
+ this.startY_ = null;
+
+ /**
+ * Indexes of selected items by dragging at the last update.
+ * @type {Array.<number>!}
+ * @private
+ */
+ this.lastSelection_ = [];
+
+ /**
+ * Indexes of selected items at the start of dragging.
+ * @type {Array.<number>!}
+ * @private
+ */
+ this.originalSelection_ = [];
+
+ // Bind handlers to make them removable.
+ this.onMouseMoveBound_ = this.onMouseMove_.bind(this);
+ this.onMouseUpBound_ = this.onMouseUp_.bind(this);
+}
+
+/**
+ * Flag that shows whether the item is included in the selection or not.
+ * @enum {number}
+ * @private
+ */
+DragSelector.SelectionFlag_ = {
+ IN_LAST_SELECTION: 1 << 0,
+ IN_CURRENT_SELECTION: 1 << 1
+};
+
+/**
+ * Starts drag selection by reacting dragstart event.
+ * This function must be called from handlers of dragstart event.
+ *
+ * @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 the drag selection
+ this.target_ = list;
+
+ // 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.
+ event.preventDefault();
+
+ // If no modifier key is pressed, clear the original selection.
+ if (!event.shiftKey && !event.ctrlKey) {
+ 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 event handlers.
+ // The handlers are bounded at the constructor.
+ this.target_.ownerDocument.addEventListener(
+ 'mousemove', this.onMouseMoveBound_, true);
+ this.target_.ownerDocument.addEventListener(
+ 'mouseup', this.onMouseUpBound_, true);
+};
+
+/**
+ * Handle the mousemove event.
+ * @private
+ * @param {MouseEvent} event The mousemove event.
+ */
+DragSelector.prototype.onMouseMove_ = function(event) {
+ // Get the selection bounds.
+ var inRect = this.target_.getBoundingClientRect();
+ var x = event.clientX - inRect.left + this.target_.scrollLeft;
+ var y = event.clientY - inRect.top + this.target_.scrollTop;
+ var borderBounds = {
+ 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)
+ };
+ borderBounds.width = borderBounds.right - borderBounds.left;
+ borderBounds.height = borderBounds.bottom - borderBounds.top;
+
+ // Collect items within the selection rect.
+ var currentSelection = [];
+ var leadIndex = -1;
+ for (var i = 0; i < this.target_.selectionModel_.length; i++) {
+ // TODO(hirono): Stop to use the private method. crbug.com/246459
+ var itemMetrics = this.target_.getHeightsForIndex_(i);
+ itemMetrics.bottom = itemMetrics.top + itemMetrics.height;
+ if (itemMetrics.top < borderBounds.bottom &&
+ itemMetrics.bottom >= borderBounds.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] | DragSelector.SelectionFlag_.IN_LAST_SELECTION;
+ }
+ for (var i = 0; i < currentSelection.length; i++) {
+ var index = currentSelection[i];
+ // Bit operator can be used for undefined value.
+ selectionFlag[index] =
+ selectionFlag[index] | DragSelector.SelectionFlag_.IN_CURRENT_SELECTION;
+ }
+
+ // Update the selection
+ this.target_.selectionModel_.beginChange();
+ for (var name in selectionFlag) {
+ var index = parseInt(name);
+ var flag = selectionFlag[name];
+ // The flag may be one of followings:
+ // - IN_LAST_SELECTION | IN_CURRENT_SELECTION
+ // - IN_LAST_SELECTION
+ // - IN_CURRENT_SELECTION
+ // - undefined
+
+ // If the flag equals to (IN_LAST_SELECTION | IN_CURRENT_SELECTION),
+ // this is included in both the last selection and the current selection.
+ // We have nothing to do for this item.
+
+ if (flag == DragSelector.SelectionFlag_.IN_LAST_SELECTION) {
+ // If the flag equals to IN_LAST_SELECTION,
+ // then the item is included in lastSelection but not in currentSelection.
+ // Revert the selection state to this.originalSelection_.
+ this.target_.selectionModel_.setIndexSelected(
+ index, this.originalSelection_.indexOf(index) != -1);
+ } else if (flag == DragSelector.SelectionFlag_.IN_CURRENT_SELECTION) {
+ // If the flag equals to IN_CURRENT_SELECTION,
+ // this is included in currentSelection but not in lastSelection.
+ this.target_.selectionModel_.setIndexSelected(index, true);
+ }
+ }
+ if (leadIndex != -1) {
+ this.target_.selectionModel_.leadIndex = leadIndex;
+ this.target_.selectionModel_.anchorIndex = leadIndex;
+ }
+ this.target_.selectionModel_.endChange();
+ this.lastSelection_ = currentSelection;
+
+ // Update the size of border
+ this.border_.style.left = borderBounds.left + 'px';
+ this.border_.style.top = borderBounds.top + 'px';
+ this.border_.style.width = borderBounds.width + 'px';
+ this.border_.style.height = borderBounds.height + 'px';
+};
+
+/**
+ * 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.onMouseMoveBound_, true);
+ this.target_.ownerDocument.removeEventListener(
+ 'mouseup', this.onMouseUpBound_, true);
+ event.stopPropagation();
+ this.target_ = null;
+};
« 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