Commit 8cf64121 authored by Kristi Park's avatar Kristi Park Committed by Commit Bot

[NTP] Allow dragging of shortcuts to the omnibox with grid layout

Convert mouse events to drag events. This allows us to use DataTransfer
to set the URL data necessary for dragging and dropping links.

Screencast: https://drive.google.com/open?id=131GJk4um_TGzgXxQ3KeQcDfJ87jh-W19

Bug: 961569
Change-Id: I8460a5e101f167efa15f34ca810244c9edd46900
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1686789
Commit-Queue: Kristi Park <kristipark@chromium.org>
Reviewed-by: default avatarKyle Milka <kmilka@chromium.org>
Cr-Commit-Position: refs/heads/master@{#675802}
parent 050530ec
......@@ -106,11 +106,6 @@ html:not(.no-initial-fade) :-webkit-any(#mv-tiles, .mv-tiles-old) {
transition: transform 300ms ease-in-out;
}
/* Prevent navigation while we're reordering the tiles. */
body.reordering .grid-tile {
pointer-events: none;
}
/* Prevent transitions on the held tile in order for it to smoothly follow the
* mouse. */
.grid-reorder .grid-tile {
......
......@@ -489,15 +489,18 @@ class Grid {
// Listen for the drag event on the tile instead of the tile container. The
// tile container remains static during the reorder flow.
tile.firstChild.draggable = true;
// Prevent default drag events on the shortcut link.
const tileItem = tile.firstChild.firstChild;
tileItem.draggable = false;
tile.firstChild.addEventListener('dragstart', (event) => {
// Support link dragging (i.e. dragging the URL to the omnibox).
event.dataTransfer.setData('text/uri-list', tileItem.href);
// Remove the ghost image that appears when dragging.
const emptyImg = new Image();
event.dataTransfer.setDragImage(emptyImg, 0, 0);
this.startReorder_(tile, event, /*mouseMode=*/ true);
});
// Listen for the mouseover event on the tile container. If this is placed
// on the tile instead, it can be triggered while the tile is translated to
// its new position.
tile.addEventListener('mouseover', (event) => {
this.reorderToIndex_(index);
});
// Set up touch support.
tile.firstChild.addEventListener('touchstart', (startEvent) => {
......@@ -516,17 +519,12 @@ class Grid {
// Insert the held tile at the index we are hovering over.
const moveOver = (moveEvent) => {
// Touch events do not have a 'mouseover' equivalent, so we need to
// manually check if we are hovering over a tile.
// manually check if we are hovering over a tile. If so, insert the held
// tile there.
// Note: The first item in |changedTouches| is the current position.
const x = moveEvent.changedTouches[0].pageX;
const y = moveEvent.changedTouches[0].pageY;
const elements = document.elementsFromPoint(x, y);
for (let i = 0; i < elements.length; i++) {
if (elements[i].classList.contains('grid-tile-container')) {
this.reorderToIndex_(Number(elements[i].getAttribute('index')));
break;
}
}
this.reorderToIndexAtPoint_(x, y);
};
// Allow 'touchstart' events again when reordering stops/was never
// started.
......@@ -565,13 +563,24 @@ class Grid {
// Disable other hover/active styling for all tiles.
document.body.classList.add(CLASSES.REORDERING);
// Set up event listeners for the reorder flow. Listen for mouse events if
// Set up event listeners for the reorder flow. Listen for drag events if
// |mouseMode|, touch events otherwise.
if (mouseMode) {
const mouseMove = this.trackCursor_(tile, event.pageX, event.pageY, true);
document.addEventListener('mousemove', mouseMove);
document.addEventListener('mouseup', () => {
document.removeEventListener('mousemove', mouseMove);
const trackCursor =
this.trackCursor_(tile, event.pageX, event.pageY, true);
// The 'dragover' event must be tracked at the document level, since the
// currently dragged tile will interfere with 'dragover' events on the
// other tiles.
const dragOver = (dragOverEvent) => {
trackCursor(dragOverEvent);
// Since the 'dragover' event is not tied to a specific tile, we need to
// manually check if we are hovering over a tile. If so, insert the held
// tile there.
this.reorderToIndexAtPoint_(dragOverEvent.pageX, dragOverEvent.pageY);
};
document.addEventListener('dragover', dragOver);
document.addEventListener('dragend', () => {
document.removeEventListener('dragover', dragOver);
this.stopReorder_(tile);
}, {once: true});
} else {
......@@ -580,7 +589,7 @@ class Grid {
const trackCursor = this.trackCursor_(
tile, event.changedTouches[0].pageX, event.changedTouches[0].pageY,
false);
const touchEnd = (event) => {
const touchEnd = (touchEndEvent) => {
tile.firstChild.removeEventListener('touchmove', trackCursor);
tile.firstChild.removeEventListener('touchend', touchEnd);
tile.firstChild.removeEventListener('touchcancel', touchEnd);
......@@ -616,6 +625,25 @@ class Grid {
this.newIndexOfItemToReorder_ = -1;
}
/**
* Attempts to insert the currently held tile at the index located at (x, y).
* Does nothing if there is no tile at (x, y) or the reorder flow is not
* ongoing.
* @param {number} x The x coordinate.
* @param {number} y The y coordinate.
* @private
*/
reorderToIndexAtPoint_(x, y) {
const elements = document.elementsFromPoint(x, y);
for (let i = 0; i < elements.length; i++) {
if (elements[i].classList.contains('grid-tile-container') &&
elements[i].getAttribute('index') !== null) {
this.reorderToIndex_(Number(elements[i].getAttribute('index')));
return;
}
}
}
/**
* Executed only when the reorder flow is ongoing. Inserts the currently held
* tile at |index| and shifts tiles accordingly.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment