blob: 0cecd6d6a729aa9e4d4c9a7a9d0ba2dabdc8e8f1 [file] [log] [blame]
John Leec5bf0f22020-02-05 21:01:131// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import './strings.m.js';
6
7import {assert} from 'chrome://resources/js/assert.m.js';
8import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
9
10import {isTabElement, TabElement} from './tab.js';
11import {isTabGroupElement, TabGroupElement} from './tab_group.js';
John Lee5db744f2020-08-19 22:55:4712import {TabStripEmbedderProxy, TabStripEmbedderProxyImpl} from './tab_strip_embedder_proxy.js';
dpapad3d9fd7362020-05-15 17:12:0113import {TabData, TabNetworkState, TabsApiProxy, TabsApiProxyImpl} from './tabs_api_proxy.js';
John Lee49ccb722020-02-26 03:30:0514
15/** @const {number} */
16export const PLACEHOLDER_TAB_ID = -1;
17
John Lee7b0b7a62020-03-03 06:00:5018/** @const {string} */
19export const PLACEHOLDER_GROUP_ID = 'placeholder';
20
John Lee49ccb722020-02-26 03:30:0521/**
22 * The data type key for pinned state of a tab. Since drag events only expose
23 * whether or not a data type exists (not the actual value), presence of this
24 * data type means that the tab is pinned.
25 * @const {string}
26 */
27const PINNED_DATA_TYPE = 'pinned';
John Leec5bf0f22020-02-05 21:01:1328
29/**
30 * Gets the data type of tab IDs on DataTransfer objects in drag events. This
31 * is a function so that loadTimeData can get overridden by tests.
32 * @return {string}
33 */
34function getTabIdDataType() {
35 return loadTimeData.getString('tabIdDataType');
36}
37
38/** @return {string} */
39function getGroupIdDataType() {
40 return loadTimeData.getString('tabGroupIdDataType');
41}
42
John Lee49ccb722020-02-26 03:30:0543/** @return {!TabData} */
44function getDefaultTabData() {
45 return {
46 active: false,
47 alertStates: [],
48 blocked: false,
49 crashed: false,
50 id: -1,
51 index: -1,
52 isDefaultFavicon: false,
53 networkState: TabNetworkState.NONE,
54 pinned: false,
55 shouldHideThrobber: false,
56 showIcon: true,
57 title: '',
58 url: '',
59 };
60}
61
John Leec5bf0f22020-02-05 21:01:1362/**
63 * @interface
64 */
65export class DragManagerDelegate {
66 /**
67 * @param {!TabElement} tabElement
68 * @return {number}
69 */
70 getIndexOfTab(tabElement) {}
71
John Leeaa89aa72020-02-21 01:53:2972 /**
73 * @param {!TabElement} element
74 * @param {number} index
75 * @param {boolean} pinned
John Lee49ccb722020-02-26 03:30:0576 * @param {string=} groupId
John Leeaa89aa72020-02-21 01:53:2977 */
78 placeTabElement(element, index, pinned, groupId) {}
79
80 /**
81 * @param {!TabGroupElement} element
82 * @param {number} index
83 */
84 placeTabGroupElement(element, index) {}
John Leec5bf0f22020-02-05 21:01:1385}
86
87/** @typedef {!DragManagerDelegate|!HTMLElement} */
88let DragManagerDelegateElement;
89
John Leeaa89aa72020-02-21 01:53:2990class DragSession {
91 /**
92 * @param {!DragManagerDelegateElement} delegate
93 * @param {!TabElement|!TabGroupElement} element
94 * @param {number} srcIndex
95 * @param {string=} srcGroup
96 */
97 constructor(delegate, element, srcIndex, srcGroup) {
98 /** @const @private {!DragManagerDelegateElement} */
99 this.delegate_ = delegate;
100
101 /** @const {!TabElement|!TabGroupElement} */
102 this.element_ = element;
103
John Lee5db744f2020-08-19 22:55:47104 /**
105 * Flag indicating if during the drag session, the element has at least
106 * moved once.
107 * @private {boolean}
108 */
109 this.hasMoved_ = false;
110
John Lee04406402020-10-09 00:59:53111 /** @private {!Object<{x: number, y: number}>} */
112 this.lastPoint_ = {x: 0, y: 0};
113
John Leeaa89aa72020-02-21 01:53:29114 /** @const {number} */
115 this.srcIndex = srcIndex;
116
117 /** @const {string|undefined} */
118 this.srcGroup = srcGroup;
119
120 /** @private @const {!TabsApiProxy} */
dpapad3d9fd7362020-05-15 17:12:01121 this.tabsProxy_ = TabsApiProxyImpl.getInstance();
John Lee5db744f2020-08-19 22:55:47122
123 /** @private {!TabStripEmbedderProxy} */
124 this.tabStripEmbedderProxy_ = TabStripEmbedderProxyImpl.getInstance();
John Leeaa89aa72020-02-21 01:53:29125 }
126
127 /**
128 * @param {!DragManagerDelegateElement} delegate
129 * @param {!TabElement|!TabGroupElement} element
130 * @return {!DragSession}
131 */
132 static createFromElement(delegate, element) {
133 if (isTabGroupElement(element)) {
134 return new DragSession(
135 delegate, element,
136 delegate.getIndexOfTab(
137 /** @type {!TabElement} */ (element.firstElementChild)));
138 }
139
140 const srcIndex = delegate.getIndexOfTab(
141 /** @type {!TabElement} */ (element));
142 const srcGroup =
143 (element.parentElement && isTabGroupElement(element.parentElement)) ?
144 element.parentElement.dataset.groupId :
145 undefined;
146 return new DragSession(delegate, element, srcIndex, srcGroup);
147 }
148
John Lee49ccb722020-02-26 03:30:05149 /**
150 * @param {!DragManagerDelegateElement} delegate
151 * @param {!DragEvent} event
152 * @return {?DragSession}
153 */
154 static createFromEvent(delegate, event) {
155 if (event.dataTransfer.types.includes(getTabIdDataType())) {
156 const isPinned = event.dataTransfer.types.includes('pinned');
157 const placeholderTabElement =
158 /** @type {!TabElement} */ (document.createElement('tabstrip-tab'));
159 placeholderTabElement.tab = /** @type {!TabData} */ (Object.assign(
160 getDefaultTabData(), {id: PLACEHOLDER_TAB_ID, pinned: isPinned}));
161 placeholderTabElement.setDragging(true);
162 delegate.placeTabElement(placeholderTabElement, -1, isPinned);
163 return DragSession.createFromElement(delegate, placeholderTabElement);
164 }
165
John Lee7b0b7a62020-03-03 06:00:50166 if (event.dataTransfer.types.includes(getGroupIdDataType())) {
167 const placeholderGroupElement = /** @type {!TabGroupElement} */
168 (document.createElement('tabstrip-tab-group'));
169 placeholderGroupElement.dataset.groupId = PLACEHOLDER_GROUP_ID;
170 placeholderGroupElement.setDragging(true);
171 delegate.placeTabGroupElement(placeholderGroupElement, -1);
172 return DragSession.createFromElement(delegate, placeholderGroupElement);
173 }
174
John Lee49ccb722020-02-26 03:30:05175 return null;
176 }
177
John Leeaa89aa72020-02-21 01:53:29178 /** @return {string|undefined} */
179 get dstGroup() {
180 if (isTabElement(this.element_) && this.element_.parentElement &&
181 isTabGroupElement(this.element_.parentElement)) {
182 return this.element_.parentElement.dataset.groupId;
183 }
184
185 return undefined;
186 }
187
188 /** @return {number} */
189 get dstIndex() {
190 if (isTabElement(this.element_)) {
191 return this.delegate_.getIndexOfTab(
192 /** @type {!TabElement} */ (this.element_));
193 }
194
John Lee7b0b7a62020-03-03 06:00:50195 if (this.element_.children.length === 0) {
196 // If this group element has no children, it was a placeholder element
197 // being dragged. Find out the destination index by finding the index of
198 // the tab closest to it and incrementing it by 1.
199 const previousElement = this.element_.previousElementSibling;
200 if (!previousElement) {
201 return 0;
202 }
203 if (isTabElement(previousElement)) {
204 return this.delegate_.getIndexOfTab(
205 /** @private {!TabElement} */ (previousElement)) +
206 1;
207 }
208
209 assert(isTabGroupElement(previousElement));
210 return this.delegate_.getIndexOfTab(/** @private {!TabElement} */ (
211 previousElement.lastElementChild)) +
212 1;
213 }
214
John Leeaa89aa72020-02-21 01:53:29215 // If a tab group is moving backwards (to the front of the tab strip), the
216 // new index is the index of the first tab in that group. If a tab group is
217 // moving forwards (to the end of the tab strip), the new index is the index
218 // of the last tab in that group.
219 let dstIndex = this.delegate_.getIndexOfTab(
220 /** @type {!TabElement} */ (this.element_.firstElementChild));
221 if (this.srcIndex <= dstIndex) {
222 dstIndex += this.element_.childElementCount - 1;
223 }
224 return dstIndex;
225 }
226
John Lee04406402020-10-09 00:59:53227 /** @param {!DragEvent} event */
228 cancel(event) {
John Lee77e94e1a2020-02-27 02:16:44229 if (this.isDraggingPlaceholder()) {
John Lee49ccb722020-02-26 03:30:05230 this.element_.remove();
231 return;
232 }
233
John Leeaa89aa72020-02-21 01:53:29234 if (isTabGroupElement(this.element_)) {
235 this.delegate_.placeTabGroupElement(
236 /** @type {!TabGroupElement} */ (this.element_), this.srcIndex);
237 } else if (isTabElement(this.element_)) {
238 this.delegate_.placeTabElement(
239 /** @type {!TabElement} */ (this.element_), this.srcIndex,
240 this.element_.tab.pinned, this.srcGroup);
241 }
242
243 this.element_.setDragging(false);
John Lee656beed2020-07-07 22:45:52244 this.element_.setDraggedOut(false);
John Lee04406402020-10-09 00:59:53245
246 if (event.type === 'dragend' && isTabElement(this.element_) &&
247 !this.hasMoved_) {
248 // If the user was dragging a tab and the tab has not ever been moved,
249 // show a context menu instead.
250 this.tabStripEmbedderProxy_.showTabContextMenu(
251 this.element_.tab.id, this.lastPoint_.x, this.lastPoint_.y);
252 }
John Leeaa89aa72020-02-21 01:53:29253 }
254
John Lee77e94e1a2020-02-27 02:16:44255 /** @return {boolean} */
256 isDraggingPlaceholder() {
John Lee7b0b7a62020-03-03 06:00:50257 return this.isDraggingPlaceholderTab_() ||
258 this.isDraggingPlaceholderGroup_();
259 }
260
261 /**
262 * @return {boolean}
263 * @private
264 */
265 isDraggingPlaceholderTab_() {
John Lee77e94e1a2020-02-27 02:16:44266 return isTabElement(this.element_) &&
John Lee7b0b7a62020-03-03 06:00:50267 this.element_.tab.id === PLACEHOLDER_TAB_ID;
268 }
269
270 /**
271 * @return {boolean}
272 * @private
273 */
274 isDraggingPlaceholderGroup_() {
275 return isTabGroupElement(this.element_) &&
276 this.element_.dataset.groupId === PLACEHOLDER_GROUP_ID;
John Lee77e94e1a2020-02-27 02:16:44277 }
278
John Lee49ccb722020-02-26 03:30:05279 /** @param {!DragEvent} event */
280 finish(event) {
John Lee7b0b7a62020-03-03 06:00:50281 if (this.isDraggingPlaceholderTab_()) {
John Lee49ccb722020-02-26 03:30:05282 const id = Number(event.dataTransfer.getData(getTabIdDataType()));
283 this.element_.tab = Object.assign({}, this.element_.tab, {id});
John Lee7b0b7a62020-03-03 06:00:50284 } else if (this.isDraggingPlaceholderGroup_()) {
285 this.element_.dataset.groupId =
286 event.dataTransfer.getData(getGroupIdDataType());
John Leeaa89aa72020-02-21 01:53:29287 }
288
289 const dstIndex = this.dstIndex;
290 if (isTabElement(this.element_)) {
291 this.tabsProxy_.moveTab(this.element_.tab.id, dstIndex);
292 } else if (isTabGroupElement(this.element_)) {
293 this.tabsProxy_.moveGroup(this.element_.dataset.groupId, dstIndex);
294 }
295
John Lee49ccb722020-02-26 03:30:05296 const dstGroup = this.dstGroup;
297 if (dstGroup && dstGroup !== this.srcGroup) {
298 this.tabsProxy_.groupTab(this.element_.tab.id, dstGroup);
299 } else if (!dstGroup && this.srcGroup) {
300 this.tabsProxy_.ungroupTab(this.element_.tab.id);
301 }
302
John Leeaa89aa72020-02-21 01:53:29303 this.element_.setDragging(false);
John Lee656beed2020-07-07 22:45:52304 this.element_.setDraggedOut(false);
John Leeaa89aa72020-02-21 01:53:29305 }
306
John Lee7b0b7a62020-03-03 06:00:50307 /**
308 * @param {!TabElement|!TabGroupElement} dragOverElement
309 * @return {boolean}
310 */
311 shouldOffsetIndexForGroup_(dragOverElement) {
312 // Since TabGroupElements do not have any TabElements, they need to offset
313 // the index for any elements that come after it as if there is at least
314 // one element inside of it.
315 return this.isDraggingPlaceholder() &&
316 !!(dragOverElement.compareDocumentPosition(this.element_) &
317 Node.DOCUMENT_POSITION_PRECEDING);
318 }
319
John Leeaa89aa72020-02-21 01:53:29320 /** @param {!DragEvent} event */
321 start(event) {
John Lee04406402020-10-09 00:59:53322 this.lastPoint_ = {x: event.clientX, y: event.clientY};
John Leeaa89aa72020-02-21 01:53:29323 event.dataTransfer.effectAllowed = 'move';
John Lee10e2eac2020-07-20 18:27:54324 const draggedItemRect = event.composedPath()[0].getBoundingClientRect();
John Leeaa89aa72020-02-21 01:53:29325 this.element_.setDragging(true);
John Lee9f2ee96852020-03-12 02:17:28326
327 const dragImage = this.element_.getDragImage();
328 const dragImageRect = dragImage.getBoundingClientRect();
329
330 let scaleFactor = 1;
331 let verticalOffset = 0;
332
333 // <if expr="chromeos">
334 // Touch on ChromeOS automatically scales drag images by 1.2 and adds a
335 // vertical offset of 25px. See //ash/drag_drop/drag_drop_controller.cc.
336 scaleFactor = 1.2;
337 verticalOffset = 25;
338 // </if>
339
John Lee10e2eac2020-07-20 18:27:54340 const eventXPercentage =
341 (event.clientX - draggedItemRect.left) / draggedItemRect.width;
342 const eventYPercentage =
343 (event.clientY - draggedItemRect.top) / draggedItemRect.height;
John Lee9f2ee96852020-03-12 02:17:28344
John Lee10e2eac2020-07-20 18:27:54345 // First, align the top-left corner of the drag image's center element
346 // to the event's coordinates.
347 const dragImageCenterRect =
348 this.element_.getDragImageCenter().getBoundingClientRect();
349 let xOffset = (dragImageCenterRect.left - dragImageRect.left) * scaleFactor;
350 let yOffset = (dragImageCenterRect.top - dragImageRect.top) * scaleFactor;
351
352 // Then, offset the drag image again by using the event's coordinates
353 // within the dragged item itself so that the drag image appears positioned
354 // as closely as its state before dragging.
355 xOffset += dragImageCenterRect.width * eventXPercentage;
356 yOffset += dragImageCenterRect.height * eventYPercentage;
357 yOffset -= verticalOffset;
358
359 event.dataTransfer.setDragImage(dragImage, xOffset, yOffset);
John Leeaa89aa72020-02-21 01:53:29360
361 if (isTabElement(this.element_)) {
362 event.dataTransfer.setData(
363 getTabIdDataType(), this.element_.tab.id.toString());
John Lee49ccb722020-02-26 03:30:05364
365 if (this.element_.tab.pinned) {
366 event.dataTransfer.setData(
367 'pinned', this.element_.tab.pinned.toString());
368 }
John Leeaa89aa72020-02-21 01:53:29369 } else if (isTabGroupElement(this.element_)) {
370 event.dataTransfer.setData(
371 getGroupIdDataType(), this.element_.dataset.groupId);
372 }
373 }
374
375 /** @param {!DragEvent} event */
376 update(event) {
John Lee04406402020-10-09 00:59:53377 this.lastPoint_ = {x: event.clientX, y: event.clientY};
378
John Lee656beed2020-07-07 22:45:52379 if (event.type === 'dragleave') {
380 this.element_.setDraggedOut(true);
John Lee5db744f2020-08-19 22:55:47381 this.hasMoved_ = true;
John Lee656beed2020-07-07 22:45:52382 return;
383 }
384
John Leeaa89aa72020-02-21 01:53:29385 event.dataTransfer.dropEffect = 'move';
John Lee656beed2020-07-07 22:45:52386 this.element_.setDraggedOut(false);
John Leeaa89aa72020-02-21 01:53:29387 if (isTabGroupElement(this.element_)) {
388 this.updateForTabGroupElement_(event);
389 } else if (isTabElement(this.element_)) {
390 this.updateForTabElement_(event);
391 }
392 }
393
394 /**
395 * @param {!DragEvent} event
396 * @private
397 */
398 updateForTabGroupElement_(event) {
399 const tabGroupElement =
400 /** @type {!TabGroupElement} */ (this.element_);
401 const composedPath = /** @type {!Array<!Element>} */ (event.composedPath());
402 if (composedPath.includes(assert(this.element_))) {
403 // Dragging over itself or a child of itself.
404 return;
405 }
406
407 const dragOverTabElement =
408 /** @type {!TabElement|undefined} */ (composedPath.find(isTabElement));
John Leed486ab1a2020-06-19 19:27:20409 if (dragOverTabElement && !dragOverTabElement.tab.pinned &&
410 dragOverTabElement.isValidDragOverTarget) {
John Lee7b0b7a62020-03-03 06:00:50411 let dragOverIndex = this.delegate_.getIndexOfTab(dragOverTabElement);
412 dragOverIndex +=
413 this.shouldOffsetIndexForGroup_(dragOverTabElement) ? 1 : 0;
John Leeaa89aa72020-02-21 01:53:29414 this.delegate_.placeTabGroupElement(tabGroupElement, dragOverIndex);
John Lee5db744f2020-08-19 22:55:47415 this.hasMoved_ = true;
John Leeaa89aa72020-02-21 01:53:29416 return;
417 }
418
John Lee7b0b7a62020-03-03 06:00:50419 const dragOverGroupElement = /** @type {!TabGroupElement|undefined} */ (
420 composedPath.find(isTabGroupElement));
John Leed486ab1a2020-06-19 19:27:20421 if (dragOverGroupElement && dragOverGroupElement.isValidDragOverTarget) {
John Lee7b0b7a62020-03-03 06:00:50422 let dragOverIndex = this.delegate_.getIndexOfTab(
John Leeaa89aa72020-02-21 01:53:29423 /** @type {!TabElement} */ (dragOverGroupElement.firstElementChild));
John Lee7b0b7a62020-03-03 06:00:50424 dragOverIndex +=
425 this.shouldOffsetIndexForGroup_(dragOverGroupElement) ? 1 : 0;
John Leeaa89aa72020-02-21 01:53:29426 this.delegate_.placeTabGroupElement(tabGroupElement, dragOverIndex);
John Lee5db744f2020-08-19 22:55:47427 this.hasMoved_ = true;
John Leeaa89aa72020-02-21 01:53:29428 }
429 }
430
431 /**
432 * @param {!DragEvent} event
433 * @private
434 */
435 updateForTabElement_(event) {
436 const tabElement = /** @type {!TabElement} */ (this.element_);
437 const composedPath = /** @type {!Array<!Element>} */ (event.composedPath());
438 const dragOverTabElement =
439 /** @type {?TabElement} */ (composedPath.find(isTabElement));
440 if (dragOverTabElement &&
John Lee1a8ab212020-06-05 18:06:43441 (dragOverTabElement.tab.pinned !== tabElement.tab.pinned ||
442 !dragOverTabElement.isValidDragOverTarget)) {
443 // Can only drag between the same pinned states and valid TabElements.
John Leeaa89aa72020-02-21 01:53:29444 return;
445 }
446
447 const previousGroupId = (tabElement.parentElement &&
448 isTabGroupElement(tabElement.parentElement)) ?
449 tabElement.parentElement.dataset.groupId :
450 undefined;
451
452 const dragOverTabGroup =
453 /** @type {?TabGroupElement} */ (composedPath.find(isTabGroupElement));
454 if (dragOverTabGroup &&
John Leed486ab1a2020-06-19 19:27:20455 dragOverTabGroup.dataset.groupId !== previousGroupId &&
456 dragOverTabGroup.isValidDragOverTarget) {
John Leeaa89aa72020-02-21 01:53:29457 this.delegate_.placeTabElement(
458 tabElement, this.dstIndex, false, dragOverTabGroup.dataset.groupId);
John Lee5db744f2020-08-19 22:55:47459 this.hasMoved_ = true;
John Leeaa89aa72020-02-21 01:53:29460 return;
461 }
462
463 if (!dragOverTabGroup && previousGroupId) {
464 this.delegate_.placeTabElement(
465 tabElement, this.dstIndex, false, undefined);
John Lee5db744f2020-08-19 22:55:47466 this.hasMoved_ = true;
John Leeaa89aa72020-02-21 01:53:29467 return;
468 }
469
470 if (!dragOverTabElement) {
471 return;
472 }
473
474 const dragOverIndex = this.delegate_.getIndexOfTab(dragOverTabElement);
475 this.delegate_.placeTabElement(
476 tabElement, dragOverIndex, tabElement.tab.pinned, previousGroupId);
John Lee5db744f2020-08-19 22:55:47477 this.hasMoved_ = true;
John Leeaa89aa72020-02-21 01:53:29478 }
479}
480
John Leec5bf0f22020-02-05 21:01:13481export class DragManager {
482 /** @param {!DragManagerDelegateElement} delegate */
483 constructor(delegate) {
484 /** @private {!DragManagerDelegateElement} */
485 this.delegate_ = delegate;
486
John Leeaa89aa72020-02-21 01:53:29487 /** @type {?DragSession} */
488 this.dragSession_ = null;
John Leec5bf0f22020-02-05 21:01:13489
John Leec5bf0f22020-02-05 21:01:13490 /** @private {!TabsApiProxy} */
dpapad3d9fd7362020-05-15 17:12:01491 this.tabsProxy_ = TabsApiProxyImpl.getInstance();
John Leec5bf0f22020-02-05 21:01:13492 }
493
John Lee656beed2020-07-07 22:45:52494 /**
495 * @param {!DragEvent} event
496 * @private
497 */
498 onDragLeave_(event) {
499 if (this.dragSession_ && this.dragSession_.isDraggingPlaceholder()) {
John Lee04406402020-10-09 00:59:53500 this.dragSession_.cancel(event);
John Lee656beed2020-07-07 22:45:52501 this.dragSession_ = null;
John Lee7b0b7a62020-03-03 06:00:50502 return;
John Lee77e94e1a2020-02-27 02:16:44503 }
504
John Lee656beed2020-07-07 22:45:52505 this.dragSession_.update(event);
John Lee9b3b01f2020-02-19 03:45:04506 }
507
508 /** @param {!DragEvent} event */
John Leeaa89aa72020-02-21 01:53:29509 onDragOver_(event) {
John Leec5bf0f22020-02-05 21:01:13510 event.preventDefault();
John Leeaa89aa72020-02-21 01:53:29511 if (!this.dragSession_) {
John Leec5bf0f22020-02-05 21:01:13512 return;
513 }
514
John Leeaa89aa72020-02-21 01:53:29515 this.dragSession_.update(event);
John Leec5bf0f22020-02-05 21:01:13516 }
517
John Leeaa89aa72020-02-21 01:53:29518 /** @param {!DragEvent} event */
519 onDragStart_(event) {
520 const draggedItem =
521 /** @type {!Array<!Element>} */ (event.composedPath()).find(item => {
522 return isTabElement(item) || isTabGroupElement(item);
523 });
524 if (!draggedItem) {
John Leec5bf0f22020-02-05 21:01:13525 return;
526 }
527
John Leeaa89aa72020-02-21 01:53:29528 this.dragSession_ = DragSession.createFromElement(
529 this.delegate_,
530 /** @type {!TabElement|!TabGroupElement} */ (draggedItem));
531 this.dragSession_.start(event);
John Leec5bf0f22020-02-05 21:01:13532 }
533
John Leeaa89aa72020-02-21 01:53:29534 /** @param {!DragEvent} event */
535 onDragEnd_(event) {
536 if (!this.dragSession_) {
John Leec5bf0f22020-02-05 21:01:13537 return;
538 }
539
John Lee04406402020-10-09 00:59:53540 this.dragSession_.cancel(event);
John Leeaa89aa72020-02-21 01:53:29541 this.dragSession_ = null;
John Leec5bf0f22020-02-05 21:01:13542 }
543
John Lee49ccb722020-02-26 03:30:05544 /** @param {!DragEvent} event */
545 onDragEnter_(event) {
546 if (this.dragSession_) {
John Lee5e11d0f2020-08-18 18:31:57547 // TODO(crbug.com/843556): Do not update the drag session on dragenter.
548 // An incorrect event target on dragenter causes tabs to move around
549 // erroneously.
John Lee49ccb722020-02-26 03:30:05550 return;
551 }
552
553 this.dragSession_ = DragSession.createFromEvent(this.delegate_, event);
554 }
555
John Leec5bf0f22020-02-05 21:01:13556 /**
557 * @param {!DragEvent} event
John Leec5bf0f22020-02-05 21:01:13558 */
John Leeaa89aa72020-02-21 01:53:29559 onDrop_(event) {
John Lee7b0b7a62020-03-03 06:00:50560 if (!this.dragSession_) {
John Leec5bf0f22020-02-05 21:01:13561 return;
562 }
563
John Lee7b0b7a62020-03-03 06:00:50564 this.dragSession_.finish(event);
565 this.dragSession_ = null;
John Leec5bf0f22020-02-05 21:01:13566 }
567
John Leeaa89aa72020-02-21 01:53:29568 startObserving() {
569 this.delegate_.addEventListener(
570 'dragstart', e => this.onDragStart_(/** @type {!DragEvent} */ (e)));
571 this.delegate_.addEventListener(
572 'dragend', e => this.onDragEnd_(/** @type {!DragEvent} */ (e)));
John Lee49ccb722020-02-26 03:30:05573 this.delegate_.addEventListener(
John Lee656beed2020-07-07 22:45:52574 'dragenter', e => this.onDragEnter_(/** @type {!DragEvent} */ (e)));
575 this.delegate_.addEventListener(
576 'dragleave', e => this.onDragLeave_(/** @type {!DragEvent} */ (e)));
John Leeaa89aa72020-02-21 01:53:29577 this.delegate_.addEventListener(
578 'dragover', e => this.onDragOver_(/** @type {!DragEvent} */ (e)));
579 this.delegate_.addEventListener(
580 'drop', e => this.onDrop_(/** @type {!DragEvent} */ (e)));
John Leec5bf0f22020-02-05 21:01:13581 }
582}