Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Unified Diff: ui/file_manager/file_manager/foreground/js/ui/directory_tree.js

Issue 645853013: Remove some platform specific stuff from views. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
deleted file mode 100644
index 49b103525fe71ba3a821f930ec3c426eb0ed847a..0000000000000000000000000000000000000000
--- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
+++ /dev/null
@@ -1,1134 +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';
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
- * @this {DirectoryItem}
- */
-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];
- var label = util.getEntryLabel(tree.volumeManager_, currentEntry);
-
- if (index >= this.items.length) {
- var item = new DirectoryItem(label, currentEntry, this, tree);
- this.add(item);
- index++;
- } else if (util.isSameEntry(currentEntry, currentElement.entry)) {
- currentElement.updateSharedStatusIcon();
- if (recursive && this.expanded)
- currentElement.updateSubDirectories(true /* recursive */);
-
- index++;
- } else if (currentEntry.toURL() < currentElement.entry.toURL()) {
- var item = new DirectoryItem(label, currentEntry, this, tree);
- this.addAt(item, index);
- index++;
- } else if (currentEntry.toURL() > currentElement.entry.toURL()) {
- 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.
- * @this {(DirectoryItem|VolumeItem|DirectoryTree)}
- */
-DirectoryItemTreeBaseMethods.searchAndSelectByEntry = function(entry) {
- for (var i = 0; i < this.items.length; i++) {
- var item = this.items[i];
- if (util.isDescendantEntry(item.entry, entry) ||
- util.isSameEntry(item.entry, entry)) {
- item.selectByEntry(entry);
- return true;
- }
- }
- return false;
-};
-
-Object.freeze(DirectoryItemTreeBaseMethods);
-
-var TREE_ITEM_INNTER_HTML =
- '<div class="tree-row">' +
- ' <span class="expand-icon"></span>' +
- ' <span class="icon"></span>' +
- ' <span class="label entry-name"></span>' +
- '</div>' +
- '<div class="tree-children"></div>';
-
-////////////////////////////////////////////////////////////////////////////////
-// DirectoryItem
-
-/**
- * A directory in the tree. Each element represents one directory.
- *
- * @param {string} label Label for this item.
- * @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
- * @param {DirectoryItem|VolumeItem|ShortcutItem|DirectoryTree} parentDirItem
- * Parent of this item.
- * @param {DirectoryTree} tree Current tree, which contains this item.
- * @extends {cr.ui.TreeItem}
- * @constructor
- */
-function DirectoryItem(label, dirEntry, parentDirItem, tree) {
- var item = new cr.ui.TreeItem();
- DirectoryItem.decorate(item, label, dirEntry, parentDirItem, tree);
- return item;
-}
-
-/**
- * @param {HTMLElement} el Element to be DirectoryItem.
- * @param {string} label Label for this item.
- * @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
- * @param {DirectoryItem|VolumeItem|ShortcutItem|DirectoryTree} parentDirItem
- * Parent of this item.
- * @param {DirectoryTree} tree Current tree, which contains this item.
- */
-DirectoryItem.decorate =
- function(el, label, dirEntry, parentDirItem, tree) {
- el.__proto__ = DirectoryItem.prototype;
- /** @type {DirectoryItem} */ (el).decorate(
- label, 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 {string} label Localized label for this item.
- * @param {DirectoryEntry} dirEntry DirectoryEntry of this item.
- * @param {DirectoryItem|VolumeItem|ShortcutItem|DirectoryTree} parentDirItem
- * Parent of this item.
- * @param {DirectoryTree} tree Current tree, which contains this item.
- */
-DirectoryItem.prototype.decorate = function(
- label, dirEntry, parentDirItem, tree) {
- this.innerHTML = TREE_ITEM_INNTER_HTML;
- this.parentTree_ = tree;
- this.directoryModel_ = tree.directoryModel;
- this.parent_ = parentDirItem;
- this.label = label;
- this.dirEntry_ = dirEntry;
- this.fileFilter_ = this.directoryModel_.getFileFilter();
-
- // Sets hasChildren=false tentatively. This will be overridden after
- // scanning sub-directories in updateSubElementsFromList().
- this.hasChildren = false;
-
- this.addEventListener('expand', this.onExpand_.bind(this), false);
- var icon = this.querySelector('.icon');
- icon.classList.add('volume-icon');
- var location = tree.volumeManager.getLocationInfo(dirEntry);
- if (location && location.rootType && location.isRootEntry) {
- icon.setAttribute('volume-type-icon', location.rootType);
- } else {
- icon.setAttribute('file-type-icon', 'folder');
- this.updateSharedStatusIcon();
- }
-
- 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 {!Event} e Event.
- * @private
- **/
-DirectoryItem.prototype.onExpand_ = function(e) {
- this.updateSubDirectories(
- true /* recursive */,
- function() {},
- function() {
- this.expanded = false;
- }.bind(this));
-
- e.stopPropagation();
-};
-
-/**
- * Invoked when the tree item is clicked.
- *
- * @param {Event} e Click event.
- * @override
- */
-DirectoryItem.prototype.handleClick = function(e) {
- cr.ui.TreeItem.prototype.handleClick.call(this, e);
- if (!e.target.classList.contains('expand-icon'))
- this.directoryModel_.activateDirectoryEntry(this.entry);
-};
-
-/**
- * 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(util.compareName);
- 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();
-};
-
-/**
- * Searches for the changed directory in the current subtree, and if it is found
- * then updates it.
- *
- * @param {DirectoryEntry} changedDirectoryEntry The entry ot the changed
- * directory.
- */
-DirectoryItem.prototype.updateItemByEntry = function(changedDirectoryEntry) {
- if (util.isSameEntry(changedDirectoryEntry, this.entry)) {
- this.updateSubDirectories(false /* recursive */);
- return;
- }
-
- // Traverse the entire subtree to find the changed element.
- for (var i = 0; i < this.items.length; i++) {
- var item = this.items[i];
- if (util.isDescendantEntry(item.entry, changedDirectoryEntry) ||
- util.isSameEntry(item.entry, changedDirectoryEntry)) {
- item.updateItemByEntry(changedDirectoryEntry);
- break;
- }
- }
-};
-
-/**
- * Update the icon based on whether the folder is shared on Drive.
- */
-DirectoryItem.prototype.updateSharedStatusIcon = function() {
- var icon = this.querySelector('.icon');
- this.parentTree_.metadataCache.getLatest(
- [this.dirEntry_],
- 'external',
- function(metadata) {
- icon.classList.toggle('shared', metadata[0] && metadata[0].shared);
- });
-};
-
-/**
- * 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 entry doesn't exist, updates sub directories and tries 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;
-};
-
-/**
- * Sets the context menu for directory tree.
- * @param {!cr.ui.Menu} menu Menu to be set.
- */
-DirectoryItem.prototype.setContextMenu = function(menu) {
- var tree = this.parentTree_ || this; // If no parent, 'this' itself is tree.
- var locationInfo = tree.volumeManager_.getLocationInfo(this.entry);
- if (locationInfo && locationInfo.isEligibleForFolderShortcut)
- cr.ui.contextMenuHandler.setContextMenu(this, menu);
-};
-
-/**
- * Change current directory to the entry of this item.
- */
-DirectoryItem.prototype.activate = function() {
- this.parentTree_.directoryModel.activateDirectoryEntry(this.entry);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// VolumeItem
-
-/**
- * A TreeItem which represents a volume. Volume items are displayed as
- * top-level children of DirectoryTree.
- *
- * @param {NavigationModelItem} modelItem NavigationModelItem of this volume.
- * @param {DirectoryTree} tree Current tree, which contains this item.
- * @extends {cr.ui.TreeItem}
- * @constructor
- */
-function VolumeItem(modelItem, tree) {
- var item = new cr.ui.TreeItem();
- item.__proto__ = VolumeItem.prototype;
- item.decorate(modelItem, tree);
- return item;
-}
-
-VolumeItem.prototype = {
- __proto__: cr.ui.TreeItem.prototype,
- get entry() {
- return this.volumeInfo_.displayRoot;
- },
- get modelItem() {
- return this.modelItem_;
- },
- get volumeInfo() {
- return this.volumeInfo_;
- },
- get labelElement() {
- return this.firstElementChild.querySelector('.label');
- },
- // Overrides the property 'expanded' to prevent volume items from shrinking.
- get expanded() {
- return Object.getOwnPropertyDescriptor(
- cr.ui.TreeItem.prototype, 'expanded').get.call(this);
- },
- set expanded(b) {
- if (!b)
- return;
- Object.getOwnPropertyDescriptor(
- cr.ui.TreeItem.prototype, 'expanded').set.call(this, b);
- }
-};
-
-/**
- * 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.
- */
-VolumeItem.prototype.searchAndSelectByEntry = function(entry) {
- return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry);
-};
-
-/**
- * Decorates this element.
- * @param {NavigationModelItem} modelItem NavigationModelItem of this volume.
- * @param {DirectoryTree} tree Current tree, which contains this item.
- */
-VolumeItem.prototype.decorate = function(modelItem, tree) {
- this.innerHTML = TREE_ITEM_INNTER_HTML;
- this.parentTree_ = tree;
- this.modelItem_ = modelItem;
- this.volumeInfo_ = modelItem.volumeInfo;
- this.label = modelItem.volumeInfo.label;
-
- this.setupIcon_(this.querySelector('.icon'), this.volumeInfo);
- this.setupEjectButton_(this.rowElement);
- if (tree.contextMenuForRootItems)
- this.setContextMenu(tree.contextMenuForRootItems);
-
- // Populate children of this volume using resolved display root.
- this.volumeInfo_.resolveDisplayRoot(function(displayRoot) {
- this.updateSubDirectories(false /* recursive */);
- }.bind(this));
-};
-
-/**
- * Invoked when the tree item is clicked.
- *
- * @param {Event} e Click event.
- * @override
- */
-VolumeItem.prototype.handleClick = function(e) {
- // If the currently selected volume is clicked, change current directory to
- // the volume's root.
- if (this.selected)
- this.activate();
-
- cr.ui.TreeItem.prototype.handleClick.call(this, e);
-
- // Resets file selection when a volume is clicked.
- this.parentTree_.directoryModel.clearSelection();
-
- // If the Drive volume is clicked, select one of the children instead of this
- // item itself.
- if (this.isDrive()) {
- this.volumeInfo_.resolveDisplayRoot(function(displayRoot) {
- this.searchAndSelectByEntry(displayRoot);
- }.bind(this));
- }
-};
-
-/**
- * Retrieves the latest subdirectories and update them on the tree.
- * @param {boolean} recursive True if the update is recursively.
- */
-VolumeItem.prototype.updateSubDirectories = function(recursive) {
- // Drive volume has children including fake entries (offline, recent, etc...).
- if (this.isDrive() && this.entry && !this.hasChildren) {
- var entries = [this.entry];
- if (this.parentTree_.fakeEntriesVisible_) {
- for (var key in this.volumeInfo.fakeEntries)
- entries.push(this.volumeInfo.fakeEntries[key]);
- }
- // This list is sorted by URL on purpose.
- entries.sort(function(a, b) {
- if (a.toURL() === b.toURL())
- return 0;
- return b.toURL() > a.toURL() ? 1 : -1;
- });
-
- for (var i = 0; i < entries.length; i++) {
- var item = new DirectoryItem(
- util.getEntryLabel(this.parentTree_.volumeManager_, entries[i]),
- entries[i], this, this.parentTree_);
- this.add(item);
- item.updateSubDirectories(false);
- }
- this.expanded = true;
- }
-};
-
-/**
- * Searches for the changed directory in the current subtree, and if it is found
- * then updates it.
- *
- * @param {DirectoryEntry} changedDirectoryEntry The entry ot the changed
- * directory.
- */
-VolumeItem.prototype.updateItemByEntry = function(changedDirectoryEntry) {
- if (this.isDrive())
- this.items[0].updateItemByEntry(changedDirectoryEntry);
-};
-
-/**
- * Select the item corresponding to the given entry.
- * @param {DirectoryEntry|Object} entry The directory entry to be selected. Can
- * be a fake.
- */
-VolumeItem.prototype.selectByEntry = function(entry) {
- // If this volume is drive, find the item to be selected amang children.
- if (this.isDrive()) {
- this.searchAndSelectByEntry(entry);
- return;
- }
- if (util.isSameEntry(this.entry, entry) ||
- util.isDescendantEntry(this.entry, entry))
- this.selected = true;
-};
-
-/**
- * Sets the context menu for volume items.
- * @param {!cr.ui.Menu} menu Menu to be set.
- */
-VolumeItem.prototype.setContextMenu = function(menu) {
- if (this.isRemovable_())
- cr.ui.contextMenuHandler.setContextMenu(this, menu);
-};
-
-/**
- * Change current entry to this volume's root directory.
- */
-VolumeItem.prototype.activate = function() {
- var directoryModel = this.parentTree_.directoryModel;
- var onEntryResolved = function(entry) {
- // Changes directory to the model item's root directory if needed.
- if (!util.isSameEntry(directoryModel.getCurrentDirEntry(), entry)) {
- metrics.recordUserAction('FolderShortcut.Navigate');
- directoryModel.changeDirectoryEntry(entry);
- }
- // In case of failure in resolveDisplayRoot() in the volume's decorate(),
- // update the volume's children here.
- this.updateSubDirectories(false);
- }.bind(this);
-
- this.volumeInfo.resolveDisplayRoot(
- onEntryResolved,
- function() {
- // Error, the display root is not available. It may happen on Drive.
- this.parentTree_.dataModel.onItemNotFoundError(this.modelItem);
- }.bind(this));
-};
-
-/**
- * @return {boolean} True if this is Drive volume.
- */
-VolumeItem.prototype.isDrive = function() {
- return this.volumeInfo.volumeType === VolumeManagerCommon.VolumeType.DRIVE;
-};
-
-/**
- * @return {boolean} True if this volume can be removed by user operation.
- * @private
- */
-VolumeItem.prototype.isRemovable_ = function() {
- var volumeType = this.volumeInfo.volumeType;
- return volumeType === VolumeManagerCommon.VolumeType.ARCHIVE ||
- volumeType === VolumeManagerCommon.VolumeType.REMOVABLE ||
- volumeType === VolumeManagerCommon.VolumeType.PROVIDED;
-};
-
-/**
- * Set up icon of this volume item.
- * @param {Element} icon Icon element to be setup.
- * @param {VolumeInfo} volumeInfo VolumeInfo determines the icon type.
- * @private
- */
-VolumeItem.prototype.setupIcon_ = function(icon, volumeInfo) {
- icon.classList.add('volume-icon');
- if (volumeInfo.volumeType === 'provided') {
- var backgroundImage = '-webkit-image-set(' +
- 'url(chrome://extension-icon/' + volumeInfo.extensionId +
- '/24/1) 1x, ' +
- 'url(chrome://extension-icon/' + volumeInfo.extensionId +
- '/48/1) 2x);';
- // The icon div is not yet added to DOM, therefore it is impossible to
- // use style.backgroundImage.
- icon.setAttribute(
- 'style', 'background-image: ' + backgroundImage);
- }
- icon.setAttribute('volume-type-icon', volumeInfo.volumeType);
- icon.setAttribute('volume-subtype', volumeInfo.deviceType || '');
-};
-
-/**
- * Set up eject button if needed.
- * @param {HTMLElement} rowElement The parent element for eject button.
- * @private
- */
-VolumeItem.prototype.setupEjectButton_ = function(rowElement) {
- if (this.isRemovable_()) {
- var ejectButton = cr.doc.createElement('div');
- // Block other mouse handlers.
- ejectButton.addEventListener(
- 'mouseup', function(event) { event.stopPropagation() });
- ejectButton.addEventListener(
- 'mousedown', function(event) { event.stopPropagation() });
- ejectButton.className = 'root-eject';
- ejectButton.addEventListener('click', function(event) {
- event.stopPropagation();
- var unmountCommand = cr.doc.querySelector('command#unmount');
- // Let's make sure 'canExecute' state of the command is properly set for
- // the root before executing it.
- unmountCommand.canExecuteChange(this);
- unmountCommand.execute(this);
- }.bind(this));
- rowElement.appendChild(ejectButton);
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// ShortcutItem
-
-/**
- * A TreeItem which represents a shortcut for Drive folder.
- * Shortcut items are displayed as top-level children of DirectoryTree.
- *
- * @param {NavigationModelItem} modelItem NavigationModelItem of this volume.
- * @param {DirectoryTree} tree Current tree, which contains this item.
- * @extends {cr.ui.TreeItem}
- * @constructor
- */
-function ShortcutItem(modelItem, tree) {
- var item = new cr.ui.TreeItem();
- item.__proto__ = ShortcutItem.prototype;
- item.decorate(modelItem, tree);
- return item;
-}
-
-ShortcutItem.prototype = {
- __proto__: cr.ui.TreeItem.prototype,
- get entry() {
- return this.dirEntry_;
- },
- get modelItem() {
- return this.modelItem_;
- },
- get labelElement() {
- return this.firstElementChild.querySelector('.label');
- }
-};
-
-/**
- * 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.
- */
-ShortcutItem.prototype.searchAndSelectByEntry = function(entry) {
- // Always false as shortcuts have no children.
- return false;
-};
-
-/**
- * Decorates this element.
- * @param {NavigationModelItem} modelItem NavigationModelItem of this volume.
- * @param {DirectoryTree} tree Current tree, which contains this item.
- */
-ShortcutItem.prototype.decorate = function(modelItem, tree) {
- this.innerHTML = TREE_ITEM_INNTER_HTML;
- this.parentTree_ = tree;
- this.label = modelItem.entry.name;
- this.dirEntry_ = modelItem.entry;
- this.modelItem_ = modelItem;
-
- var icon = this.querySelector('.icon');
- icon.classList.add('volume-icon');
- icon.setAttribute('volume-type-icon', VolumeManagerCommon.VolumeType.DRIVE);
-
- if (tree.contextMenuForRootItems)
- this.setContextMenu(tree.contextMenuForRootItems);
-};
-
-/**
- * Invoked when the tree item is clicked.
- *
- * @param {Event} e Click event.
- * @override
- */
-ShortcutItem.prototype.handleClick = function(e) {
- cr.ui.TreeItem.prototype.handleClick.call(this, e);
- this.parentTree_.directoryModel.clearSelection();
-};
-
-/**
- * Select the item corresponding to the given entry.
- * @param {DirectoryEntry} entry The directory entry to be selected.
- */
-ShortcutItem.prototype.selectByEntry = function(entry) {
- if (util.isSameEntry(entry, this.entry))
- this.selected = true;
-};
-
-/**
- * Sets the context menu for shortcut items.
- * @param {!cr.ui.Menu} menu Menu to be set.
- */
-ShortcutItem.prototype.setContextMenu = function(menu) {
- cr.ui.contextMenuHandler.setContextMenu(this, menu);
-};
-
-/**
- * Change current entry to the entry corresponding to this shortcut.
- */
-ShortcutItem.prototype.activate = function() {
- var directoryModel = this.parentTree_.directoryModel;
- var onEntryResolved = function(entry) {
- // Changes directory to the model item's root directory if needed.
- if (!util.isSameEntry(directoryModel.getCurrentDirEntry(), entry)) {
- metrics.recordUserAction('FolderShortcut.Navigate');
- directoryModel.changeDirectoryEntry(entry);
- }
- }.bind(this);
-
- // For shortcuts we already have an Entry, but it has to be resolved again
- // in case, it points to a non-existing directory.
- webkitResolveLocalFileSystemURL(
- this.entry.toURL(),
- onEntryResolved,
- function() {
- // Error, the entry can't be re-resolved. It may happen for shortcuts
- // which targets got removed after resolving the Entry during
- // initialization.
- this.parentTree_.dataModel.onItemNotFoundError(this.modelItem);
- }.bind(this));
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// 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.
- * @param {MetadataCache} metadataCache Shared MetadataCache instance.
- * @param {boolean} fakeEntriesVisible True if it should show the fakeEntries.
- */
-DirectoryTree.decorate = function(
- el, directoryModel, volumeManager, metadataCache, fakeEntriesVisible) {
- el.__proto__ = DirectoryTree.prototype;
- /** @type {DirectoryTree} */ (el).decorate(
- directoryModel, volumeManager, metadataCache, fakeEntriesVisible);
-};
-
-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_;
- },
-
- /**
- * The reference to shared MetadataCache instance.
- * @type {MetadataCache}
- */
- get metadataCache() {
- return this.metadataCache_;
- },
-
- set dataModel(dataModel) {
- if (!this.onListContentChangedBound_)
- this.onListContentChangedBound_ = this.onListContentChanged_.bind(this);
-
- if (this.dataModel_) {
- this.dataModel_.removeEventListener(
- 'change', this.onListContentChangedBound_);
- this.dataModel_.removeEventListener(
- 'permuted', this.onListContentChangedBound_);
- }
- this.dataModel_ = dataModel;
- dataModel.addEventListener('change', this.onListContentChangedBound_);
- dataModel.addEventListener('permuted', this.onListContentChangedBound_);
- },
-
- get dataModel() {
- return this.dataModel_;
- }
-};
-
-cr.defineProperty(DirectoryTree, 'contextMenuForSubitems', cr.PropertyKind.JS);
-cr.defineProperty(DirectoryTree, 'contextMenuForRootItems', 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) {
- // First, current items which is not included in the dataModel should be
- // removed.
- for (var i = 0; i < this.items.length;) {
- var found = false;
- for (var j = 0; j < this.dataModel.length; j++) {
- if (NavigationModelItem.isSame(this.items[i].modelItem,
- this.dataModel.item(j))) {
- found = true;
- break;
- }
- }
- if (!found) {
- if (this.items[i].selected)
- this.items[i].selected = false;
- this.remove(this.items[i]);
- } else {
- i++;
- }
- }
-
- // Next, insert items which is in dataModel but not in current items.
- var modelIndex = 0;
- var itemIndex = 0;
- while (modelIndex < this.dataModel.length) {
- if (itemIndex < this.items.length &&
- NavigationModelItem.isSame(this.items[itemIndex].modelItem,
- this.dataModel.item(modelIndex))) {
- if (recursive && this.items[itemIndex] instanceof VolumeItem)
- this.items[itemIndex].updateSubDirectories(true);
- } else {
- var modelItem = this.dataModel.item(modelIndex);
- if (modelItem.isVolume)
- this.addAt(new VolumeItem(modelItem, this), itemIndex);
- else
- this.addAt(new ShortcutItem(modelItem, this), itemIndex);
- }
- itemIndex++;
- modelIndex++;
- }
-
- if (itemIndex !== 0)
- 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.
- */
-DirectoryTree.prototype.searchAndSelectByEntry = function(entry) {
- // If the |entry| is same as one of volumes or shortcuts, select it.
- for (var i = 0; i < this.items.length; i++) {
- // Skips the Drive root volume. For Drive entries, one of children of Drive
- // root or shortcuts should be selected.
- var item = this.items[i];
- if (item instanceof VolumeItem && item.isDrive())
- continue;
-
- if (util.isSameEntry(item.entry, entry)) {
- this.dontHandleChangeEvent_ = true;
- item.selectByEntry(entry);
- this.dontHandleChangeEvent_ = false;
- return true;
- }
- }
- // Otherwise, search whole tree.
- this.dontHandleChangeEvent_ = true;
- var found = DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(
- this, entry);
- this.dontHandleChangeEvent_ = false;
- return found;
-};
-
-/**
- * Decorates an element.
- * @param {DirectoryModel} directoryModel Current DirectoryModel.
- * @param {VolumeManagerWrapper} volumeManager VolumeManager of the system.
- * @param {MetadataCache} metadataCache Shared MetadataCache instance.
- * @param {boolean} fakeEntriesVisible True if it should show the fakeEntries.
- */
-DirectoryTree.prototype.decorate = function(
- directoryModel, volumeManager, metadataCache, fakeEntriesVisible) {
- cr.ui.Tree.prototype.decorate.call(this);
-
- this.sequence_ = 0;
- this.directoryModel_ = directoryModel;
- this.volumeManager_ = volumeManager;
- this.metadataCache_ = metadataCache;
- this.models_ = [];
-
- 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.dontHandleChangeEvent_)
- this.selectedItem.activate();
- }.bind(this));
-
- this.privateOnDirectoryChangedBound_ =
- this.onDirectoryContentChanged_.bind(this);
- chrome.fileManagerPrivate.onDirectoryChanged.addListener(
- this.privateOnDirectoryChangedBound_);
-
- this.scrollBar_ = new MainPanelScrollBar();
- this.scrollBar_.initialize(this.parentElement, this);
-
- /**
- * Flag to show fake entries in the tree.
- * @type {boolean}
- * @private
- */
- this.fakeEntriesVisible_ = fakeEntriesVisible;
-};
-
-/**
- * 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 (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry))
- return;
-
- if (this.searchAndSelectByEntry(entry))
- return;
-
- this.updateSubDirectories(false /* recursive */);
- var currentSequence = ++this.sequence_;
- var volumeInfo = this.volumeManager_.getVolumeInfo(entry);
- if (!volumeInfo)
- return;
- volumeInfo.resolveDisplayRoot(function() {
- if (this.sequence_ !== currentSequence)
- return;
- if (!this.searchAndSelectByEntry(entry))
- this.selectedItem = null;
- }.bind(this));
-};
-
-/**
- * Select the volume or the shortcut corresponding to the given index.
- * @param {number} index 0-based index of the target top-level item.
- * @return {boolean} True if one of the volume items is selected.
- */
-DirectoryTree.prototype.selectByIndex = function(index) {
- if (index < 0 || index >= this.items.length)
- return false;
-
- this.items[index].selected = true;
- return true;
-};
-
-/**
- * Retrieves the latest subdirectories and update them on the tree.
- *
- * @param {boolean} recursive True if the update is recursively.
- * @param {function()=} opt_callback Called when subdirectories are fully
- * updated.
- */
-DirectoryTree.prototype.updateSubDirectories = function(
- recursive, opt_callback) {
- this.redraw(recursive);
- if (opt_callback)
- opt_callback();
-};
-
-/**
- * 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 {!Event} event Event.
- * @private
- */
-DirectoryTree.prototype.onDirectoryContentChanged_ = function(event) {
- if (event.eventType !== 'changed')
- return;
-
- for (var i = 0; i < this.items.length; i++) {
- if (this.items[i] instanceof VolumeItem)
- this.items[i].updateItemByEntry(event.entry);
- }
-};
-
-/**
- * Invoked when the current directory is changed.
- * @param {!Event} event Event.
- * @private
- */
-DirectoryTree.prototype.onCurrentDirectoryChanged_ = function(event) {
- this.selectByEntry(event.newDirEntry);
-};
-
-/**
- * Invoked when the volume list or shortcut list is changed.
- * @private
- */
-DirectoryTree.prototype.onListContentChanged_ = function() {
- this.updateSubDirectories(false, function() {
- // If no item is selected now, try to select the item corresponding to
- // current directory because the current directory might have been populated
- // in this tree in previous updateSubDirectories().
- if (!this.selectedItem) {
- var currentDir = this.directoryModel_.getCurrentDirEntry();
- if (currentDir)
- this.selectByEntry(currentDir);
- }
- }.bind(this));
-};
-
-/**
- * Updates the UI after the layout has changed.
- */
-DirectoryTree.prototype.relayout = function() {
- cr.dispatchSimpleEvent(this, 'relayout');
-};

Powered by Google App Engine
This is Rietveld 408576698