Index: chrome/browser/resources/enhanced_bookmark_manager/js/dnd.js |
diff --git a/chrome/browser/resources/enhanced_bookmark_manager/js/dnd.js b/chrome/browser/resources/enhanced_bookmark_manager/js/dnd.js |
deleted file mode 100644 |
index b4859a6310aaaa38723c993580a05ebc6a181fca..0000000000000000000000000000000000000000 |
--- a/chrome/browser/resources/enhanced_bookmark_manager/js/dnd.js |
+++ /dev/null |
@@ -1,502 +0,0 @@ |
-// Copyright 2013 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. |
- |
-cr.define('dnd', function() { |
- 'use strict'; |
- |
- /** @const */ var BookmarkList = bmm.BookmarkList; |
- /** @const */ var ListItem = cr.ui.ListItem; |
- /** @const */ var TreeItem = cr.ui.TreeItem; |
- |
- /** |
- * Enumeration of valid drop locations relative to an element. These are |
- * bit masks to allow combining multiple locations in a single value. |
- * @enum {number} |
- * @const |
- */ |
- var DropPosition = { |
- NONE: 0, |
- ABOVE: 1, |
- ON: 2, |
- BELOW: 4 |
- }; |
- |
- /** |
- * @type {Object} Drop information calculated in |handleDragOver|. |
- */ |
- var dropDestination = null; |
- |
- /** |
- * @type {number} Timer id used to help minimize flicker. |
- */ |
- var removeDropIndicatorTimer; |
- |
- /** |
- * The element that had a style applied it to indicate the drop location. |
- * This is used to easily remove the style when necessary. |
- * @type {Element} |
- */ |
- var lastIndicatorElement; |
- |
- /** |
- * The style that was applied to indicate the drop location. |
- * @type {string} |
- */ |
- var lastIndicatorClassName; |
- |
- var dropIndicator = { |
- /** |
- * Applies the drop indicator style on the target element and stores that |
- * information to easily remove the style in the future. |
- */ |
- addDropIndicatorStyle: function(indicatorElement, position) { |
- var indicatorStyleName = position == DropPosition.ABOVE ? 'drag-above' : |
- position == DropPosition.BELOW ? 'drag-below' : |
- 'drag-on'; |
- |
- lastIndicatorElement = indicatorElement; |
- lastIndicatorClassName = indicatorStyleName; |
- |
- indicatorElement.classList.add(indicatorStyleName); |
- }, |
- |
- /** |
- * Clears the drop indicator style from the last element was the drop target |
- * so the drop indicator is no longer for that element. |
- */ |
- removeDropIndicatorStyle: function() { |
- if (!lastIndicatorElement || !lastIndicatorClassName) |
- return; |
- lastIndicatorElement.classList.remove(lastIndicatorClassName); |
- lastIndicatorElement = null; |
- lastIndicatorClassName = null; |
- }, |
- |
- /** |
- * Displays the drop indicator on the current drop target to give the |
- * user feedback on where the drop will occur. |
- */ |
- update: function(dropDest) { |
- window.clearTimeout(removeDropIndicatorTimer); |
- |
- var indicatorElement = dropDest.element; |
- var position = dropDest.position; |
- if (dropDest.element instanceof BookmarkList) { |
- // For an empty bookmark list use 'drop-above' style. |
- position = DropPosition.ABOVE; |
- } else if (dropDest.element instanceof TreeItem) { |
- indicatorElement = indicatorElement.querySelector('.tree-row'); |
- } |
- dropIndicator.removeDropIndicatorStyle(); |
- dropIndicator.addDropIndicatorStyle(indicatorElement, position); |
- }, |
- |
- /** |
- * Stop displaying the drop indicator. |
- */ |
- finish: function() { |
- // The use of a timeout is in order to reduce flickering as we move |
- // between valid drop targets. |
- window.clearTimeout(removeDropIndicatorTimer); |
- removeDropIndicatorTimer = window.setTimeout(function() { |
- dropIndicator.removeDropIndicatorStyle(); |
- }, 100); |
- } |
- }; |
- |
- /** |
- * Delay for expanding folder when pointer hovers on folder in tree view in |
- * milliseconds. |
- * @type {number} |
- * @const |
- */ |
- // TODO(yosin): EXPAND_FOLDER_DELAY should follow system settings. 400ms is |
- // taken from Windows default settings. |
- var EXPAND_FOLDER_DELAY = 400; |
- |
- /** |
- * The timestamp when the mouse was over a folder during a drag operation. |
- * Used to open the hovered folder after a certain time. |
- * @type {number} |
- */ |
- var lastHoverOnFolderTimeStamp = 0; |
- |
- /** |
- * Expand a folder if the user has hovered for longer than the specified |
- * time during a drag action. |
- */ |
- function updateAutoExpander(eventTimeStamp, overElement) { |
- // Expands a folder in tree view when pointer hovers on it longer than |
- // EXPAND_FOLDER_DELAY. |
- var hoverOnFolderTimeStamp = lastHoverOnFolderTimeStamp; |
- lastHoverOnFolderTimeStamp = 0; |
- if (hoverOnFolderTimeStamp) { |
- if (eventTimeStamp - hoverOnFolderTimeStamp >= EXPAND_FOLDER_DELAY) |
- overElement.expanded = true; |
- else |
- lastHoverOnFolderTimeStamp = hoverOnFolderTimeStamp; |
- } else if (overElement instanceof TreeItem && |
- bmm.isFolder(overElement.bookmarkNode) && |
- overElement.hasChildren && |
- !overElement.expanded) { |
- lastHoverOnFolderTimeStamp = eventTimeStamp; |
- } |
- } |
- |
- /** |
- * Stores the information abou the bookmark and folders being dragged. |
- * @type {Object} |
- */ |
- var dragData = null; |
- var dragInfo = { |
- handleChromeDragEnter: function(newDragData) { |
- dragData = newDragData; |
- }, |
- clearDragData: function() { |
- dragData = null; |
- }, |
- isDragValid: function() { |
- return !!dragData; |
- }, |
- isSameProfile: function() { |
- return dragData && dragData.sameProfile; |
- }, |
- isDraggingFolders: function() { |
- return dragData && dragData.elements.some(function(node) { |
- return !node.url; |
- }); |
- }, |
- isDraggingBookmark: function(bookmarkId) { |
- return dragData && dragData.elements.some(function(node) { |
- return node.id == bookmarkId; |
- }); |
- }, |
- isDraggingChildBookmark: function(folderId) { |
- return dragData && dragData.elements.some(function(node) { |
- return node.parentId == folderId; |
- }); |
- }, |
- isDraggingFolderToDescendant: function(bookmarkNode) { |
- return dragData && dragData.elements.some(function(node) { |
- var dragFolder = bmm.treeLookup[node.id]; |
- var dragFolderNode = dragFolder && dragFolder.bookmarkNode; |
- return dragFolderNode && bmm.contains(dragFolderNode, bookmarkNode); |
- }); |
- } |
- }; |
- |
- /** |
- * External function to select folders or bookmarks after a drop action. |
- * @type {function} |
- */ |
- var selectItemsAfterUserAction = null; |
- |
- function getBookmarkElement(el) { |
- while (el && !el.bookmarkNode) { |
- el = el.parentNode; |
- } |
- return el; |
- } |
- |
- // If we are over the list and the list is showing search result, we cannot |
- // drop. |
- function isOverSearch(overElement) { |
- return list.isSearch() && list.contains(overElement); |
- } |
- |
- /** |
- * Determines the valid drop positions for the given target element. |
- * @param {!HTMLElement} overElement The element that we are currently |
- * dragging over. |
- * @return {DropPosition} An bit field enumeration of valid drop locations. |
- */ |
- function calculateValidDropTargets(overElement) { |
- if (!dragInfo.isDragValid() || isOverSearch(overElement)) |
- return DropPosition.NONE; |
- |
- if (dragInfo.isSameProfile() && |
- (dragInfo.isDraggingBookmark(overElement.bookmarkNode.id) || |
- dragInfo.isDraggingFolderToDescendant(overElement.bookmarkNode))) { |
- return DropPosition.NONE; |
- } |
- |
- var canDropInfo = calculateDropAboveBelow(overElement); |
- if (canDropOn(overElement)) |
- canDropInfo |= DropPosition.ON; |
- |
- return canDropInfo; |
- } |
- |
- function calculateDropAboveBelow(overElement) { |
- if (overElement instanceof BookmarkList) |
- return DropPosition.NONE; |
- |
- // We cannot drop between Bookmarks bar and Other bookmarks. |
- if (overElement.bookmarkNode.parentId == bmm.ROOT_ID) |
- return DropPosition.NONE; |
- |
- var isOverTreeItem = overElement instanceof TreeItem; |
- var isOverExpandedTree = isOverTreeItem && overElement.expanded; |
- var isDraggingFolders = dragInfo.isDraggingFolders(); |
- |
- // We can only drop between items in the tree if we have any folders. |
- if (isOverTreeItem && !isDraggingFolders) |
- return DropPosition.NONE; |
- |
- // When dragging from a different profile we do not need to consider |
- // conflicts between the dragged items and the drop target. |
- if (!dragInfo.isSameProfile()) { |
- // Don't allow dropping below an expanded tree item since it is confusing |
- // to the user anyway. |
- return isOverExpandedTree ? DropPosition.ABOVE : |
- (DropPosition.ABOVE | DropPosition.BELOW); |
- } |
- |
- var resultPositions = DropPosition.NONE; |
- |
- // Cannot drop above if the item above is already in the drag source. |
- var previousElem = overElement.previousElementSibling; |
- if (!previousElem || !dragInfo.isDraggingBookmark(previousElem.bookmarkId)) |
- resultPositions |= DropPosition.ABOVE; |
- |
- // Don't allow dropping below an expanded tree item since it is confusing |
- // to the user anyway. |
- if (isOverExpandedTree) |
- return resultPositions; |
- |
- // Cannot drop below if the item below is already in the drag source. |
- var nextElement = overElement.nextElementSibling; |
- if (!nextElement || !dragInfo.isDraggingBookmark(nextElement.bookmarkId)) |
- resultPositions |= DropPosition.BELOW; |
- |
- return resultPositions; |
- } |
- |
- /** |
- * Determine whether we can drop the dragged items on the drop target. |
- * @param {!HTMLElement} overElement The element that we are currently |
- * dragging over. |
- * @return {boolean} Whether we can drop the dragged items on the drop |
- * target. |
- */ |
- function canDropOn(overElement) { |
- // We can only drop on a folder. |
- if (!bmm.isFolder(overElement.bookmarkNode)) |
- return false; |
- |
- if (!dragInfo.isSameProfile()) |
- return true; |
- |
- if (overElement instanceof BookmarkList) { |
- // We are trying to drop an item past the last item. This is |
- // only allowed if dragged item is different from the last item |
- // in the list. |
- var listItems = list.items; |
- var len = listItems.length; |
- if (!len || !dragInfo.isDraggingBookmark(listItems[len - 1].bookmarkId)) |
- return true; |
- } |
- |
- return !dragInfo.isDraggingChildBookmark(overElement.bookmarkNode.id); |
- } |
- |
- /** |
- * Callback for the dragstart event. |
- * @param {Event} e The dragstart event. |
- */ |
- function handleDragStart(e) { |
- // Determine the selected bookmarks. |
- var target = e.target; |
- var draggedNodes = []; |
- if (target instanceof ListItem) { |
- // Use selected items. |
- draggedNodes = target.parentNode.selectedItems; |
- } else if (target instanceof TreeItem) { |
- draggedNodes.push(target.bookmarkNode); |
- } |
- |
- // We manage starting the drag by using the extension API. |
- e.preventDefault(); |
- |
- if (draggedNodes.length) { |
- // If we are dragging a single link, we can do the *Link* effect. |
- // Otherwise, we only allow copy and move. |
- e.dataTransfer.effectAllowed = draggedNodes.length == 1 && |
- !bmm.isFolder(draggedNodes[0]) ? 'copyMoveLink' : 'copyMove'; |
- |
- chrome.bookmarkManagerPrivate.startDrag(draggedNodes.map(function(node) { |
- return node.id; |
- })); |
- } |
- } |
- |
- function handleDragEnter(e) { |
- e.preventDefault(); |
- } |
- |
- /** |
- * Calback for the dragover event. |
- * @param {Event} e The dragover event. |
- */ |
- function handleDragOver(e) { |
- // Allow DND on text inputs. |
- if (e.target.tagName != 'INPUT') { |
- // The default operation is to allow dropping links etc to do navigation. |
- // We never want to do that for the bookmark manager. |
- e.preventDefault(); |
- |
- // Set to none. This will get set to something if we can do the drop. |
- e.dataTransfer.dropEffect = 'none'; |
- } |
- |
- if (!dragInfo.isDragValid()) |
- return; |
- |
- var overElement = getBookmarkElement(e.target) || |
- (e.target == list ? list : null); |
- if (!overElement) |
- return; |
- |
- updateAutoExpander(e.timeStamp, overElement); |
- |
- var canDropInfo = calculateValidDropTargets(overElement); |
- if (canDropInfo == DropPosition.NONE) |
- return; |
- |
- // Now we know that we can drop. Determine if we will drop above, on or |
- // below based on mouse position etc. |
- |
- dropDestination = calcDropPosition(e.clientY, overElement, canDropInfo); |
- if (!dropDestination) { |
- e.dataTransfer.dropEffect = 'none'; |
- return; |
- } |
- |
- e.dataTransfer.dropEffect = dragInfo.isSameProfile() ? 'move' : 'copy'; |
- dropIndicator.update(dropDestination); |
- } |
- |
- /** |
- * This function determines where the drop will occur relative to the element. |
- * @return {?Object} If no valid drop position is found, null, otherwise |
- * an object containing the following parameters: |
- * element - The target element that will receive the drop. |
- * position - A |DropPosition| relative to the |element|. |
- */ |
- function calcDropPosition(elementClientY, overElement, canDropInfo) { |
- if (overElement instanceof BookmarkList) { |
- // Dropping on the BookmarkList either means dropping below the last |
- // bookmark element or on the list itself if it is empty. |
- var length = overElement.items.length; |
- if (length) |
- return { |
- element: overElement.getListItemByIndex(length - 1), |
- position: DropPosition.BELOW |
- }; |
- return {element: overElement, position: DropPosition.ON}; |
- } |
- |
- var above = canDropInfo & DropPosition.ABOVE; |
- var below = canDropInfo & DropPosition.BELOW; |
- var on = canDropInfo & DropPosition.ON; |
- var rect = overElement.getBoundingClientRect(); |
- var yRatio = (elementClientY - rect.top) / rect.height; |
- |
- if (above && (yRatio <= .25 || yRatio <= .5 && (!below || !on))) |
- return {element: overElement, position: DropPosition.ABOVE}; |
- if (below && (yRatio > .75 || yRatio > .5 && (!above || !on))) |
- return {element: overElement, position: DropPosition.BELOW}; |
- if (on) |
- return {element: overElement, position: DropPosition.ON}; |
- return null; |
- } |
- |
- function calculateDropInfo(eventTarget, dropDestination) { |
- if (!dropDestination || !dragInfo.isDragValid()) |
- return null; |
- |
- var dropPos = dropDestination.position; |
- var relatedNode = dropDestination.element.bookmarkNode; |
- var dropInfoResult = { |
- selectTarget: null, |
- selectedTreeId: -1, |
- parentId: dropPos == DropPosition.ON ? relatedNode.id : |
- relatedNode.parentId, |
- index: -1, |
- relatedIndex: -1 |
- }; |
- |
- // Try to find the index in the dataModel so we don't have to always keep |
- // the index for the list items up to date. |
- var overElement = getBookmarkElement(eventTarget); |
- if (overElement instanceof ListItem) { |
- dropInfoResult.relatedIndex = |
- overElement.parentNode.dataModel.indexOf(relatedNode); |
- dropInfoResult.selectTarget = list; |
- } else if (overElement instanceof BookmarkList) { |
- dropInfoResult.relatedIndex = overElement.dataModel.length - 1; |
- dropInfoResult.selectTarget = list; |
- } else { |
- // Tree |
- dropInfoResult.relatedIndex = relatedNode.index; |
- dropInfoResult.selectTarget = tree; |
- dropInfoResult.selectedTreeId = |
- tree.selectedItem ? tree.selectedItem.bookmarkId : null; |
- } |
- |
- if (dropPos == DropPosition.ABOVE) |
- dropInfoResult.index = dropInfoResult.relatedIndex; |
- else if (dropPos == DropPosition.BELOW) |
- dropInfoResult.index = dropInfoResult.relatedIndex + 1; |
- |
- return dropInfoResult; |
- } |
- |
- function handleDragLeave(e) { |
- dropIndicator.finish(); |
- } |
- |
- function handleDrop(e) { |
- var dropInfo = calculateDropInfo(e.target, dropDestination); |
- if (dropInfo) { |
- selectItemsAfterUserAction(dropInfo.selectTarget, |
- dropInfo.selectedTreeId); |
- if (dropInfo.index != -1) |
- chrome.bookmarkManagerPrivate.drop(dropInfo.parentId, dropInfo.index); |
- else |
- chrome.bookmarkManagerPrivate.drop(dropInfo.parentId); |
- |
- e.preventDefault(); |
- } |
- dropDestination = null; |
- dropIndicator.finish(); |
- } |
- |
- function clearDragData() { |
- dragInfo.clearDragData(); |
- dropDestination = null; |
- } |
- |
- function init(selectItemsAfterUserActionFunction) { |
- function deferredClearData() { |
- setTimeout(clearDragData); |
- } |
- |
- selectItemsAfterUserAction = selectItemsAfterUserActionFunction; |
- |
- document.addEventListener('dragstart', handleDragStart); |
- document.addEventListener('dragenter', handleDragEnter); |
- document.addEventListener('dragover', handleDragOver); |
- document.addEventListener('dragleave', handleDragLeave); |
- document.addEventListener('drop', handleDrop); |
- document.addEventListener('dragend', deferredClearData); |
- document.addEventListener('mouseup', deferredClearData); |
- |
- chrome.bookmarkManagerPrivate.onDragEnter.addListener( |
- dragInfo.handleChromeDragEnter); |
- chrome.bookmarkManagerPrivate.onDragLeave.addListener(deferredClearData); |
- chrome.bookmarkManagerPrivate.onDrop.addListener(deferredClearData); |
- } |
- return {init: init}; |
-}); |