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

Unified Diff: chrome/browser/resources/ntp/drag_drop_controller.js

Issue 6297013: [NTP] Allow reordering of apps via drag and drop. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: incorporate feedback Created 9 years, 11 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/ntp/drag_drop_controller.js
diff --git a/chrome/browser/resources/ntp/drag_drop_controller.js b/chrome/browser/resources/ntp/drag_drop_controller.js
new file mode 100644
index 0000000000000000000000000000000000000000..fe604a41ee9ee583829280cc8e9c4d5209c65a33
--- /dev/null
+++ b/chrome/browser/resources/ntp/drag_drop_controller.js
@@ -0,0 +1,164 @@
+// Copyright (c) 2011 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.
+
+// The delegate interface:
+// dragContainer -->
+// element containing the draggable items
+//
+// transitionsDuration -->
+// length of time of transitions in ms
+//
+// dragItem -->
+// get / set property containing the item being dragged
+//
+// getItem(e) -->
+// get's the item that is under the mouse event |e|
+//
+// canDropOn(coordinates) -->
+// returns true if the coordinates (relative to the drag container)
+// point to a valid place to drop an item
+//
+// setDragPlaceholder(coordinates) -->
+// tells the delegate that the dragged item is currently above
+// the specified coordinates.
+//
+// saveDrag() -->
+// tells the delegate that the drag is done. move the item to the
+// position last specified by setDragPlaceholder. (e.g., commit changes)
+//
+
+function DragAndDropController(delegate) {
+ this.delegate_ = delegate;
+
+ this.installHandlers_();
+}
+
+DragAndDropController.prototype = {
+ startX_: 0,
+ startY_: 0,
+ startScreenX_: 0,
+ startScreenY_: 0,
+
+ installHandlers_: function() {
+ var el = this.delegate_.dragContainer;
+ el.addEventListener('dragstart', this.handleDragStart_.bind(this));
+ el.addEventListener('dragenter', this.handleDragEnter_.bind(this));
+ el.addEventListener('dragover', this.handleDragOver_.bind(this));
+ el.addEventListener('dragleave', this.handleDragLeave_.bind(this));
+ el.addEventListener('drop', this.handleDrop_.bind(this));
+ el.addEventListener('dragend', this.handleDragEnd_.bind(this));
+ el.addEventListener('drag', this.handleDrag_.bind(this));
+ el.addEventListener('mousedown', this.handleMouseDown_.bind(this));
+ },
+
+ getCoordinates_: function(e) {
+ var rect = this.delegate_.dragContainer.getBoundingClientRect();
+ var coordinates = {
+ x: e.clientX + window.scrollX - rect.left,
+ y: e.clientY + window.scrollY - rect.top
+ };
+
+ // If we're in an RTL language, reflect the coordinates so the delegate
+ // doesn't need to worry about it.
+ if (isRtl())
+ coordinates.x = this.delegate_.dragContainer.offsetWidth - coordinates.x;
+
+ return coordinates;
+ },
+
+ // Listen to mousedown to get the relative position of the cursor when
+ // starting drag and drop.
+ handleMouseDown_: function(e) {
+ var item = this.delegate_.getItem(e);
+ if (!item)
+ return;
+
+ this.startX_ = item.offsetLeft;
+ this.startY_ = item.offsetTop;
+ this.startScreenX_ = e.screenX;
+ this.startScreenY_ = e.screenY;
+
+ // We don't want to focus the item on mousedown. However, to prevent
+ // focus one has to call preventDefault but this also prevents the drag
+ // and drop (sigh) so we only prevent it when the user is not doing a
+ // left mouse button drag.
+ if (e.button != 0) // LEFT
+ e.preventDefault();
+ },
+
+ handleDragStart_: function(e) {
+ var item = this.delegate_.getItem(e);
+ if (!item)
+ return;
+
+ // Don't set data since HTML5 does not allow setting the name for
+ // url-list. Instead, we just rely on the dragging of link behavior.
+ this.delegate_.dragItem = item;
+ item.classList.add('dragging');
+
+ e.dataTransfer.effectAllowed = 'copyLinkMove';
+ },
+
+ handleDragEnter_: function(e) {
+ if (this.delegate_.canDropOn(this.getCoordinates_(e)))
+ e.preventDefault();
+ },
+
+ handleDragOver_: function(e) {
+ var coordinates = this.getCoordinates_(e);
+ if (!this.delegate_.canDropOn(coordinates))
+ return;
+
+ this.delegate_.setDragPlaceholder(coordinates);
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'move';
+ },
+
+ handleDragLeave_: function(e) {
+ if (this.delegate_.canDropOn(this.getCoordinates_(e)))
+ e.preventDefault();
+ },
+
+ handleDrop_: function(e) {
+ var dragItem = this.delegate_.dragItem;
+ if (!dragItem)
+ return;
+
+ this.delegate_.dragItem = null;
+ this.delegate_.saveDrag();
+
+ setTimeout(function() {
+ dragItem.classList.remove('dragging');
+ }, this.delegate_.transitionsDuration + 10);
+ },
+
+ handleDragEnd_: function(e) {
+ return this.handleDrop_(e);
+ },
+
+ handleDrag_: function(e) {
+ // Moves the drag item making sure that it is not displayed outside the
+ // browser viewport.
+ var dragItem = this.delegate_.dragItem;
+ var rect = this.delegate_.dragContainer.getBoundingClientRect();
+
+ var x = this.startX_ + e.screenX - this.startScreenX_;
+ var y = this.startY_ + e.screenY - this.startScreenY_;
+
+ // The position of the item is relative to #apps so we need to
+ // subtract that when calculating the allowed position.
+ x = Math.max(x, -rect.left);
+ x = Math.min(x, document.body.clientWidth - rect.left -
+ dragItem.offsetWidth - 2);
+
+ // The shadow is 2px
+ y = Math.max(-rect.top, y);
+ y = Math.min(y, document.body.clientHeight - rect.top -
+ dragItem.offsetHeight - 2);
+
+ // Override right in case of RTL.
+ dragItem.style.left = x + 'px';
+ dragItem.style.top = y + 'px';
+ }
+};

Powered by Google App Engine
This is Rietveld 408576698