Chromium Code Reviews| 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..1df92a54caed62cb4f97c75bdab1ec61c36fcd93 |
| --- /dev/null |
| +++ b/chrome/browser/resources/settings/device_page/drag_behavior.js |
| @@ -0,0 +1,194 @@ |
| +// 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} */ |
|
michaelpg
2016/06/24 21:00:10
is it really nullable? (if so, initialize to null
stevenjb
2016/06/24 21:44:12
Done.
|
| + dragStartLocation_: {x: 0, y: 0}, |
|
michaelpg
2016/06/24 21:00:11
used elsewhere without the underscore
stevenjb
2016/06/24 21:44:12
<rant> It never ceases to surprise me what Closure
|
| + |
| + /** |
| + * Used to ignore unnecessary drag events. |
| + * @private {?DragPosition} |
| + */ |
| + lastTouchLocation_: null, |
| + |
| + /** @private {?function(!Event)} */ |
| + mouseUpListener_: 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.onmousemove = null; |
|
michaelpg
2016/06/24 21:00:11
throughout: use addEventListener/removeEventListen
stevenjb
2016/06/24 21:44:12
Ugh. Yeah. Done.
|
| + this.container.ontouchmove = null; |
| + this.container.ontouchend = null; |
| + } |
| + if (this.mouseUpListener_) { |
| + window.removeEventListener('keydown', this.mouseUpListener_); |
| + this.mouseUpListener_ = null; |
| + } |
| + return; |
| + } |
| + |
| + if (opt_container !== undefined) |
| + this.container_ = opt_container; |
| + var container = this.container_; |
| + assert(container); |
| + // Mouse |
| + container.onmousedown = this.onMouseDown_.bind(this); |
| + container.onmousemove = this.onMouseMove_.bind(this); |
| + this.mouseUpListener_ = this.endDrag_.bind(this); |
| + window.addEventListener('mouseup', this.mouseUpListener_, true); |
| + // Touch |
| + container.ontouchstart = this.onTouchStart_.bind(this); |
| + container.ontouchmove = this.onTouchMove_.bind(this); |
| + container.ontouchend = this.endDrag_.bind(this); |
| + |
| + 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; |
|
michaelpg
2016/06/24 21:00:10
nice
stevenjb
2016/06/24 21:44:12
Acknowledged.
|
| + 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) { |
| + console.log('Start Drag: ' + target.id); |
|
michaelpg
2016/06/24 21:00:11
ahem
stevenjb
2016/06/24 21:44:12
Removed.
|
| + 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; |
| + }, |
| +}; |