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

Side by Side Diff: chrome/browser/resources/file_manager/js/navigation_list.js

Issue 23851011: Remove unavailable shortcut silently instead of showing a confirmation dialog (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/resources/file_manager/js/file_manager.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 'use strict'; 5 'use strict';
6 6
7 /** 7 /**
8 * Entry of NavigationListModel. This construtor should be called only from 8 * Entry of NavigationListModel. This construtor should be called only from
9 * the helper methods (NavigationModelItem.createWithPath/createWithEntry). 9 * the helper methods (NavigationModelItem.createWithPath/createWithEntry).
10 * 10 *
11 * @param {FileSystem} filesystem Fielsystem. 11 * @param {FileSystem} filesystem Fielsystem.
12 * @param {?string} path Path. 12 * @param {?string} path Path.
13 * @param {DirectoryEntry} entry Entry. Can be a fake. 13 * @param {DirectoryEntry} entry Entry. Can be a fake.
14 * @extends {cr.EventTarget} 14 * @extends {cr.EventTarget}
15 * @constructor 15 * @constructor
16 */ 16 */
17 function NavigationModelItem(filesystem, path, entry) { 17 function NavigationModelItem(filesystem, path, entry) {
18 this.filesystem_ = filesystem; 18 this.filesystem_ = filesystem;
19 this.path_ = path; 19 this.path_ = path;
20 this.entry_ = entry; 20 this.entry_ = entry;
21 this.fileError_ = null;
21 22
22 this.resolvingQueue_ = new AsyncUtil.Queue(); 23 this.resolvingQueue_ = new AsyncUtil.Queue();
24
25 Object.seal(this);
23 } 26 }
24 27
25 NavigationModelItem.prototype = { 28 NavigationModelItem.prototype = {
26 __proto__: cr.EventTarget.prototype, 29 get path() { return this.path_; },
27 get path() { return this.path_; } 30 get fileError() { return this.fileError_; }
28 }; 31 };
29 32
30 /** 33 /**
31 * Returns the cached entry of the item. This may returns NULL if the target is 34 * Returns the cached entry of the item. This may returns NULL if the target is
32 * not available on the filesystem, is not resolved or is under resolving the 35 * not available on the filesystem, is not resolved or is under resolving the
33 * entry. 36 * entry.
34 * 37 *
35 * @return {Entry} Cached entry. 38 * @return {Entry} Cached entry.
36 */ 39 */
37 NavigationModelItem.prototype.getCachedEntry = function() { 40 NavigationModelItem.prototype.getCachedEntry = function() {
38 return this.entry_; 41 return this.entry_;
39 }; 42 };
40 43
41 /** 44 /**
42 * @param {FileSystem} filesystem FileSystem. 45 * @param {FileSystem} filesystem FileSystem.
43 * @param {string} path Path. 46 * @param {string} path Path.
47 * @param {function(NavigationModelItem)} callback Called when the resolving is
48 * success/failed with the created NavigationModelItem.
44 * @return {NavigationModelItem} Created NavigationModelItem. 49 * @return {NavigationModelItem} Created NavigationModelItem.
45 */ 50 */
46 NavigationModelItem.createWithPath = function(filesystem, path) { 51 NavigationModelItem.createWithPath = function(filesystem, path, callback) {
47 var modelItem = new NavigationModelItem( 52 var modelItem = new NavigationModelItem(
48 filesystem, 53 filesystem,
49 path, 54 path,
50 null); 55 null);
51 modelItem.resolveDirectoryEntry_(); 56 modelItem.resolveDirectoryEntry_(function() {
57 callback(modelItem);
58 });
52 return modelItem; 59 return modelItem;
53 }; 60 };
54 61
55 /** 62 /**
56 * @param {DirectoryEntry} entry Entry. Can be a fake. 63 * @param {DirectoryEntry} entry Entry. Can be a fake.
57 * @return {NavigationModelItem} Created NavigationModelItem. 64 * @return {NavigationModelItem} Created NavigationModelItem.
58 */ 65 */
59 NavigationModelItem.createWithEntry = function(entry) { 66 NavigationModelItem.createWithEntry = function(entry) {
60 if (entry) { 67 if (entry) {
61 return new NavigationModelItem( 68 return new NavigationModelItem(
(...skipping 16 matching lines...) Expand all
78 NavigationModelItem.prototype.getEntryAsync = function(callback) { 85 NavigationModelItem.prototype.getEntryAsync = function(callback) {
79 // If resolveDirectoryEntry_() is running, waits until it finishes. 86 // If resolveDirectoryEntry_() is running, waits until it finishes.
80 this.resolvingQueue_.run(function(continueCallback) { 87 this.resolvingQueue_.run(function(continueCallback) {
81 callback(this.entry_); 88 callback(this.entry_);
82 continueCallback(); 89 continueCallback();
83 }.bind(this)); 90 }.bind(this));
84 }; 91 };
85 92
86 /** 93 /**
87 * Resolves an directory entry. 94 * Resolves an directory entry.
95 * @param {function()} callback Called when the resolving is success/failed.
88 * @private 96 * @private
89 */ 97 */
90 NavigationModelItem.prototype.resolveDirectoryEntry_ = function() { 98 NavigationModelItem.prototype.resolveDirectoryEntry_ = function(callback) {
91 this.resolvingQueue_.run(function(continueCallback) { 99 this.resolvingQueue_.run(function(continueCallback) {
92 this.filesystem_.root.getDirectory( 100 this.filesystem_.root.getDirectory(
93 this.path_, 101 this.path_,
94 {create: false}, 102 {create: false},
95 function(directoryEntry) { 103 function(directoryEntry) {
96 this.entry_ = directoryEntry; 104 this.entry_ = directoryEntry;
105 callback();
97 continueCallback(); 106 continueCallback();
98 }.bind(this), 107 }.bind(this),
99 function(error) { 108 function(error) {
100 this.entry_ = null; 109 this.entry_ = null;
110 this.fileError_ = error;
101 console.error('Error on resolving path: ' + this.path_); 111 console.error('Error on resolving path: ' + this.path_);
112 callback();
102 continueCallback(); 113 continueCallback();
103 }.bind(this)); 114 }.bind(this));
104 }.bind(this)); 115 }.bind(this));
105 }; 116 };
106 117
107 /** 118 /**
108 * Returns if this item is a shortcut or a volume root. 119 * Returns if this item is a shortcut or a volume root.
109 * @return {boolean} True if a shortcut, false if a volume root. 120 * @return {boolean} True if a shortcut, false if a volume root.
110 */ 121 */
111 NavigationModelItem.prototype.isShortcut = function() { 122 NavigationModelItem.prototype.isShortcut = function() {
(...skipping 12 matching lines...) Expand all
124 this.volumesListModel_ = volumesList; 135 this.volumesListModel_ = volumesList;
125 this.shortcutListModel_ = shortcutList; 136 this.shortcutListModel_ = shortcutList;
126 137
127 // On default, shortcut list is disabled. It may be enabled on initializetion. 138 // On default, shortcut list is disabled. It may be enabled on initializetion.
128 this.showShortcuts_ = false; 139 this.showShortcuts_ = false;
129 140
130 var entryToModelItem = function(entry) { 141 var entryToModelItem = function(entry) {
131 return NavigationModelItem.createWithEntry(entry); 142 return NavigationModelItem.createWithEntry(entry);
132 }; 143 };
133 var pathToModelItem = function(path) { 144 var pathToModelItem = function(path) {
134 return NavigationModelItem.createWithPath(filesystem, path); 145 return NavigationModelItem.createWithPath(filesystem, path,
135 }; 146 function(modelItem) {
147 if (!modelItem.getCachedEntry() &&
148 modelItem.fileError &&
149 modelItem.fileError.code === FileError.NOT_FOUND_ERR) {
150 this.onItemNotFoundError(modelItem);
151 }
152 }.bind(this));
153 }.bind(this);
136 154
137 /** 155 /**
138 * Type of updated list. 156 * Type of updated list.
139 * @enum {number} 157 * @enum {number}
140 * @const 158 * @const
141 */ 159 */
142 var ListType = { 160 var ListType = {
143 VOLUME_LIST: 1, 161 VOLUME_LIST: 1,
144 SHORTCUT_LIST: 2 162 SHORTCUT_LIST: 2
145 }; 163 };
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 */ 339 */
322 NavigationListModel.prototype.indexOf = function(modelItem, opt_fromIndex) { 340 NavigationListModel.prototype.indexOf = function(modelItem, opt_fromIndex) {
323 for (var i = opt_fromIndex || 0; i < this.length; i++) { 341 for (var i = opt_fromIndex || 0; i < this.length; i++) {
324 if (modelItem === this.item(i)) 342 if (modelItem === this.item(i))
325 return i; 343 return i;
326 } 344 }
327 return -1; 345 return -1;
328 }; 346 };
329 347
330 /** 348 /**
349 * Called when one od the items is not found on the filesystem.
350 * @param {NavigationModelItem} modelItem The entry which is not found.
351 */
352 NavigationListModel.prototype.onItemNotFoundError = function(modelItem) {
353 var index = this.indexOf(modelItem);
354 if (index === -1) {
355 // Invalid modelItem.
356 } else if (index < this.volumesList_.length) {
357 // The item is in the volume list.
358 // Not implemented.
359 // TODO(yoshiki): Implement it when necessary.
360 } else {
361 // The item is in the folder shortcut list.
362 if (this.isDriveMounted())
363 this.shortcutListModel_.remove(modelItem.path);
364 }
365 };
366
367 /**
368 * Returns if the drive is mounted or not.
369 * @return {boolean} True if the drive is mounted, false otherwise.
370 */
371 NavigationListModel.prototype.isDriveMounted = function() {
372 for (var i = 0; i < this.volumesList_.length; i++) {
373 if (PathUtil.isDriveBasedPath(this.item(i).path))
374 return true;
375 }
376 return false;
377 };
378
379 /**
331 * A navigation list item. 380 * A navigation list item.
332 * @constructor 381 * @constructor
333 * @extends {HTMLLIElement} 382 * @extends {HTMLLIElement}
334 */ 383 */
335 var NavigationListItem = cr.ui.define('li'); 384 var NavigationListItem = cr.ui.define('li');
336 385
337 NavigationListItem.prototype = { 386 NavigationListItem.prototype = {
338 __proto__: HTMLLIElement.prototype, 387 __proto__: HTMLLIElement.prototype,
339 get modelItem() { return this.modelItem_; }, 388 get modelItem() { return this.modelItem_; }
340 }; 389 };
341 390
342 /** 391 /**
343 * Decorate the item. 392 * Decorate the item.
344 */ 393 */
345 NavigationListItem.prototype.decorate = function() { 394 NavigationListItem.prototype.decorate = function() {
346 // decorate() may be called twice: from the constructor and from 395 // decorate() may be called twice: from the constructor and from
347 // List.createItem(). This check prevents double-decorating. 396 // List.createItem(). This check prevents double-decorating.
348 if (this.className) 397 if (this.className)
349 return; 398 return;
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 628
580 // TODO(yoshiki): Animation is temporary disabled for volumes. Add animation 629 // TODO(yoshiki): Animation is temporary disabled for volumes. Add animation
581 // back. crbug.com/276132. 630 // back. crbug.com/276132.
582 item.setFadeinAnimation(modelItem.isShortcut() && 631 item.setFadeinAnimation(modelItem.isShortcut() &&
583 !this.measuringTemporaryItemNow_); 632 !this.measuringTemporaryItemNow_);
584 633
585 var handleClick = function() { 634 var handleClick = function() {
586 if (item.selected && 635 if (item.selected &&
587 modelItem.path !== this.directoryModel_.getCurrentDirPath()) { 636 modelItem.path !== this.directoryModel_.getCurrentDirPath()) {
588 metrics.recordUserAction('FolderShortcut.Navigate'); 637 metrics.recordUserAction('FolderShortcut.Navigate');
589 this.changeDirectory_(modelItem.path); 638 this.changeDirectory_(modelItem);
590 } 639 }
591 }.bind(this); 640 }.bind(this);
592 item.addEventListener('click', handleClick); 641 item.addEventListener('click', handleClick);
593 642
594 var handleEject = function() { 643 var handleEject = function() {
595 var unmountCommand = cr.doc.querySelector('command#unmount'); 644 var unmountCommand = cr.doc.querySelector('command#unmount');
596 // Let's make sure 'canExecute' state of the command is properly set for 645 // Let's make sure 'canExecute' state of the command is properly set for
597 // the root before executing it. 646 // the root before executing it.
598 unmountCommand.canExecuteChange(item); 647 unmountCommand.canExecuteChange(item);
599 unmountCommand.execute(item); 648 unmountCommand.execute(item);
600 }; 649 };
601 item.addEventListener('eject', handleEject); 650 item.addEventListener('eject', handleEject);
602 651
603 if (this.contextMenu_) 652 if (this.contextMenu_)
604 item.maybeSetContextMenu(this.contextMenu_); 653 item.maybeSetContextMenu(this.contextMenu_);
605 654
606 return item; 655 return item;
607 }; 656 };
608 657
609 /** 658 /**
610 * Changes the current directory to the given path. 659 * Changes the current directory to the given path.
611 * If the given path is not found, a 'shortcut-target-not-found' event is 660 * If the given path is not found, a 'shortcut-target-not-found' event is
612 * fired. 661 * fired.
613 * 662 *
614 * @param {string} path Path of the directory to be chagned to. 663 * @param {NavigationModelItem} modelItem Directory to be chagned to.
615 * @private 664 * @private
616 */ 665 */
617 NavigationList.prototype.changeDirectory_ = function(path) { 666 NavigationList.prototype.changeDirectory_ = function(modelItem) {
618 var onErrorCallback = function() { 667 var onErrorCallback = function(error) {
619 // TODO(yoshiki): Remove this if the teporary patch is merged to the M30. 668 if (error.code === FileError.NOT_FOUND_ERR)
620 // crbug.com/270436 669 this.dataModel.onItemNotFoundError(modelItem);
621 }.bind(this); 670 }.bind(this);
622 671
623 this.directoryModel_.changeDirectory(path, onErrorCallback); 672 this.directoryModel_.changeDirectory(modelItem.path, onErrorCallback);
624 }; 673 };
625 674
626 /** 675 /**
627 * Sets a context menu. Context menu is enabled only on archive and removable 676 * Sets a context menu. Context menu is enabled only on archive and removable
628 * volumes as of now. 677 * volumes as of now.
629 * 678 *
630 * @param {cr.ui.Menu} menu Context menu. 679 * @param {cr.ui.Menu} menu Context menu.
631 */ 680 */
632 NavigationList.prototype.setContextMenu = function(menu) { 681 NavigationList.prototype.setContextMenu = function(menu) {
633 this.contextMenu_ = menu; 682 this.contextMenu_ = menu;
634 683
635 for (var i = 0; i < this.dataModel.length; i++) { 684 for (var i = 0; i < this.dataModel.length; i++) {
636 this.getListItemByIndex(i).maybeSetContextMenu(this.contextMenu_); 685 this.getListItemByIndex(i).maybeSetContextMenu(this.contextMenu_);
637 } 686 }
638 }; 687 };
639 688
640 /** 689 /**
641 * Selects the n-th item from the list. 690 * Selects the n-th item from the list.
642 * 691 *
643 * @param {number} index Item index. 692 * @param {number} index Item index.
644 * @return {boolean} True for success, otherwise false. 693 * @return {boolean} True for success, otherwise false.
645 */ 694 */
646 NavigationList.prototype.selectByIndex = function(index) { 695 NavigationList.prototype.selectByIndex = function(index) {
647 if (index < 0 || index > this.dataModel.length - 1) 696 if (index < 0 || index > this.dataModel.length - 1)
648 return false; 697 return false;
649 698
650 var newPath = this.dataModel.item(index).path; 699 var newModelItem = this.dataModel.item(index);
700 var newPath = newModelItem.path;
651 if (!newPath) 701 if (!newPath)
652 return false; 702 return false;
653 703
654 // Prevents double-moving to the current directory. 704 // Prevents double-moving to the current directory.
655 // eg. When user clicks the item, changing directory has already been done in 705 // eg. When user clicks the item, changing directory has already been done in
656 // click handler. 706 // click handler.
657 if (this.directoryModel_.getCurrentDirEntry().fullPath == newPath) 707 if (this.directoryModel_.getCurrentDirEntry().fullPath == newPath)
658 return false; 708 return false;
659 709
660 metrics.recordUserAction('FolderShortcut.Navigate'); 710 metrics.recordUserAction('FolderShortcut.Navigate');
661 this.changeDirectory_(newPath); 711 this.changeDirectory_(newModelItem);
662 return true; 712 return true;
663 }; 713 };
664 714
665 /** 715 /**
666 * Handler before root item change. 716 * Handler before root item change.
667 * @param {Event} event The event. 717 * @param {Event} event The event.
668 * @private 718 * @private
669 */ 719 */
670 NavigationList.prototype.onBeforeSelectionChange_ = function(event) { 720 NavigationList.prototype.onBeforeSelectionChange_ = function(event) {
671 if (event.changes.length == 1 && !event.changes[0].selected) 721 if (event.changes.length == 1 && !event.changes[0].selected)
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 var itemPath = this.dataModel.item(i).path; 791 var itemPath = this.dataModel.item(i).path;
742 if (PathUtil.getRootPath(itemPath) == newRootPath) { 792 if (PathUtil.getRootPath(itemPath) == newRootPath) {
743 // Not to invoke the handler of this instance, sets the guard. 793 // Not to invoke the handler of this instance, sets the guard.
744 this.dontHandleSelectionEvent_ = true; 794 this.dontHandleSelectionEvent_ = true;
745 this.selectionModel.selectedIndex = i; 795 this.selectionModel.selectedIndex = i;
746 this.dontHandleSelectionEvent_ = false; 796 this.dontHandleSelectionEvent_ = false;
747 return; 797 return;
748 } 798 }
749 } 799 }
750 }; 800 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/file_manager/js/file_manager.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698