diff options
Diffstat (limited to 'chromium/chrome/browser/resources/file_manager/foreground/js/directory_tree.js')
-rw-r--r-- | chromium/chrome/browser/resources/file_manager/foreground/js/directory_tree.js | 676 |
1 files changed, 0 insertions, 676 deletions
diff --git a/chromium/chrome/browser/resources/file_manager/foreground/js/directory_tree.js b/chromium/chrome/browser/resources/file_manager/foreground/js/directory_tree.js deleted file mode 100644 index 5c9de7aa0fe..00000000000 --- a/chromium/chrome/browser/resources/file_manager/foreground/js/directory_tree.js +++ /dev/null @@ -1,676 +0,0 @@ -// Copyright (c) 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. - -'use strict'; - -//////////////////////////////////////////////////////////////////////////////// -// DirectoryTreeUtil - -/** - * Utility methods. They are intended for use only in this file. - */ -var DirectoryTreeUtil = {}; - -/** - * Generate a list of the directory entries for the top level on the tree. - * @return {Array.<DirectoryEntry>} Entries for the top level on the tree. - */ -DirectoryTreeUtil.generateTopLevelEntries = function() { - var entries = [ - DirectoryModel.fakeDriveEntry_, - DirectoryModel.fakeDriveOfflineEntry_, - DirectoryModel.fakeDriveSharedWithMeEntry_, - DirectoryModel.fakeDriveRecentEntry_, - ]; - - for (var i = 0; i < entries.length; i++) { - entries[i]['label'] = PathUtil.getRootLabel(entries[i].fullPath); - } - - return entries; -}; - -/** - * Checks if the given directory can be on the tree or not. - * - * @param {string} path Path to be checked. - * @return {boolean} True if the path is eligible for the directory tree. - * Otherwise, false. - */ -DirectoryTreeUtil.isEligiblePathForDirectoryTree = function(path) { - return PathUtil.isDriveBasedPath(path); -}; - -Object.freeze(DirectoryTreeUtil); - -//////////////////////////////////////////////////////////////////////////////// -// DirectoryTreeBase - -/** - * Implementation of methods for DirectoryTree and DirectoryItem. These classes - * inherits cr.ui.Tree/TreeItem so we can't make them inherit this class. - * Instead, we separate their implementations to this separate object and call - * it with setting 'this' from DirectoryTree/Item. - */ -var DirectoryItemTreeBaseMethods = {}; - -/** - * Updates sub-elements of {@code this} reading {@code DirectoryEntry}. - * The list of {@code DirectoryEntry} are not updated by this method. - * - * @param {boolean} recursive True if the all visible sub-directories are - * updated recursively including left arrows. If false, the update walks - * only immediate child directories without arrows. - */ -DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) { - var index = 0; - var tree = this.parentTree_ || this; // If no parent, 'this' itself is tree. - while (this.entries_[index]) { - var currentEntry = this.entries_[index]; - var currentElement = this.items[index]; - - if (index >= this.items.length) { - var item = new DirectoryItem(currentEntry, this, tree); - this.add(item); - index++; - } else if (currentEntry.fullPath == currentElement.fullPath) { - if (recursive && this.expanded) - currentElement.updateSubDirectories(true /* recursive */); - - index++; - } else if (currentEntry.fullPath < currentElement.fullPath) { - var item = new DirectoryItem(currentEntry, this, tree); - this.addAt(item, index); - index++; - } else if (currentEntry.fullPath > currentElement.fullPath) { - this.remove(currentElement); - } - } - - var removedChild; - while (removedChild = this.items[index]) { - this.remove(removedChild); - } - - if (index == 0) { - this.hasChildren = false; - this.expanded = false; - } else { - this.hasChildren = true; - } -}; - -/** - * Finds a parent directory of the {@code entry} in {@code this}, and - * invokes the DirectoryItem.selectByEntry() of the found directory. - * - * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be - * a fake. - * @return {boolean} True if the parent item is found. - */ -DirectoryItemTreeBaseMethods.searchAndSelectByEntry = function(entry) { - for (var i = 0; i < this.items.length; i++) { - var item = this.items[i]; - if (util.isParentEntry(item.entry, entry)) { - item.selectByEntry(entry); - return true; - } - } - return false; -}; - -Object.freeze(DirectoryItemTreeBaseMethods); - -//////////////////////////////////////////////////////////////////////////////// -// DirectoryItem - -/** - * A directory in the tree. Each element represents one directory. - * - * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. - * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. - * @param {DirectoryTree} tree Current tree, which contains this item. - * @extends {cr.ui.TreeItem} - * @constructor - */ -function DirectoryItem(dirEntry, parentDirItem, tree) { - var item = cr.doc.createElement('div'); - DirectoryItem.decorate(item, dirEntry, parentDirItem, tree); - return item; -} - -/** - * @param {HTMLElement} el Element to be DirectoryItem. - * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. - * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. - * @param {DirectoryTree} tree Current tree, which contains this item. - */ -DirectoryItem.decorate = - function(el, dirEntry, parentDirItem, tree) { - el.__proto__ = DirectoryItem.prototype; - (/** @type {DirectoryItem} */ el).decorate( - dirEntry, parentDirItem, tree); -}; - -DirectoryItem.prototype = { - __proto__: cr.ui.TreeItem.prototype, - - /** - * The DirectoryEntry corresponding to this DirectoryItem. This may be - * a dummy DirectoryEntry. - * @type {DirectoryEntry|Object} - */ - get entry() { - return this.dirEntry_; - }, - - /** - * The element containing the label text and the icon. - * @type {!HTMLElement} - * @override - */ - get labelElement() { - return this.firstElementChild.querySelector('.label'); - } -}; - -/** - * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). - * - * @param {boolean} recursive True if the all visible sub-directories are - * updated recursively including left arrows. If false, the update walks - * only immediate child directories without arrows. - */ -DirectoryItem.prototype.updateSubElementsFromList = function(recursive) { - DirectoryItemTreeBaseMethods.updateSubElementsFromList.call(this, recursive); -}; - -/** - * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). - * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be - * a fake. - * @return {boolean} True if the parent item is found. - */ -DirectoryItem.prototype.searchAndSelectByEntry = function(entry) { - return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry); -}; - -/** - * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. - * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. - * @param {DirectoryTree} tree Current tree, which contains this item. - */ -DirectoryItem.prototype.decorate = function( - dirEntry, parentDirItem, tree) { - var path = dirEntry.fullPath; - var label; - label = dirEntry.label ? dirEntry.label : dirEntry.name; - - this.className = 'tree-item'; - this.innerHTML = - '<div class="tree-row">' + - ' <span class="expand-icon"></span>' + - ' <span class="icon"></span>' + - ' <span class="label"></span>' + - '</div>' + - '<div class="tree-children"></div>'; - this.setAttribute('role', 'treeitem'); - - this.parentTree_ = tree; - this.directoryModel_ = tree.directoryModel; - this.parent_ = parentDirItem; - this.label = label; - this.fullPath = path; - this.dirEntry_ = dirEntry; - this.fileFilter_ = this.directoryModel_.getFileFilter(); - - // Sets hasChildren=false tentatively. This will be overridden after - // scanning sub-directories in DirectoryTreeUtil.updateSubElementsFromList. - this.hasChildren = false; - - this.addEventListener('expand', this.onExpand_.bind(this), false); - var icon = this.querySelector('.icon'); - icon.classList.add('volume-icon'); - var iconType = PathUtil.getRootType(path); - if (iconType && PathUtil.isRootPath(path)) - icon.setAttribute('volume-type-icon', iconType); - else - icon.setAttribute('file-type-icon', 'folder'); - - if (this.parentTree_.contextMenuForSubitems) - this.setContextMenu(this.parentTree_.contextMenuForSubitems); - // Adds handler for future change. - this.parentTree_.addEventListener( - 'contextMenuForSubitemsChange', - function(e) { this.setContextMenu(e.newValue); }.bind(this)); - - if (parentDirItem.expanded) - this.updateSubDirectories(false /* recursive */); -}; - -/** - * Overrides WebKit's scrollIntoViewIfNeeded, which doesn't work well with - * a complex layout. This call is not necessary, so we are ignoring it. - * - * @param {boolean} unused Unused. - * @override - */ -DirectoryItem.prototype.scrollIntoViewIfNeeded = function(unused) { -}; - -/** - * Removes the child node, but without selecting the parent item, to avoid - * unintended changing of directories. Removing is done externally, and other - * code will navigate to another directory. - * - * @param {!cr.ui.TreeItem} child The tree item child to remove. - * @override - */ -DirectoryItem.prototype.remove = function(child) { - this.lastElementChild.removeChild(child); - if (this.items.length == 0) - this.hasChildren = false; -}; - -/** - * Invoked when the item is being expanded. - * @param {!UIEvent} e Event. - * @private - **/ -DirectoryItem.prototype.onExpand_ = function(e) { - this.updateSubDirectories( - true /* recursive */, - function() {}, - function() { - this.expanded = false; - }.bind(this)); - - e.stopPropagation(); -}; - -/** - * Retrieves the latest subdirectories and update them on the tree. - * @param {boolean} recursive True if the update is recursively. - * @param {function()=} opt_successCallback Callback called on success. - * @param {function()=} opt_errorCallback Callback called on error. - */ -DirectoryItem.prototype.updateSubDirectories = function( - recursive, opt_successCallback, opt_errorCallback) { - if (util.isFakeEntry(this.entry)) { - if (opt_errorCallback) - opt_errorCallback(); - return; - } - - var sortEntries = function(fileFilter, entries) { - entries.sort(function(a, b) { - return (a.name.toLowerCase() > b.name.toLowerCase()) ? 1 : -1; - }); - return entries.filter(fileFilter.filter.bind(fileFilter)); - }; - - var onSuccess = function(entries) { - this.entries_ = entries; - this.redrawSubDirectoryList_(recursive); - opt_successCallback && opt_successCallback(); - }.bind(this); - - var reader = this.entry.createReader(); - var entries = []; - var readEntry = function() { - reader.readEntries(function(results) { - if (!results.length) { - onSuccess(sortEntries(this.fileFilter_, entries)); - return; - } - - for (var i = 0; i < results.length; i++) { - var entry = results[i]; - if (entry.isDirectory) - entries.push(entry); - } - readEntry(); - }.bind(this)); - }.bind(this); - readEntry(); -}; - -/** - * Updates sub-elements of {@code parentElement} reading {@code DirectoryEntry} - * with calling {@code iterator}. - * - * @param {string} changedDirectryPath The path of the changed directory. - */ -DirectoryItem.prototype.updateItemByPath = function(changedDirectryPath) { - if (changedDirectryPath === this.entry.fullPath) { - this.updateSubDirectories(false /* recursive */); - return; - } - - for (var i = 0; i < this.items.length; i++) { - var item = this.items[i]; - if (PathUtil.isParentPath(item.entry.fullPath, changedDirectryPath)) { - item.updateItemByPath(changedDirectryPath); - break; - } - } -}; - -/** - * Redraw subitems with the latest information. The items are sorted in - * alphabetical order, case insensitive. - * @param {boolean} recursive True if the update is recursively. - * @private - */ -DirectoryItem.prototype.redrawSubDirectoryList_ = function(recursive) { - this.updateSubElementsFromList(recursive); -}; - -/** - * Select the item corresponding to the given {@code entry}. - * @param {DirectoryEntry|Object} entry The entry to be selected. Can be a fake. - */ -DirectoryItem.prototype.selectByEntry = function(entry) { - if (util.isSameEntry(entry, this.entry)) { - this.selected = true; - return; - } - - if (this.searchAndSelectByEntry(entry)) - return; - - // If the path doesn't exist, updates sub directories and tryes again. - this.updateSubDirectories( - false /* recursive */, - this.searchAndSelectByEntry.bind(this, entry)); -}; - -/** - * Executes the assigned action as a drop target. - */ -DirectoryItem.prototype.doDropTargetAction = function() { - this.expanded = true; -}; - -/** - * Executes the assigned action. DirectoryItem performs changeDirectory. - */ -DirectoryItem.prototype.doAction = function() { - if (this.fullPath != this.directoryModel_.getCurrentDirPath()) - this.directoryModel_.changeDirectory(this.fullPath); -}; - -/** - * Sets the context menu for directory tree. - * @param {cr.ui.Menu} menu Menu to be set. - */ -DirectoryItem.prototype.setContextMenu = function(menu) { - if (this.entry && PathUtil.isEligibleForFolderShortcut(this.entry.fullPath)) - cr.ui.contextMenuHandler.setContextMenu(this, menu); -}; - -//////////////////////////////////////////////////////////////////////////////// -// DirectoryTree - -/** - * Tree of directories on the middle bar. This element is also the root of - * items, in other words, this is the parent of the top-level items. - * - * @constructor - * @extends {cr.ui.Tree} - */ -function DirectoryTree() {} - -/** - * Decorates an element. - * @param {HTMLElement} el Element to be DirectoryTree. - * @param {DirectoryModel} directoryModel Current DirectoryModel. - * @param {VolumeManagerWrapper} volumeManager VolumeManager of the system. - */ -DirectoryTree.decorate = function(el, directoryModel, volumeManager) { - el.__proto__ = DirectoryTree.prototype; - (/** @type {DirectoryTree} */ el).decorate(directoryModel, volumeManager); -}; - -DirectoryTree.prototype = { - __proto__: cr.ui.Tree.prototype, - - // DirectoryTree is always expanded. - get expanded() { return true; }, - /** - * @param {boolean} value Not used. - */ - set expanded(value) {}, - - /** - * The DirectoryEntry corresponding to this DirectoryItem. This may be - * a dummy DirectoryEntry. - * @type {DirectoryEntry|Object} - * @override - **/ - get entry() { - return this.dirEntry_; - }, - - /** - * The DirectoryModel this tree corresponds to. - * @type {DirectoryModel} - */ - get directoryModel() { - return this.directoryModel_; - }, - - /** - * The VolumeManager instance of the system. - * @type {VolumeManager} - */ - get volumeManager() { - return this.volumeManager_; - }, -}; - -cr.defineProperty(DirectoryTree, 'contextMenuForSubitems', cr.PropertyKind.JS); - -/** - * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). - * - * @param {boolean} recursive True if the all visible sub-directories are - * updated recursively including left arrows. If false, the update walks - * only immediate child directories without arrows. - */ -DirectoryTree.prototype.updateSubElementsFromList = function(recursive) { - DirectoryItemTreeBaseMethods.updateSubElementsFromList.call(this, recursive); -}; - -/** - * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). - * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be - * a fake. - * @return {boolean} True if the parent item is found. - */ -DirectoryTree.prototype.searchAndSelectByEntry = function(entry) { - return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry); -}; - -/** - * Decorates an element. - * @param {DirectoryModel} directoryModel Current DirectoryModel. - * @param {VolumeManagerWrapper} volumeManager VolumeManager of the system. - */ -DirectoryTree.prototype.decorate = function(directoryModel, volumeManager) { - cr.ui.Tree.prototype.decorate.call(this); - - this.directoryModel_ = directoryModel; - this.volumeManager_ = volumeManager; - this.entries_ = DirectoryTreeUtil.generateTopLevelEntries(); - - this.fileFilter_ = this.directoryModel_.getFileFilter(); - this.fileFilter_.addEventListener('changed', - this.onFilterChanged_.bind(this)); - - this.directoryModel_.addEventListener('directory-changed', - this.onCurrentDirectoryChanged_.bind(this)); - - // Add a handler for directory change. - this.addEventListener('change', function() { - if (this.selectedItem && - (!this.currentEntry_ || - !util.isSameEntry(this.currentEntry_, this.selectedItem.entry))) { - this.currentEntry_ = this.selectedItem.entry; - this.selectedItem.doAction(); - return; - } - }.bind(this)); - - this.privateOnDirectoryChangedBound_ = - this.onDirectoryContentChanged_.bind(this); - chrome.fileBrowserPrivate.onDirectoryChanged.addListener( - this.privateOnDirectoryChangedBound_); - - this.scrollBar_ = MainPanelScrollBar(); - this.scrollBar_.initialize(this.parentNode, this); - - // Once, draws the list with the fake '/drive/' entry. - this.redraw(false /* recursive */); - // Resolves 'My Drive' entry and replaces the fake with the true one. - this.maybeResolveMyDriveRoot_(function() { - // After the true entry is resolved, draws the list again. - this.redraw(true /* recursive */); - }.bind(this)); -}; - -/** - * Select the item corresponding to the given entry. - * @param {DirectoryEntry|Object} entry The directory entry to be selected. Can - * be a fake. - */ -DirectoryTree.prototype.selectByEntry = function(entry) { - // If the target directory is not in the tree, do nothing. - if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(entry.fullPath)) - return; - - this.maybeResolveMyDriveRoot_(function() { - if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry)) - return; - - if (this.searchAndSelectByEntry(entry)) - return; - - this.selectedItem = null; - this.updateSubDirectories( - false /* recursive */, - // Success callback, failure is not handled. - function() { - if (!this.searchAndSelectByEntry(entry)) - this.selectedItem = null; - }.bind(this)); - }.bind(this)); -}; - -/** - * Resolves the My Drive root's entry, if it is a fake. If the entry is already - * resolved to a DirectoryEntry, completionCallback() will be called - * immediately. - * @param {function()} completionCallback Called when the resolving is - * done (or the entry is already resolved), regardless if it is - * successfully done or not. - * @private - */ -DirectoryTree.prototype.maybeResolveMyDriveRoot_ = function( - completionCallback) { - var myDriveItem = this.items[0]; - if (!util.isFakeEntry(myDriveItem.entry)) { - // The entry is already resolved. Don't need to try again. - completionCallback(); - return; - } - - // The entry is a fake. - this.directoryModel_.resolveDirectory( - myDriveItem.fullPath, - function(entry) { - if (!util.isFakeEntry(entry)) - myDriveItem.dirEntry_ = entry; - - completionCallback(); - }, - completionCallback); -}; - -/** - * Retrieves the latest subdirectories and update them on the tree. - * @param {boolean} recursive True if the update is recursively. - * @param {function()=} opt_successCallback Callback called on success. - * @param {function()=} opt_errorCallback Callback called on error. - */ -DirectoryTree.prototype.updateSubDirectories = function( - recursive, opt_successCallback, opt_errorCallback) { - this.entries_ = DirectoryTreeUtil.generateTopLevelEntries(); - this.redraw(recursive); - if (opt_successCallback) - opt_successCallback(); -}; - -/** - * Redraw the list. - * @param {boolean} recursive True if the update is recursively. False if the - * only root items are updated. - */ -DirectoryTree.prototype.redraw = function(recursive) { - this.updateSubElementsFromList(recursive); -}; - -/** - * Invoked when the filter is changed. - * @private - */ -DirectoryTree.prototype.onFilterChanged_ = function() { - // Returns immediately, if the tree is hidden. - if (this.hidden) - return; - - this.redraw(true /* recursive */); -}; - -/** - * Invoked when a directory is changed. - * @param {!UIEvent} event Event. - * @private - */ -DirectoryTree.prototype.onDirectoryContentChanged_ = function(event) { - if (event.eventType == 'changed') { - // TODO: Use Entry instead of urls. This will stop working once migrating - // to separate file systems. See: crbug.com/325052. - if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(event.entry.fullPath)) - return; - - var myDriveItem = this.items[0]; - myDriveItem.updateItemByPath(event.entry.fullPath); - } -}; - -/** - * Invoked when the current directory is changed. - * @param {!UIEvent} event Event. - * @private - */ -DirectoryTree.prototype.onCurrentDirectoryChanged_ = function(event) { - this.selectByEntry(event.newDirEntry); -}; - -/** - * Sets the margin height for the transparent preview panel at the bottom. - * @param {number} margin Margin to be set in px. - */ -DirectoryTree.prototype.setBottomMarginForPanel = function(margin) { - this.style.paddingBottom = margin + 'px'; - this.scrollBar_.setBottomMarginForPanel(margin); -}; - -/** - * Updates the UI after the layout has changed. - */ -DirectoryTree.prototype.relayout = function() { - cr.dispatchSimpleEvent(this, 'relayout'); -}; |