OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview Behavior for handling dragging elements in a container. | 6 * @fileoverview Behavior for handling dragging elements in a container. |
7 * Draggable elements must have the 'draggable' attribute set. | 7 * Draggable elements must have the 'draggable' attribute set. |
8 */ | 8 */ |
9 | 9 |
10 /** | 10 /** |
11 * @typedef {{ | 11 * @typedef {{ |
12 * x: number, | 12 * x: number, |
13 * y: number | 13 * y: number |
14 * }} | 14 * }} |
15 */ | 15 */ |
16 var DragPosition; | 16 var DragPosition; |
17 | 17 |
18 /** @polymerBehavior */ | 18 /** @polymerBehavior */ |
19 var DragBehavior = { | 19 var DragBehavior = { |
20 properties: { | |
21 /** Whether or not drag is enabled (e.g. not mirrored). */ | |
22 dragEnabled: Boolean, | |
23 }, | |
24 | |
20 /** | 25 /** |
21 * The id of the element being dragged, or empty if not dragging. | 26 * The id of the element being dragged, or empty if not dragging. |
22 * @private {string} | 27 * @private {string} |
23 */ | 28 */ |
24 dragId_: '', | 29 dragId_: '', |
25 | 30 |
26 /** @private {boolean} */ | |
27 enabled_: false, | |
28 | |
29 /** @private {!HTMLDivElement|undefined} */ | 31 /** @private {!HTMLDivElement|undefined} */ |
30 container_: undefined, | 32 container_: undefined, |
31 | 33 |
32 /** @private {?function(string, ?DragPosition):void} */ | 34 /** @private {?function(string, ?DragPosition):void} */ |
33 callback_: null, | 35 callback_: null, |
34 | 36 |
35 /** @private {!DragPosition} */ | 37 /** @private {!DragPosition} */ |
36 dragStartLocation_: {x: 0, y: 0}, | 38 dragStartLocation_: {x: 0, y: 0}, |
37 | 39 |
38 /** | 40 /** |
(...skipping 16 matching lines...) Expand all Loading... | |
55 | 57 |
56 /** @private {?function(!Event)} */ | 58 /** @private {?function(!Event)} */ |
57 endDragListener_: null, | 59 endDragListener_: null, |
58 | 60 |
59 /** | 61 /** |
60 * @param {boolean} enabled | 62 * @param {boolean} enabled |
61 * @param {!HTMLDivElement=} opt_container | 63 * @param {!HTMLDivElement=} opt_container |
62 * @param {!function(string, ?DragPosition):void=} opt_callback | 64 * @param {!function(string, ?DragPosition):void=} opt_callback |
63 */ | 65 */ |
64 initializeDrag: function(enabled, opt_container, opt_callback) { | 66 initializeDrag: function(enabled, opt_container, opt_callback) { |
65 this.enabled_ = enabled; | 67 this.dragEnabled = enabled; |
66 if (!enabled) { | 68 if (!enabled) { |
67 if (this.container) { | 69 this.removeListeners_(); |
68 this.container.removeEventListener('mousdown', this.mouseDownListener_); | |
69 this.mouseDownListener_ = null; | |
70 this.container.removeEventListener( | |
71 'mousemove', this.mouseMoveListener_); | |
72 this.mouseMoveListener_ = null; | |
73 this.container.removeEventListener( | |
74 'touchstart', this.touchStartListener_); | |
75 this.touchStartListener_ = null; | |
76 this.container.removeEventListener( | |
77 'touchmove', this.touchMoveListener_); | |
78 this.touchMoveListener_ = null; | |
79 this.container.removeEventListener('touchend', this.endDragListener_); | |
80 } | |
81 if (this.mouseUpListener_) | |
82 window.removeEventListener('mouseup', this.endDragListener_); | |
83 this.endDragListener_ = null; | |
84 return; | 70 return; |
85 } | 71 } |
86 | 72 |
87 if (opt_container !== undefined) | 73 if (opt_container !== undefined) |
88 this.container_ = opt_container; | 74 this.container_ = opt_container; |
89 var container = this.container_; | |
90 assert(container); | |
91 | 75 |
92 this.mouseDownListener_ = this.onMouseDown_.bind(this); | 76 this.addListeners_(); |
93 container.addEventListener('mousedown', this.mouseDownListener_, true); | |
94 | |
95 this.mouseMoveListener_ = this.onMouseMove_.bind(this); | |
96 container.addEventListener('mousemove', this.mouseMoveListener_, true); | |
97 | |
98 this.touchStartListener_ = this.onTouchStart_.bind(this); | |
99 container.addEventListener('touchstart', this.touchStartListener_, true); | |
100 | |
101 this.touchMoveListener_ = this.onTouchMove_.bind(this); | |
102 container.addEventListener('touchmove', this.touchMoveListener_, true); | |
103 | |
104 this.endDragListener_ = this.endDrag_.bind(this); | |
105 window.addEventListener('mouseup', this.endDragListener_, true); | |
106 container.addEventListener('touchend', this.endDragListener_, true); | |
107 | 77 |
108 if (opt_callback !== undefined) | 78 if (opt_callback !== undefined) |
109 this.callback_ = opt_callback; | 79 this.callback_ = opt_callback; |
110 }, | 80 }, |
111 | 81 |
82 /** @private */ | |
83 addListeners_() { | |
84 let container = this.container_; | |
85 if (!container || this.mouseDownListener_) | |
86 return; | |
87 this.mouseDownListener_ = this.onMouseDown_.bind(this); | |
88 container.addEventListener('mousedown', this.mouseDownListener_); | |
89 | |
90 this.mouseMoveListener_ = this.onMouseMove_.bind(this); | |
91 container.addEventListener('mousemove', this.mouseMoveListener_); | |
92 | |
93 this.touchStartListener_ = this.onTouchStart_.bind(this); | |
94 container.addEventListener('touchstart', this.touchStartListener_); | |
95 | |
96 this.touchMoveListener_ = this.onTouchMove_.bind(this); | |
97 container.addEventListener('touchmove', this.touchMoveListener_); | |
98 | |
99 this.endDragListener_ = this.endDrag_.bind(this); | |
100 window.addEventListener('mouseup', this.endDragListener_); | |
101 container.addEventListener('touchend', this.endDragListener_); | |
102 }, | |
103 | |
104 /** @private */ | |
105 removeListeners_() { | |
106 let container = this.container_; | |
107 if (!container || !this.mouseDownListener_) | |
108 return; | |
109 container.removeEventListener('mousedown', this.mouseDownListener_); | |
110 this.mouseDownListener_ = null; | |
111 container.removeEventListener('mousemove', this.mouseMoveListener_); | |
112 this.mouseMoveListener_ = null; | |
113 container.removeEventListener('touchstart', this.touchStartListener_); | |
114 this.touchStartListener_ = null; | |
115 container.removeEventListener('touchmove', this.touchMoveListener_); | |
116 this.touchMoveListener_ = null; | |
117 container.removeEventListener('touchend', this.endDragListener_); | |
118 if (this.endDragListener_) | |
119 window.removeEventListener('mouseup', this.endDragListener_); | |
michaelpg
2016/07/12 22:36:48
do we risk retaining this listener on window if th
stevenjb
2016/07/12 22:41:32
We shouldn't be unsetting this.container_ anywhere
michaelpg
2016/07/12 22:43:12
yeah, makes sense. it helps that it's called "init
| |
120 this.endDragListener_ = null; | |
121 }, | |
122 | |
112 /** | 123 /** |
113 * @param {Event} e The mouse down event. | 124 * @param {Event} e The mouse down event. |
114 * @return {boolean} | 125 * @return {boolean} |
115 * @private | 126 * @private |
116 */ | 127 */ |
117 onMouseDown_: function(e) { | 128 onMouseDown_: function(e) { |
118 if (e.button != 0) | 129 if (e.button != 0 || !e.target.getAttribute('draggable')) |
119 return true; | |
120 if (!e.target.getAttribute('draggable')) | |
121 return true; | 130 return true; |
122 e.preventDefault(); | 131 e.preventDefault(); |
123 var target = assertInstanceof(e.target, HTMLElement); | 132 var target = assertInstanceof(e.target, HTMLElement); |
124 return this.startDrag_(target, {x: e.pageX, y: e.pageY}); | 133 return this.startDrag_(target, {x: e.pageX, y: e.pageY}); |
125 }, | 134 }, |
126 | 135 |
127 /** | 136 /** |
128 * @param {Event} e The mouse move event. | 137 * @param {Event} e The mouse move event. |
129 * @return {boolean} | 138 * @return {boolean} |
130 * @private | 139 * @private |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
174 return this.processDrag_(e, touchLocation); | 183 return this.processDrag_(e, touchLocation); |
175 }, | 184 }, |
176 | 185 |
177 /** | 186 /** |
178 * @param {!HTMLElement} target | 187 * @param {!HTMLElement} target |
179 * @param {!DragPosition} eventLocation | 188 * @param {!DragPosition} eventLocation |
180 * @return {boolean} | 189 * @return {boolean} |
181 * @private | 190 * @private |
182 */ | 191 */ |
183 startDrag_: function(target, eventLocation) { | 192 startDrag_: function(target, eventLocation) { |
193 assert(this.dragEnabled); | |
184 this.dragId_ = target.id; | 194 this.dragId_ = target.id; |
185 this.dragStartLocation_ = eventLocation; | 195 this.dragStartLocation_ = eventLocation; |
186 return false; | 196 return false; |
187 }, | 197 }, |
188 | 198 |
189 /** | 199 /** |
190 * @param {Event} e | 200 * @param {Event} e |
191 * @return {boolean} | 201 * @return {boolean} |
192 * @private | 202 * @private |
193 */ | 203 */ |
194 endDrag_: function(e) { | 204 endDrag_: function(e) { |
205 assert(this.dragEnabled); | |
195 if (this.dragId_ && this.callback_) | 206 if (this.dragId_ && this.callback_) |
196 this.callback_(this.dragId_, null); | 207 this.callback_(this.dragId_, null); |
197 this.dragId_ = ''; | 208 this.dragId_ = ''; |
198 this.lastTouchLocation_ = null; | 209 this.lastTouchLocation_ = null; |
199 return false; | 210 return false; |
200 }, | 211 }, |
201 | 212 |
202 /** | 213 /** |
203 * @param {Event} e The event which triggers this drag. | 214 * @param {Event} e The event which triggers this drag. |
204 * @param {DragPosition} eventLocation The location of the event. | 215 * @param {DragPosition} eventLocation The location of the event. |
205 * @return {boolean} | 216 * @return {boolean} |
206 * @private | 217 * @private |
207 */ | 218 */ |
208 processDrag_: function(e, eventLocation) { | 219 processDrag_: function(e, eventLocation) { |
220 assert(this.dragEnabled); | |
209 if (!this.dragId_) | 221 if (!this.dragId_) |
210 return true; | 222 return true; |
211 if (this.callback_) { | 223 if (this.callback_) { |
212 var delta = { | 224 var delta = { |
213 x: eventLocation.x - this.dragStartLocation_.x, | 225 x: eventLocation.x - this.dragStartLocation_.x, |
214 y: eventLocation.y - this.dragStartLocation_.y, | 226 y: eventLocation.y - this.dragStartLocation_.y, |
215 }; | 227 }; |
216 this.callback_(this.dragId_, delta); | 228 this.callback_(this.dragId_, delta); |
217 } | 229 } |
218 return false; | 230 return false; |
219 }, | 231 }, |
220 }; | 232 }; |
OLD | NEW |