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

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

Issue 39123003: [Files.app] Split the JavaScript files into subdirectories: common, background, and foreground (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed test failure. Created 7 years, 1 month 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 'use strict';
6
7 /**
8 * Entry of NavigationListModel. This constructor should be called only from
9 * the helper methods (NavigationModelItem.createFromPath/createFromEntry).
10 *
11 * @param {string} path Path.
12 * @param {DirectoryEntry} entry Entry. Can be null.
13 * @constructor
14 */
15 function NavigationModelItem(path, entry) {
16 this.path_ = path;
17 this.entry_ = entry;
18 this.resolvingQueue_ = new AsyncUtil.Queue();
19
20 Object.seal(this);
21 }
22
23 NavigationModelItem.prototype = {
24 get path() { return this.path_; },
25 };
26
27 /**
28 * Returns the cached entry of the item. This may return NULL if the target is
29 * not available on the filesystem, is not resolved or is under resolving the
30 * entry.
31 *
32 * @return {Entry} Cached entry.
33 */
34 NavigationModelItem.prototype.getCachedEntry = function() {
35 return this.entry_;
36 };
37
38 /**
39 * @param {VolumeManagerWrapper} volumeManager VolumeManagerWrapper instance.
40 * @param {string} path Path.
41 * @param {function(FileError)} errorCallback Called when the resolving is
42 * failed with the error.
43 * @return {NavigationModelItem} Created NavigationModelItem.
44 */
45 NavigationModelItem.createFromPath = function(
46 volumeManager, path, errorCallback) {
47 var item = new NavigationModelItem(path, null);
48 item.resolvingQueue_.run(function(continueCallback) {
49 volumeManager.resolvePath(
50 path,
51 function(entry) {
52 if (entry.isDirectory)
53 item.entry_ = entry;
54 else
55 errorCallback(util.createFileError(FileError.TYPE_MISMATCH_ERR));
56 continueCallback();
57 },
58 function(error) {
59 errorCallback(error);
60 continueCallback();
61 });
62 });
63 return item;
64 };
65
66 /**
67 * @param {DirectoryEntry} entry Entry. Can be null.
68 * @return {NavigationModelItem} Created NavigationModelItem.
69 */
70 NavigationModelItem.createFromEntry = function(entry) {
71 if (!entry)
72 return null;
73 return new NavigationModelItem(entry.fullPath, entry);
74 };
75
76 /**
77 * Retrieves the entry. If the entry is being retrieved, waits until it
78 * finishes.
79 * @param {function(Entry)} callback Called with the resolved entry. The entry
80 * may be NULL if resolving is failed.
81 */
82 NavigationModelItem.prototype.getEntryAsync = function(callback) {
83 // If resolving the entry is running, wait until it finishes.
84 this.resolvingQueue_.run(function(continueCallback) {
85 callback(this.entry_);
86 continueCallback();
87 }.bind(this));
88 };
89
90 /**
91 * Returns if this item is a shortcut or a volume root.
92 * @return {boolean} True if a shortcut, false if a volume root.
93 */
94 NavigationModelItem.prototype.isShortcut = function() {
95 return !PathUtil.isRootPath(this.path_);
96 };
97
98 /**
99 * A navigation list model. This model combines the 2 lists.
100 * @param {VolumeManagerWrapper} volumeManager VolumeManagerWrapper instance.
101 * @param {cr.ui.ArrayDataModel} shortcutListModel The list of folder shortcut.
102 * @constructor
103 * @extends {cr.EventTarget}
104 */
105 function NavigationListModel(volumeManager, shortcutListModel) {
106 cr.EventTarget.call(this);
107
108 this.volumeManager_ = volumeManager;
109 this.shortcutListModel_ = shortcutListModel;
110
111 var volumeInfoToModelItem = function(volumeInfo) {
112 if (volumeInfo.volumeType == util.VolumeType.DRIVE) {
113 // For drive volume, we assign the path to "My Drive".
114 return NavigationModelItem.createFromPath(
115 this.volumeManager_,
116 volumeInfo.mountPath + '/root',
117 function() {});
118 } else {
119 return NavigationModelItem.createFromEntry(volumeInfo.root);
120 }
121 }.bind(this);
122
123 var pathToModelItem = function(path) {
124 var item = NavigationModelItem.createFromPath(
125 this.volumeManager_,
126 path,
127 function(error) {
128 if (error.code == FileError.NOT_FOUND_ERR)
129 this.onItemNotFoundError(item);
130 }.bind(this));
131 return item;
132 }.bind(this);
133
134 /**
135 * Type of updated list.
136 * @enum {number}
137 * @const
138 */
139 var ListType = {
140 VOLUME_LIST: 1,
141 SHORTCUT_LIST: 2
142 };
143 Object.freeze(ListType);
144
145 // Generates this.volumeList_ and this.shortcutList_ from the models.
146 this.volumeList_ =
147 this.volumeManager_.volumeInfoList.slice().map(volumeInfoToModelItem);
148
149 this.shortcutList_ = [];
150 for (var i = 0; i < this.shortcutListModel_.length; i++) {
151 var shortcutPath = this.shortcutListModel_.item(i);
152 var mountPath = PathUtil.isDriveBasedPath(shortcutPath) ?
153 RootDirectory.DRIVE :
154 PathUtil.getRootPath(shortcutPath);
155 var volumeInfo = this.volumeManager_.getVolumeInfo(mountPath);
156 var isMounted = volumeInfo && !volumeInfo.error;
157 if (isMounted)
158 this.shortcutList_.push(pathToModelItem(shortcutPath));
159 }
160
161 // Generates a combined 'permuted' event from an event of either list.
162 var permutedHandler = function(listType, event) {
163 var permutation;
164
165 // Build the volumeList.
166 if (listType == ListType.VOLUME_LIST) {
167 // The volume is mounted or unmounted.
168 var newList = [];
169
170 // Use the old instances if they just move.
171 for (var i = 0; i < event.permutation.length; i++) {
172 if (event.permutation[i] >= 0)
173 newList[event.permutation[i]] = this.volumeList_[i];
174 }
175
176 // Create missing instances.
177 for (var i = 0; i < event.newLength; i++) {
178 if (!newList[i]) {
179 newList[i] = volumeInfoToModelItem(
180 this.volumeManager_.volumeInfoList.item(i));
181 }
182 }
183 this.volumeList_ = newList;
184
185 permutation = event.permutation.slice();
186 } else {
187 // volumeList part has not been changed, so the permutation should be
188 // idenetity mapping.
189 permutation = [];
190 for (var i = 0; i < this.volumeList_.length; i++)
191 permutation[i] = i;
192 }
193
194 // Build the shortcutList. Even if the event is for the volumeInfoList
195 // update, the short cut path may be unmounted or newly mounted. So, here
196 // shortcutList will always be re-built.
197 // Currently this code may be redundant, as shortcut folder is supported
198 // only on Drive File System and we can assume single-profile, but
199 // multi-profile will be supported later.
200 // The shortcut list is sorted in case-insensitive lexicographical order.
201 // So we just can traverse the two list linearly.
202 var modelIndex = 0;
203 var oldListIndex = 0;
204 var newList = [];
205 while (modelIndex < this.shortcutListModel_.length &&
206 oldListIndex < this.shortcutList_.length) {
207 var shortcutPath = this.shortcutListModel_.item(modelIndex);
208 var cmp = this.shortcutListModel_.compare(
209 shortcutPath, this.shortcutList_[oldListIndex].path);
210 if (cmp > 0) {
211 // The shortcut at shortcutList_[oldListIndex] is removed.
212 permutation.push(-1);
213 oldListIndex++;
214 continue;
215 }
216
217 // Check if the volume where the shortcutPath is is mounted or not.
218 var mountPath = PathUtil.isDriveBasedPath(shortcutPath) ?
219 RootDirectory.DRIVE :
220 PathUtil.getRootPath(shortcutPath);
221 var volumeInfo = this.volumeManager_.getVolumeInfo(mountPath);
222 var isMounted = volumeInfo && !volumeInfo.error;
223 if (cmp == 0) {
224 // There exists an old NavigationModelItem instance.
225 if (isMounted) {
226 // Reuse the old instance.
227 permutation.push(newList.length + this.volumeList_.length);
228 newList.push(this.shortcutList_[oldListIndex]);
229 } else {
230 permutation.push(-1);
231 }
232 oldListIndex++;
233 } else {
234 // We needs to create a new instance for the shortcut path.
235 if (isMounted)
236 newList.push(pathToModelItem(shortcutPath));
237 }
238 modelIndex++;
239 }
240
241 // Add remaining (new) shortcuts if necessary.
242 for (; modelIndex < this.shortcutListModel_.length; modelIndex++) {
243 var shortcutPath = this.shortcutListModel_.item(modelIndex);
244 var mountPath = PathUtil.isDriveBasedPath(shortcutPath) ?
245 RootDirectory.DRIVE :
246 PathUtil.getRootPath(shortcutPath);
247 var volumeInfo = this.volumeManager_.getVolumeInfo(mountPath);
248 var isMounted = volumeInfo && !volumeInfo.error;
249 if (isMounted)
250 newList.push(pathToModelItem(shortcutPath));
251 }
252
253 // Fill remaining permutation if necessary.
254 for (; oldListIndex < this.shortcutList_.length; oldListIndex++)
255 permutation.push(-1);
256
257 this.shortcutList_ = newList;
258
259 // Dispatch permuted event.
260 var permutedEvent = new Event('permuted');
261 permutedEvent.newLength =
262 this.volumeList_.length + this.shortcutList_.length;
263 permutedEvent.permutation = permutation;
264 this.dispatchEvent(permutedEvent);
265 };
266
267 this.volumeManager_.volumeInfoList.addEventListener(
268 'permuted', permutedHandler.bind(this, ListType.VOLUME_LIST));
269 this.shortcutListModel_.addEventListener(
270 'permuted', permutedHandler.bind(this, ListType.SHORTCUT_LIST));
271
272 // 'change' event is just ignored, because it is not fired neither in
273 // the folder shortcut list nor in the volume info list.
274 // 'splice' and 'sorted' events are not implemented, since they are not used
275 // in list.js.
276 }
277
278 /**
279 * NavigationList inherits cr.EventTarget.
280 */
281 NavigationListModel.prototype = {
282 __proto__: cr.EventTarget.prototype,
283 get length() { return this.length_(); },
284 get folderShortcutList() { return this.shortcutList_; }
285 };
286
287 /**
288 * Returns the item at the given index.
289 * @param {number} index The index of the entry to get.
290 * @return {?string} The path at the given index.
291 */
292 NavigationListModel.prototype.item = function(index) {
293 var offset = this.volumeList_.length;
294 if (index < offset)
295 return this.volumeList_[index];
296 return this.shortcutList_[index - offset];
297 };
298
299 /**
300 * Returns the number of items in the model.
301 * @return {number} The length of the model.
302 * @private
303 */
304 NavigationListModel.prototype.length_ = function() {
305 return this.volumeList_.length + this.shortcutList_.length;
306 };
307
308 /**
309 * Returns the first matching item.
310 * @param {NavigationModelItem} modelItem The entry to find.
311 * @param {number=} opt_fromIndex If provided, then the searching start at
312 * the {@code opt_fromIndex}.
313 * @return {number} The index of the first found element or -1 if not found.
314 */
315 NavigationListModel.prototype.indexOf = function(modelItem, opt_fromIndex) {
316 for (var i = opt_fromIndex || 0; i < this.length; i++) {
317 if (modelItem === this.item(i))
318 return i;
319 }
320 return -1;
321 };
322
323 /**
324 * Called when one od the items is not found on the filesystem.
325 * @param {NavigationModelItem} modelItem The entry which is not found.
326 */
327 NavigationListModel.prototype.onItemNotFoundError = function(modelItem) {
328 var index = this.indexOf(modelItem);
329 if (index === -1) {
330 // Invalid modelItem.
331 } else if (index < this.volumeList_.length) {
332 // The item is in the volume list.
333 // Not implemented.
334 // TODO(yoshiki): Implement it when necessary.
335 } else {
336 // The item is in the folder shortcut list.
337 if (this.isDriveMounted())
338 this.shortcutListModel_.remove(modelItem.path);
339 }
340 };
341
342 /**
343 * Returns if the drive is mounted or not.
344 * @return {boolean} True if the drive is mounted, false otherwise.
345 */
346 NavigationListModel.prototype.isDriveMounted = function() {
347 return !!this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE);
348 };
349
350 /**
351 * A navigation list item.
352 * @constructor
353 * @extends {HTMLLIElement}
354 */
355 var NavigationListItem = cr.ui.define('li');
356
357 NavigationListItem.prototype = {
358 __proto__: HTMLLIElement.prototype,
359 get modelItem() { return this.modelItem_; }
360 };
361
362 /**
363 * Decorate the item.
364 */
365 NavigationListItem.prototype.decorate = function() {
366 // decorate() may be called twice: from the constructor and from
367 // List.createItem(). This check prevents double-decorating.
368 if (this.className)
369 return;
370
371 this.className = 'root-item';
372 this.setAttribute('role', 'option');
373
374 this.iconDiv_ = cr.doc.createElement('div');
375 this.iconDiv_.className = 'volume-icon';
376 this.appendChild(this.iconDiv_);
377
378 this.label_ = cr.doc.createElement('div');
379 this.label_.className = 'root-label';
380 this.appendChild(this.label_);
381
382 cr.defineProperty(this, 'lead', cr.PropertyKind.BOOL_ATTR);
383 cr.defineProperty(this, 'selected', cr.PropertyKind.BOOL_ATTR);
384 };
385
386 /**
387 * Associate a path with this item.
388 * @param {NavigationModelItem} modelItem NavigationModelItem of this item.
389 * @param {string=} opt_deviceType The type of the device. Available iff the
390 * path represents removable storage.
391 */
392 NavigationListItem.prototype.setModelItem =
393 function(modelItem, opt_deviceType) {
394 if (this.modelItem_)
395 console.warn('NavigationListItem.setModelItem should be called only once.');
396
397 this.modelItem_ = modelItem;
398
399 var rootType = PathUtil.getRootType(modelItem.path);
400 this.iconDiv_.setAttribute('volume-type-icon', rootType);
401 if (opt_deviceType) {
402 this.iconDiv_.setAttribute('volume-subtype', opt_deviceType);
403 }
404
405 this.label_.textContent = PathUtil.getFolderLabel(modelItem.path);
406
407 if (rootType === RootType.ARCHIVE || rootType === RootType.REMOVABLE) {
408 this.eject_ = cr.doc.createElement('div');
409 // Block other mouse handlers.
410 this.eject_.addEventListener(
411 'mouseup', function(event) { event.stopPropagation() });
412 this.eject_.addEventListener(
413 'mousedown', function(event) { event.stopPropagation() });
414
415 this.eject_.className = 'root-eject';
416 this.eject_.addEventListener('click', function(event) {
417 event.stopPropagation();
418 cr.dispatchSimpleEvent(this, 'eject');
419 }.bind(this));
420
421 this.appendChild(this.eject_);
422 }
423 };
424
425 /**
426 * Associate a context menu with this item.
427 * @param {cr.ui.Menu} menu Menu this item.
428 */
429 NavigationListItem.prototype.maybeSetContextMenu = function(menu) {
430 if (!this.modelItem_.path) {
431 console.error('NavigationListItem.maybeSetContextMenu must be called ' +
432 'after setModelItem().');
433 return;
434 }
435
436 var isRoot = PathUtil.isRootPath(this.modelItem_.path);
437 var rootType = PathUtil.getRootType(this.modelItem_.path);
438 // The context menu is shown on the following items:
439 // - Removable and Archive volumes
440 // - Folder shortcuts
441 if (!isRoot ||
442 (rootType != RootType.DRIVE && rootType != RootType.DOWNLOADS))
443 cr.ui.contextMenuHandler.setContextMenu(this, menu);
444 };
445
446 /**
447 * A navigation list.
448 * @constructor
449 * @extends {cr.ui.List}
450 */
451 function NavigationList() {
452 }
453
454 /**
455 * NavigationList inherits cr.ui.List.
456 */
457 NavigationList.prototype = {
458 __proto__: cr.ui.List.prototype,
459
460 set dataModel(dataModel) {
461 if (!this.onListContentChangedBound_)
462 this.onListContentChangedBound_ = this.onListContentChanged_.bind(this);
463
464 if (this.dataModel_) {
465 this.dataModel_.removeEventListener(
466 'change', this.onListContentChangedBound_);
467 this.dataModel_.removeEventListener(
468 'permuted', this.onListContentChangedBound_);
469 }
470
471 var parentSetter = cr.ui.List.prototype.__lookupSetter__('dataModel');
472 parentSetter.call(this, dataModel);
473
474 // This must be placed after the parent method is called, in order to make
475 // it sure that the list was changed.
476 dataModel.addEventListener('change', this.onListContentChangedBound_);
477 dataModel.addEventListener('permuted', this.onListContentChangedBound_);
478 },
479
480 get dataModel() {
481 return this.dataModel_;
482 },
483
484 // TODO(yoshiki): Add a setter of 'directoryModel'.
485 };
486
487 /**
488 * @param {HTMLElement} el Element to be DirectoryItem.
489 * @param {VolumeManagerWrapper} volumeManager The VolumeManager of the system.
490 * @param {DirectoryModel} directoryModel Current DirectoryModel.
491 * folders.
492 */
493 NavigationList.decorate = function(el, volumeManager, directoryModel) {
494 el.__proto__ = NavigationList.prototype;
495 el.decorate(volumeManager, directoryModel);
496 };
497
498 /**
499 * @param {VolumeManagerWrapper} volumeManager The VolumeManager of the system.
500 * @param {DirectoryModel} directoryModel Current DirectoryModel.
501 */
502 NavigationList.prototype.decorate = function(volumeManager, directoryModel) {
503 cr.ui.List.decorate(this);
504 this.__proto__ = NavigationList.prototype;
505
506 this.directoryModel_ = directoryModel;
507 this.volumeManager_ = volumeManager;
508 this.selectionModel = new cr.ui.ListSingleSelectionModel();
509
510 this.directoryModel_.addEventListener('directory-changed',
511 this.onCurrentDirectoryChanged_.bind(this));
512 this.selectionModel.addEventListener(
513 'change', this.onSelectionChange_.bind(this));
514 this.selectionModel.addEventListener(
515 'beforeChange', this.onBeforeSelectionChange_.bind(this));
516
517 this.scrollBar_ = new ScrollBar();
518 this.scrollBar_.initialize(this.parentNode, this);
519
520 // Overriding default role 'list' set by cr.ui.List.decorate() to 'listbox'
521 // role for better accessibility on ChromeOS.
522 this.setAttribute('role', 'listbox');
523
524 var self = this;
525 this.itemConstructor = function(modelItem) {
526 return self.renderRoot_(modelItem);
527 };
528 };
529
530 /**
531 * This overrides cr.ui.List.measureItem().
532 * In the method, a temporary element is added/removed from the list, and we
533 * need to omit animations for such temporary items.
534 *
535 * @param {ListItem=} opt_item The list item to be measured.
536 * @return {{height: number, marginTop: number, marginBottom:number,
537 * width: number, marginLeft: number, marginRight:number}} Size.
538 * @override
539 */
540 NavigationList.prototype.measureItem = function(opt_item) {
541 this.measuringTemporaryItemNow_ = true;
542 var result = cr.ui.List.prototype.measureItem.call(this, opt_item);
543 this.measuringTemporaryItemNow_ = false;
544 return result;
545 };
546
547 /**
548 * Creates an element of a navigation list. This method is called from
549 * cr.ui.List internally.
550 *
551 * @param {NavigationModelItem} modelItem NavigationModelItem to be rendered.
552 * @return {NavigationListItem} Rendered element.
553 * @private
554 */
555 NavigationList.prototype.renderRoot_ = function(modelItem) {
556 var item = new NavigationListItem();
557 var volumeInfo =
558 PathUtil.isRootPath(modelItem.path) &&
559 this.volumeManager_.getVolumeInfo(modelItem.path);
560 item.setModelItem(modelItem, volumeInfo && volumeInfo.deviceType);
561
562 var handleClick = function() {
563 if (item.selected &&
564 modelItem.path !== this.directoryModel_.getCurrentDirPath()) {
565 metrics.recordUserAction('FolderShortcut.Navigate');
566 this.changeDirectory_(modelItem);
567 }
568 }.bind(this);
569 item.addEventListener('click', handleClick);
570
571 var handleEject = function() {
572 var unmountCommand = cr.doc.querySelector('command#unmount');
573 // Let's make sure 'canExecute' state of the command is properly set for
574 // the root before executing it.
575 unmountCommand.canExecuteChange(item);
576 unmountCommand.execute(item);
577 };
578 item.addEventListener('eject', handleEject);
579
580 if (this.contextMenu_)
581 item.maybeSetContextMenu(this.contextMenu_);
582
583 return item;
584 };
585
586 /**
587 * Changes the current directory to the given path.
588 * If the given path is not found, a 'shortcut-target-not-found' event is
589 * fired.
590 *
591 * @param {NavigationModelItem} modelItem Directory to be chagned to.
592 * @private
593 */
594 NavigationList.prototype.changeDirectory_ = function(modelItem) {
595 var onErrorCallback = function(error) {
596 if (error.code === FileError.NOT_FOUND_ERR)
597 this.dataModel.onItemNotFoundError(modelItem);
598 }.bind(this);
599
600 this.directoryModel_.changeDirectory(modelItem.path, onErrorCallback);
601 };
602
603 /**
604 * Sets a context menu. Context menu is enabled only on archive and removable
605 * volumes as of now.
606 *
607 * @param {cr.ui.Menu} menu Context menu.
608 */
609 NavigationList.prototype.setContextMenu = function(menu) {
610 this.contextMenu_ = menu;
611
612 for (var i = 0; i < this.dataModel.length; i++) {
613 this.getListItemByIndex(i).maybeSetContextMenu(this.contextMenu_);
614 }
615 };
616
617 /**
618 * Selects the n-th item from the list.
619 *
620 * @param {number} index Item index.
621 * @return {boolean} True for success, otherwise false.
622 */
623 NavigationList.prototype.selectByIndex = function(index) {
624 if (index < 0 || index > this.dataModel.length - 1)
625 return false;
626
627 var newModelItem = this.dataModel.item(index);
628 var newPath = newModelItem.path;
629 if (!newPath)
630 return false;
631
632 // Prevents double-moving to the current directory.
633 // eg. When user clicks the item, changing directory has already been done in
634 // click handler.
635 var entry = this.directoryModel_.getCurrentDirEntry();
636 if (entry && entry.fullPath == newPath)
637 return false;
638
639 metrics.recordUserAction('FolderShortcut.Navigate');
640 this.changeDirectory_(newModelItem);
641 return true;
642 };
643
644 /**
645 * Handler before root item change.
646 * @param {Event} event The event.
647 * @private
648 */
649 NavigationList.prototype.onBeforeSelectionChange_ = function(event) {
650 if (event.changes.length == 1 && !event.changes[0].selected)
651 event.preventDefault();
652 };
653
654 /**
655 * Handler for root item being clicked.
656 * @param {Event} event The event.
657 * @private
658 */
659 NavigationList.prototype.onSelectionChange_ = function(event) {
660 // This handler is invoked even when the navigation list itself changes the
661 // selection. In such case, we shouldn't handle the event.
662 if (this.dontHandleSelectionEvent_)
663 return;
664
665 this.selectByIndex(this.selectionModel.selectedIndex);
666 };
667
668 /**
669 * Invoked when the current directory is changed.
670 * @param {Event} event The event.
671 * @private
672 */
673 NavigationList.prototype.onCurrentDirectoryChanged_ = function(event) {
674 this.selectBestMatchItem_();
675 };
676
677 /**
678 * Invoked when the content in the data model is changed.
679 * @param {Event} event The event.
680 * @private
681 */
682 NavigationList.prototype.onListContentChanged_ = function(event) {
683 this.selectBestMatchItem_();
684 };
685
686 /**
687 * Synchronizes the volume list selection with the current directory, after
688 * it is changed outside of the volume list.
689 * @private
690 */
691 NavigationList.prototype.selectBestMatchItem_ = function() {
692 var entry = this.directoryModel_.getCurrentDirEntry();
693 var path = entry && entry.fullPath;
694 if (!path)
695 return;
696
697 // (1) Select the nearest parent directory (including the shortcut folders).
698 var bestMatchIndex = -1;
699 var bestMatchSubStringLen = 0;
700 for (var i = 0; i < this.dataModel.length; i++) {
701 var itemPath = this.dataModel.item(i).path;
702 if (path.indexOf(itemPath) == 0) {
703 if (bestMatchSubStringLen < itemPath.length) {
704 bestMatchIndex = i;
705 bestMatchSubStringLen = itemPath.length;
706 }
707 }
708 }
709 if (bestMatchIndex != -1) {
710 // Not to invoke the handler of this instance, sets the guard.
711 this.dontHandleSelectionEvent_ = true;
712 this.selectionModel.selectedIndex = bestMatchIndex;
713 this.dontHandleSelectionEvent_ = false;
714 return;
715 }
716
717 // (2) Selects the volume of the current directory.
718 var newRootPath = PathUtil.getRootPath(path);
719 for (var i = 0; i < this.dataModel.length; i++) {
720 var itemPath = this.dataModel.item(i).path;
721 if (PathUtil.getRootPath(itemPath) == newRootPath) {
722 // Not to invoke the handler of this instance, sets the guard.
723 this.dontHandleSelectionEvent_ = true;
724 this.selectionModel.selectedIndex = i;
725 this.dontHandleSelectionEvent_ = false;
726 return;
727 }
728 }
729 };
OLDNEW
« no previous file with comments | « chrome/browser/resources/file_manager/js/metrics.js ('k') | chrome/browser/resources/file_manager/js/path_util.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698