Index: chrome/browser/resources/settings/device_page/drag_behavior.js |
diff --git a/chrome/browser/resources/settings/device_page/drag_behavior.js b/chrome/browser/resources/settings/device_page/drag_behavior.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..91d9c502ba8065a01b2810fafa91442d06a10795 |
--- /dev/null |
+++ b/chrome/browser/resources/settings/device_page/drag_behavior.js |
@@ -0,0 +1,220 @@ |
+// Copyright 2016 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. |
+ |
+/** |
+ * @fileoverview Behavior for handling dragging elements in a container. |
+ * Draggable elements must have the 'draggable' attribute set. |
+ */ |
+ |
+/** |
+ * @typedef {{ |
+ * x: number, |
+ * y: number |
+ * }} |
+ */ |
+var DragPosition; |
+ |
+/** @polymerBehavior */ |
+var DragBehavior = { |
+ /** |
+ * The id of the element being dragged, or empty if not dragging. |
+ * @private {string} |
+ */ |
+ dragId_: '', |
+ |
+ /** @private {boolean} */ |
+ enabled_: false, |
+ |
+ /** @private {!HTMLDivElement|undefined} */ |
+ container_: undefined, |
+ |
+ /** @private {?function(string, ?DragPosition):void} */ |
+ callback_: null, |
+ |
+ /** @private {!DragPosition} */ |
+ dragStartLocation_: {x: 0, y: 0}, |
+ |
+ /** |
+ * Used to ignore unnecessary drag events. |
+ * @private {?DragPosition} |
+ */ |
+ lastTouchLocation_: null, |
+ |
+ /** @private {?function(!Event)} */ |
+ mouseDownListener_: null, |
+ |
+ /** @private {?function(!Event)} */ |
+ mouseMoveListener_: null, |
+ |
+ /** @private {?function(!Event)} */ |
+ touchStartListener_: null, |
+ |
+ /** @private {?function(!Event)} */ |
+ touchMoveListener_: null, |
+ |
+ /** @private {?function(!Event)} */ |
+ endDragListener_: null, |
+ |
+ /** |
+ * @param {boolean} enabled |
+ * @param {!HTMLDivElement=} opt_container |
+ * @param {!function(string, ?DragPosition):void=} opt_callback |
+ */ |
+ initializeDrag: function(enabled, opt_container, opt_callback) { |
+ this.enabled_ = enabled; |
+ if (!enabled) { |
+ if (this.container) { |
+ this.container.removeEventListener('mousdown', this.mouseDownListener_); |
+ this.mouseDownListener_ = null; |
+ this.container.removeEventListener( |
+ 'mousemove', this.mouseMoveListener_); |
+ this.mouseMoveListener_ = null; |
+ this.container.removeEventListener( |
+ 'touchstart', this.touchStartListener_); |
+ this.touchStartListener_ = null; |
+ this.container.removeEventListener( |
+ 'touchmove', this.touchMoveListener_); |
+ this.touchMoveListener_ = null; |
+ this.container.removeEventListener('touchend', this.endDragListener_); |
+ } |
+ if (this.mouseUpListener_) |
+ window.removeEventListener('mouseup', this.endDragListener_); |
+ this.endDragListener_ = null; |
+ return; |
+ } |
+ |
+ if (opt_container !== undefined) |
+ this.container_ = opt_container; |
+ var container = this.container_; |
+ assert(container); |
+ |
+ this.mouseDownListener_ = this.onMouseDown_.bind(this); |
+ container.addEventListener('mousedown', this.mouseDownListener_, true); |
+ |
+ this.mouseMoveListener_ = this.onMouseMove_.bind(this); |
+ container.addEventListener('mousemove', this.mouseMoveListener_, true); |
+ |
+ this.touchStartListener_ = this.onTouchStart_.bind(this); |
+ container.addEventListener('touchstart', this.touchStartListener_, true); |
+ |
+ this.touchMoveListener_ = this.onTouchMove_.bind(this); |
+ container.addEventListener('touchmove', this.touchMoveListener_, true); |
+ |
+ this.endDragListener_ = this.endDrag_.bind(this); |
+ window.addEventListener('mouseup', this.endDragListener_, true); |
+ container.addEventListener('touchend', this.endDragListener_, true); |
+ |
+ if (opt_callback !== undefined) |
+ this.callback_ = opt_callback; |
+ }, |
+ |
+ /** |
+ * @param {Event} e The mouse down event. |
+ * @return {boolean} |
+ * @private |
+ */ |
+ onMouseDown_: function(e) { |
+ if (e.button != 0) |
+ return true; |
+ if (!e.target.getAttribute('draggable')) |
+ return true; |
+ e.preventDefault(); |
+ var target = assertInstanceof(e.target, HTMLElement); |
+ return this.startDrag_(target, {x: e.pageX, y: e.pageY}); |
+ }, |
+ |
+ /** |
+ * @param {Event} e The mouse move event. |
+ * @return {boolean} |
+ * @private |
+ */ |
+ onMouseMove_: function(e) { |
+ e.preventDefault(); |
+ return this.processDrag_(e, {x: e.pageX, y: e.pageY}); |
+ }, |
+ |
+ /** |
+ * @param {Event} e The touch start event. |
+ * @return {boolean} |
+ * @private |
+ */ |
+ onTouchStart_: function(e) { |
+ if (e.touches.length != 1) |
+ return false; |
+ |
+ e.preventDefault(); |
+ var touch = e.touches[0]; |
+ this.lastTouchLocation_ = {x: touch.pageX, y: touch.pageY}; |
+ var target = assertInstanceof(e.target, HTMLElement); |
+ return this.startDrag_(target, this.lastTouchLocation_); |
+ }, |
+ |
+ /** |
+ * @param {Event} e The touch move event. |
+ * @return {boolean} |
+ * @private |
+ */ |
+ onTouchMove_: function(e) { |
+ if (e.touches.length != 1) |
+ return true; |
+ |
+ var touchLocation = {x: e.touches[0].pageX, y: e.touches[0].pageY}; |
+ // Touch move events can happen even if the touch location doesn't change |
+ // and on small unintentional finger movements. Ignore these small changes. |
+ if (this.lastTouchLocation_) { |
+ /** @const */ var IGNORABLE_TOUCH_MOVE_PX = 1; |
+ var xDiff = Math.abs(touchLocation.x - this.lastTouchLocation_.x); |
+ var yDiff = Math.abs(touchLocation.y - this.lastTouchLocation_.y); |
+ if (xDiff <= IGNORABLE_TOUCH_MOVE_PX && yDiff <= IGNORABLE_TOUCH_MOVE_PX) |
+ return true; |
+ } |
+ this.lastTouchLocation_ = touchLocation; |
+ e.preventDefault(); |
+ return this.processDrag_(e, touchLocation); |
+ }, |
+ |
+ /** |
+ * @param {!HTMLElement} target |
+ * @param {!DragPosition} eventLocation |
+ * @return {boolean} |
+ * @private |
+ */ |
+ startDrag_: function(target, eventLocation) { |
+ this.dragId_ = target.id; |
+ this.dragStartLocation_ = eventLocation; |
+ return false; |
+ }, |
+ |
+ /** |
+ * @param {Event} e |
+ * @return {boolean} |
+ * @private |
+ */ |
+ endDrag_: function(e) { |
+ if (this.dragId_ && this.callback_) |
+ this.callback_(this.dragId_, null); |
+ this.dragId_ = ''; |
+ this.lastTouchLocation_ = null; |
+ return false; |
+ }, |
+ |
+ /** |
+ * @param {Event} e The event which triggers this drag. |
+ * @param {DragPosition} eventLocation The location of the event. |
+ * @return {boolean} |
+ * @private |
+ */ |
+ processDrag_: function(e, eventLocation) { |
+ if (!this.dragId_) |
+ return true; |
+ if (this.callback_) { |
+ var delta = { |
+ x: eventLocation.x - this.dragStartLocation_.x, |
+ y: eventLocation.y - this.dragStartLocation_.y, |
+ }; |
+ this.callback_(this.dragId_, delta); |
+ } |
+ return false; |
+ }, |
+}; |