OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 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 // DirectoryTreeUtil | |
9 | |
10 /** | |
11 * Utility methods. They are intended for use only in this file. | |
12 */ | |
13 var DirectoryTreeUtil = {}; | |
14 | |
15 /** | |
16 * Generate a list of the directory entries for the top level on the tree. | |
17 * @return {Array.<DirectoryEntry>} Entries for the top level on the tree. | |
18 */ | |
19 DirectoryTreeUtil.generateTopLevelEntries = function() { | |
20 var entries = [ | |
21 DirectoryModel.fakeDriveEntry_, | |
22 DirectoryModel.fakeDriveOfflineEntry_, | |
23 DirectoryModel.fakeDriveSharedWithMeEntry_, | |
24 DirectoryModel.fakeDriveRecentEntry_, | |
25 ]; | |
26 | |
27 for (var i = 0; i < entries.length; i++) { | |
28 entries[i]['label'] = PathUtil.getRootLabel(entries[i].fullPath); | |
29 } | |
30 | |
31 return entries; | |
32 }; | |
33 | |
34 /** | |
35 * Checks if the given directory can be on the tree or not. | |
36 * | |
37 * @param {string} path Path to be checked. | |
38 * @return {boolean} True if the path is eligible for the directory tree. | |
39 * Otherwise, false. | |
40 */ | |
41 DirectoryTreeUtil.isEligiblePathForDirectoryTree = function(path) { | |
42 return PathUtil.isDriveBasedPath(path); | |
43 }; | |
44 | |
45 Object.freeze(DirectoryTreeUtil); | |
46 | |
47 //////////////////////////////////////////////////////////////////////////////// | |
48 // DirectoryTreeBase | |
49 | |
50 /** | |
51 * Implementation of methods for DirectoryTree and DirectoryItem. These classes | |
52 * inherits cr.ui.Tree/TreeItem so we can't make them inherit this class. | |
53 * Instead, we separate their implementations to this separate object and call | |
54 * it with setting 'this' from DirectoryTree/Item. | |
55 */ | |
56 var DirectoryItemTreeBaseMethods = {}; | |
57 | |
58 /** | |
59 * Updates sub-elements of {@code this} reading {@code DirectoryEntry}. | |
60 * The list of {@code DirectoryEntry} are not updated by this method. | |
61 * | |
62 * @param {boolean} recursive True if the all visible sub-directories are | |
63 * updated recursively including left arrows. If false, the update walks | |
64 * only immediate child directories without arrows. | |
65 */ | |
66 DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) { | |
67 var index = 0; | |
68 var tree = this.parentTree_ || this; // If no parent, 'this' itself is tree. | |
69 while (this.entries_[index]) { | |
70 var currentEntry = this.entries_[index]; | |
71 var currentElement = this.items[index]; | |
72 | |
73 if (index >= this.items.length) { | |
74 var item = new DirectoryItem(currentEntry, this, tree); | |
75 this.add(item); | |
76 index++; | |
77 } else if (currentEntry.fullPath == currentElement.fullPath) { | |
78 if (recursive && this.expanded) | |
79 currentElement.updateSubDirectories(true /* recursive */); | |
80 | |
81 index++; | |
82 } else if (currentEntry.fullPath < currentElement.fullPath) { | |
83 var item = new DirectoryItem(currentEntry, this, tree); | |
84 this.addAt(item, index); | |
85 index++; | |
86 } else if (currentEntry.fullPath > currentElement.fullPath) { | |
87 this.remove(currentElement); | |
88 } | |
89 } | |
90 | |
91 var removedChild; | |
92 while (removedChild = this.items[index]) { | |
93 this.remove(removedChild); | |
94 } | |
95 | |
96 if (index == 0) { | |
97 this.hasChildren = false; | |
98 this.expanded = false; | |
99 } else { | |
100 this.hasChildren = true; | |
101 } | |
102 }; | |
103 | |
104 /** | |
105 * Finds a parent directory of the {@code entry} in {@code this}, and | |
106 * invokes the DirectoryItem.selectByEntry() of the found directory. | |
107 * | |
108 * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be | |
109 * a fake. | |
110 * @return {boolean} True if the parent item is found. | |
111 */ | |
112 DirectoryItemTreeBaseMethods.searchAndSelectByEntry = function(entry) { | |
113 for (var i = 0; i < this.items.length; i++) { | |
114 var item = this.items[i]; | |
115 if (util.isParentEntry(item.entry, entry)) { | |
116 item.selectByEntry(entry); | |
117 return true; | |
118 } | |
119 } | |
120 return false; | |
121 }; | |
122 | |
123 Object.freeze(DirectoryItemTreeBaseMethods); | |
124 | |
125 //////////////////////////////////////////////////////////////////////////////// | |
126 // DirectoryItem | |
127 | |
128 /** | |
129 * A directory in the tree. Each element represents one directory. | |
130 * | |
131 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. | |
132 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. | |
133 * @param {DirectoryTree} tree Current tree, which contains this item. | |
134 * @extends {cr.ui.TreeItem} | |
135 * @constructor | |
136 */ | |
137 function DirectoryItem(dirEntry, parentDirItem, tree) { | |
138 var item = cr.doc.createElement('div'); | |
139 DirectoryItem.decorate(item, dirEntry, parentDirItem, tree); | |
140 return item; | |
141 } | |
142 | |
143 /** | |
144 * @param {HTMLElement} el Element to be DirectoryItem. | |
145 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. | |
146 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. | |
147 * @param {DirectoryTree} tree Current tree, which contains this item. | |
148 */ | |
149 DirectoryItem.decorate = | |
150 function(el, dirEntry, parentDirItem, tree) { | |
151 el.__proto__ = DirectoryItem.prototype; | |
152 (/** @type {DirectoryItem} */ el).decorate( | |
153 dirEntry, parentDirItem, tree); | |
154 }; | |
155 | |
156 DirectoryItem.prototype = { | |
157 __proto__: cr.ui.TreeItem.prototype, | |
158 | |
159 /** | |
160 * The DirectoryEntry corresponding to this DirectoryItem. This may be | |
161 * a dummy DirectoryEntry. | |
162 * @type {DirectoryEntry|Object} | |
163 */ | |
164 get entry() { | |
165 return this.dirEntry_; | |
166 }, | |
167 | |
168 /** | |
169 * The element containing the label text and the icon. | |
170 * @type {!HTMLElement} | |
171 * @override | |
172 */ | |
173 get labelElement() { | |
174 return this.firstElementChild.querySelector('.label'); | |
175 } | |
176 }; | |
177 | |
178 /** | |
179 * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). | |
180 * | |
181 * @param {boolean} recursive True if the all visible sub-directories are | |
182 * updated recursively including left arrows. If false, the update walks | |
183 * only immediate child directories without arrows. | |
184 */ | |
185 DirectoryItem.prototype.updateSubElementsFromList = function(recursive) { | |
186 DirectoryItemTreeBaseMethods.updateSubElementsFromList.call(this, recursive); | |
187 }; | |
188 | |
189 /** | |
190 * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). | |
191 * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be | |
192 * a fake. | |
193 * @return {boolean} True if the parent item is found. | |
194 */ | |
195 DirectoryItem.prototype.searchAndSelectByEntry = function(entry) { | |
196 return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry); | |
197 }; | |
198 | |
199 /** | |
200 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. | |
201 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. | |
202 * @param {DirectoryTree} tree Current tree, which contains this item. | |
203 */ | |
204 DirectoryItem.prototype.decorate = function( | |
205 dirEntry, parentDirItem, tree) { | |
206 var path = dirEntry.fullPath; | |
207 var label; | |
208 label = dirEntry.label ? dirEntry.label : dirEntry.name; | |
209 | |
210 this.className = 'tree-item'; | |
211 this.innerHTML = | |
212 '<div class="tree-row">' + | |
213 ' <span class="expand-icon"></span>' + | |
214 ' <span class="icon"></span>' + | |
215 ' <span class="label"></span>' + | |
216 ' <div class="root-eject"></div>' + | |
217 '</div>' + | |
218 '<div class="tree-children"></div>'; | |
219 this.setAttribute('role', 'treeitem'); | |
220 | |
221 this.parentTree_ = tree; | |
222 this.directoryModel_ = tree.directoryModel; | |
223 this.parent_ = parentDirItem; | |
224 this.label = label; | |
225 this.fullPath = path; | |
226 this.dirEntry_ = dirEntry; | |
227 this.fileFilter_ = this.directoryModel_.getFileFilter(); | |
228 | |
229 // Sets hasChildren=false tentatively. This will be overridden after | |
230 // scanning sub-directories in DirectoryTreeUtil.updateSubElementsFromList. | |
231 this.hasChildren = false; | |
232 | |
233 this.addEventListener('expand', this.onExpand_.bind(this), false); | |
234 var icon = this.querySelector('.icon'); | |
235 icon.classList.add('volume-icon'); | |
236 var iconType = PathUtil.getRootType(path); | |
237 if (iconType && PathUtil.isRootPath(path)) | |
238 icon.setAttribute('volume-type-icon', iconType); | |
239 else | |
240 icon.setAttribute('file-type-icon', 'folder'); | |
241 | |
242 var eject = this.querySelector('.root-eject'); | |
243 eject.hidden = !PathUtil.isUnmountableByUser(path); | |
244 eject.addEventListener('click', | |
245 function(event) { | |
246 event.stopPropagation(); | |
247 if (!PathUtil.isUnmountableByUser(path)) | |
248 return; | |
249 | |
250 tree.volumeManager.unmount(path, function() {}, function() {}); | |
251 }.bind(this)); | |
252 | |
253 if (this.parentTree_.contextMenuForSubitems) | |
254 this.setContextMenu(this.parentTree_.contextMenuForSubitems); | |
255 // Adds handler for future change. | |
256 this.parentTree_.addEventListener( | |
257 'contextMenuForSubitemsChange', | |
258 function(e) { this.setContextMenu(e.newValue); }.bind(this)); | |
259 | |
260 if (parentDirItem.expanded) | |
261 this.updateSubDirectories(false /* recursive */); | |
262 }; | |
263 | |
264 /** | |
265 * Overrides WebKit's scrollIntoViewIfNeeded, which doesn't work well with | |
266 * a complex layout. This call is not necessary, so we are ignoring it. | |
267 * | |
268 * @param {boolean} unused Unused. | |
269 * @override | |
270 */ | |
271 DirectoryItem.prototype.scrollIntoViewIfNeeded = function(unused) { | |
272 }; | |
273 | |
274 /** | |
275 * Removes the child node, but without selecting the parent item, to avoid | |
276 * unintended changing of directories. Removing is done externally, and other | |
277 * code will navigate to another directory. | |
278 * | |
279 * @param {!cr.ui.TreeItem} child The tree item child to remove. | |
280 * @override | |
281 */ | |
282 DirectoryItem.prototype.remove = function(child) { | |
283 this.lastElementChild.removeChild(child); | |
284 if (this.items.length == 0) | |
285 this.hasChildren = false; | |
286 }; | |
287 | |
288 /** | |
289 * Invoked when the item is being expanded. | |
290 * @param {!UIEvent} e Event. | |
291 * @private | |
292 **/ | |
293 DirectoryItem.prototype.onExpand_ = function(e) { | |
294 this.updateSubDirectories( | |
295 true /* recursive */, | |
296 function() {}, | |
297 function() { | |
298 this.expanded = false; | |
299 }.bind(this)); | |
300 | |
301 e.stopPropagation(); | |
302 }; | |
303 | |
304 /** | |
305 * Retrieves the latest subdirectories and update them on the tree. | |
306 * @param {boolean} recursive True if the update is recursively. | |
307 * @param {function()=} opt_successCallback Callback called on success. | |
308 * @param {function()=} opt_errorCallback Callback called on error. | |
309 */ | |
310 DirectoryItem.prototype.updateSubDirectories = function( | |
311 recursive, opt_successCallback, opt_errorCallback) { | |
312 if (util.isFakeDirectoryEntry(this.entry)) { | |
313 if (opt_errorCallback) | |
314 opt_errorCallback(); | |
315 return; | |
316 } | |
317 | |
318 var sortEntries = function(fileFilter, entries) { | |
319 entries.sort(function(a, b) { | |
320 return (a.name.toLowerCase() > b.name.toLowerCase()) ? 1 : -1; | |
321 }); | |
322 return entries.filter(fileFilter.filter.bind(fileFilter)); | |
323 }; | |
324 | |
325 var onSuccess = function(entries) { | |
326 this.entries_ = entries; | |
327 this.redrawSubDirectoryList_(recursive); | |
328 opt_successCallback && opt_successCallback(); | |
329 }.bind(this); | |
330 | |
331 var reader = this.entry.createReader(); | |
332 var entries = []; | |
333 var readEntry = function() { | |
334 reader.readEntries(function(results) { | |
335 if (!results.length) { | |
336 onSuccess(sortEntries(this.fileFilter_, entries)); | |
337 return; | |
338 } | |
339 | |
340 for (var i = 0; i < results.length; i++) { | |
341 var entry = results[i]; | |
342 if (entry.isDirectory) | |
343 entries.push(entry); | |
344 } | |
345 readEntry(); | |
346 }.bind(this)); | |
347 }.bind(this); | |
348 readEntry(); | |
349 }; | |
350 | |
351 /** | |
352 * Updates sub-elements of {@code parentElement} reading {@code DirectoryEntry} | |
353 * with calling {@code iterator}. | |
354 * | |
355 * @param {string} changedDirectryPath The path of the changed directory. | |
356 */ | |
357 DirectoryItem.prototype.updateItemByPath = function(changedDirectryPath) { | |
358 if (changedDirectryPath === this.entry.fullPath) { | |
359 this.updateSubDirectories(false /* recursive */); | |
360 return; | |
361 } | |
362 | |
363 for (var i = 0; i < this.items.length; i++) { | |
364 var item = this.items[i]; | |
365 if (PathUtil.isParentPath(item.entry.fullPath, changedDirectryPath)) { | |
366 item.updateItemByPath(changedDirectryPath); | |
367 break; | |
368 } | |
369 } | |
370 }; | |
371 | |
372 /** | |
373 * Redraw subitems with the latest information. The items are sorted in | |
374 * alphabetical order, case insensitive. | |
375 * @param {boolean} recursive True if the update is recursively. | |
376 * @private | |
377 */ | |
378 DirectoryItem.prototype.redrawSubDirectoryList_ = function(recursive) { | |
379 this.updateSubElementsFromList(recursive); | |
380 }; | |
381 | |
382 /** | |
383 * Select the item corresponding to the given {@code entry}. | |
384 * @param {DirectoryEntry|Object} entry The entry to be selected. Can be a fake. | |
385 */ | |
386 DirectoryItem.prototype.selectByEntry = function(entry) { | |
387 if (util.isSameEntry(entry, this.entry)) { | |
388 this.selected = true; | |
389 return; | |
390 } | |
391 | |
392 if (this.searchAndSelectByEntry(entry)) | |
393 return; | |
394 | |
395 // If the path doesn't exist, updates sub directories and tryes again. | |
396 this.updateSubDirectories( | |
397 false /* recursive */, | |
398 this.searchAndSelectByEntry.bind(this, entry)); | |
399 }; | |
400 | |
401 /** | |
402 * Executes the assigned action as a drop target. | |
403 */ | |
404 DirectoryItem.prototype.doDropTargetAction = function() { | |
405 this.expanded = true; | |
406 }; | |
407 | |
408 /** | |
409 * Executes the assigned action. DirectoryItem performs changeDirectory. | |
410 */ | |
411 DirectoryItem.prototype.doAction = function() { | |
412 if (this.fullPath != this.directoryModel_.getCurrentDirPath()) | |
413 this.directoryModel_.changeDirectory(this.fullPath); | |
414 }; | |
415 | |
416 /** | |
417 * Sets the context menu for directory tree. | |
418 * @param {cr.ui.Menu} menu Menu to be set. | |
419 */ | |
420 DirectoryItem.prototype.setContextMenu = function(menu) { | |
421 if (this.entry && PathUtil.isEligibleForFolderShortcut(this.entry.fullPath)) | |
422 cr.ui.contextMenuHandler.setContextMenu(this, menu); | |
423 }; | |
424 | |
425 //////////////////////////////////////////////////////////////////////////////// | |
426 // DirectoryTree | |
427 | |
428 /** | |
429 * Tree of directories on the middle bar. This element is also the root of | |
430 * items, in other words, this is the parent of the top-level items. | |
431 * | |
432 * @constructor | |
433 * @extends {cr.ui.Tree} | |
434 */ | |
435 function DirectoryTree() {} | |
436 | |
437 /** | |
438 * Decorates an element. | |
439 * @param {HTMLElement} el Element to be DirectoryTree. | |
440 * @param {DirectoryModel} directoryModel Current DirectoryModel. | |
441 * @param {VolumeManagerWrapper} volumeManager VolumeManager of the system. | |
442 */ | |
443 DirectoryTree.decorate = function(el, directoryModel, volumeManager) { | |
444 el.__proto__ = DirectoryTree.prototype; | |
445 (/** @type {DirectoryTree} */ el).decorate(directoryModel, volumeManager); | |
446 }; | |
447 | |
448 DirectoryTree.prototype = { | |
449 __proto__: cr.ui.Tree.prototype, | |
450 | |
451 // DirectoryTree is always expanded. | |
452 get expanded() { return true; }, | |
453 /** | |
454 * @param {boolean} value Not used. | |
455 */ | |
456 set expanded(value) {}, | |
457 | |
458 /** | |
459 * The DirectoryEntry corresponding to this DirectoryItem. This may be | |
460 * a dummy DirectoryEntry. | |
461 * @type {DirectoryEntry|Object} | |
462 * @override | |
463 **/ | |
464 get entry() { | |
465 return this.dirEntry_; | |
466 }, | |
467 | |
468 /** | |
469 * The DirectoryModel this tree corresponds to. | |
470 * @type {DirectoryModel} | |
471 */ | |
472 get directoryModel() { | |
473 return this.directoryModel_; | |
474 }, | |
475 | |
476 /** | |
477 * The VolumeManager instance of the system. | |
478 * @type {VolumeManager} | |
479 */ | |
480 get volumeManager() { | |
481 return this.volumeManager_; | |
482 }, | |
483 }; | |
484 | |
485 cr.defineProperty(DirectoryTree, 'contextMenuForSubitems', cr.PropertyKind.JS); | |
486 | |
487 /** | |
488 * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). | |
489 * | |
490 * @param {boolean} recursive True if the all visible sub-directories are | |
491 * updated recursively including left arrows. If false, the update walks | |
492 * only immediate child directories without arrows. | |
493 */ | |
494 DirectoryTree.prototype.updateSubElementsFromList = function(recursive) { | |
495 DirectoryItemTreeBaseMethods.updateSubElementsFromList.call(this, recursive); | |
496 }; | |
497 | |
498 /** | |
499 * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). | |
500 * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be | |
501 * a fake. | |
502 * @return {boolean} True if the parent item is found. | |
503 */ | |
504 DirectoryTree.prototype.searchAndSelectByEntry = function(entry) { | |
505 return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry); | |
506 }; | |
507 | |
508 /** | |
509 * Decorates an element. | |
510 * @param {DirectoryModel} directoryModel Current DirectoryModel. | |
511 * @param {VolumeManagerWrapper} volumeManager VolumeManager of the system. | |
512 */ | |
513 DirectoryTree.prototype.decorate = function(directoryModel, volumeManager) { | |
514 cr.ui.Tree.prototype.decorate.call(this); | |
515 | |
516 this.directoryModel_ = directoryModel; | |
517 this.volumeManager_ = volumeManager; | |
518 this.entries_ = DirectoryTreeUtil.generateTopLevelEntries(); | |
519 | |
520 this.fileFilter_ = this.directoryModel_.getFileFilter(); | |
521 this.fileFilter_.addEventListener('changed', | |
522 this.onFilterChanged_.bind(this)); | |
523 | |
524 this.directoryModel_.addEventListener('directory-changed', | |
525 this.onCurrentDirectoryChanged_.bind(this)); | |
526 | |
527 // Add a handler for directory change. | |
528 this.addEventListener('change', function() { | |
529 if (this.selectedItem && | |
530 (!this.currentEntry_ || | |
531 !util.isSameEntry(this.currentEntry_, this.selectedItem.entry))) { | |
532 this.currentEntry_ = this.selectedItem.entry; | |
533 this.selectedItem.doAction(); | |
534 return; | |
535 } | |
536 }.bind(this)); | |
537 | |
538 this.privateOnDirectoryChangedBound_ = | |
539 this.onDirectoryContentChanged_.bind(this); | |
540 chrome.fileBrowserPrivate.onDirectoryChanged.addListener( | |
541 this.privateOnDirectoryChangedBound_); | |
542 | |
543 this.scrollBar_ = MainPanelScrollBar(); | |
544 this.scrollBar_.initialize(this.parentNode, this); | |
545 | |
546 // Once, draws the list with the fake '/drive/' entry. | |
547 this.redraw(false /* recursive */); | |
548 // Resolves 'My Drive' entry and replaces the fake with the true one. | |
549 this.maybeResolveMyDriveRoot_(function() { | |
550 // After the true entry is resolved, draws the list again. | |
551 this.redraw(true /* recursive */); | |
552 }.bind(this)); | |
553 }; | |
554 | |
555 /** | |
556 * Select the item corresponding to the given entry. | |
557 * @param {DirectoryEntry|Object} entry The directory entry to be selected. Can | |
558 * be a fake. | |
559 */ | |
560 DirectoryTree.prototype.selectByEntry = function(entry) { | |
561 // If the target directory is not in the tree, do nothing. | |
562 if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(entry.fullPath)) | |
563 return; | |
564 | |
565 this.maybeResolveMyDriveRoot_(function() { | |
566 if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry)) | |
567 return; | |
568 | |
569 if (this.searchAndSelectByEntry(entry)) | |
570 return; | |
571 | |
572 this.selectedItem = null; | |
573 this.updateSubDirectories( | |
574 false /* recursive */, | |
575 // Success callback, failure is not handled. | |
576 function() { | |
577 if (!this.searchAndSelectByEntry(entry)) | |
578 this.selectedItem = null; | |
579 }.bind(this)); | |
580 }.bind(this)); | |
581 }; | |
582 | |
583 /** | |
584 * Resolves the My Drive root's entry, if it is a fake. If the entry is already | |
585 * resolved to a DirectoryEntry, completionCallback() will be called | |
586 * immediately. | |
587 * @param {function()} completionCallback Called when the resolving is | |
588 * done (or the entry is already resolved), regardless if it is | |
589 * successfully done or not. | |
590 * @private | |
591 */ | |
592 DirectoryTree.prototype.maybeResolveMyDriveRoot_ = function( | |
593 completionCallback) { | |
594 var myDriveItem = this.items[0]; | |
595 if (!util.isFakeDirectoryEntry(myDriveItem.entry)) { | |
596 // The entry is already resolved. Don't need to try again. | |
597 completionCallback(); | |
598 return; | |
599 } | |
600 | |
601 // The entry is a fake. | |
602 this.directoryModel_.resolveDirectory( | |
603 myDriveItem.fullPath, | |
604 function(entry) { | |
605 if (!util.isFakeDirectoryEntry(entry)) { | |
606 myDriveItem.dirEntry_ = entry; | |
607 } | |
608 | |
609 completionCallback(); | |
610 }, | |
611 completionCallback); | |
612 }; | |
613 | |
614 /** | |
615 * Retrieves the latest subdirectories and update them on the tree. | |
616 * @param {boolean} recursive True if the update is recursively. | |
617 * @param {function()=} opt_successCallback Callback called on success. | |
618 * @param {function()=} opt_errorCallback Callback called on error. | |
619 */ | |
620 DirectoryTree.prototype.updateSubDirectories = function( | |
621 recursive, opt_successCallback, opt_errorCallback) { | |
622 this.entries_ = DirectoryTreeUtil.generateTopLevelEntries(); | |
623 this.redraw(recursive); | |
624 if (opt_successCallback) | |
625 opt_successCallback(); | |
626 }; | |
627 | |
628 /** | |
629 * Redraw the list. | |
630 * @param {boolean} recursive True if the update is recursively. False if the | |
631 * only root items are updated. | |
632 */ | |
633 DirectoryTree.prototype.redraw = function(recursive) { | |
634 this.updateSubElementsFromList(recursive); | |
635 }; | |
636 | |
637 /** | |
638 * Invoked when the filter is changed. | |
639 * @private | |
640 */ | |
641 DirectoryTree.prototype.onFilterChanged_ = function() { | |
642 // Returns immediately, if the tree is hidden. | |
643 if (this.hidden) | |
644 return; | |
645 | |
646 this.redraw(true /* recursive */); | |
647 }; | |
648 | |
649 /** | |
650 * Invoked when a directory is changed. | |
651 * @param {!UIEvent} event Event. | |
652 * @private | |
653 */ | |
654 DirectoryTree.prototype.onDirectoryContentChanged_ = function(event) { | |
655 if (event.eventType == 'changed') { | |
656 var path = util.extractFilePath(event.directoryUrl); | |
657 if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(path)) | |
658 return; | |
659 | |
660 var myDriveItem = this.items[0]; | |
661 myDriveItem.updateItemByPath(path); | |
662 } | |
663 }; | |
664 | |
665 /** | |
666 * Invoked when the current directory is changed. | |
667 * @param {!UIEvent} event Event. | |
668 * @private | |
669 */ | |
670 DirectoryTree.prototype.onCurrentDirectoryChanged_ = function(event) { | |
671 this.selectByEntry(event.newDirEntry); | |
672 }; | |
673 | |
674 /** | |
675 * Sets the margin height for the transparent preview panel at the bottom. | |
676 * @param {number} margin Margin to be set in px. | |
677 */ | |
678 DirectoryTree.prototype.setBottomMarginForPanel = function(margin) { | |
679 this.style.paddingBottom = margin + 'px'; | |
680 this.scrollBar_.setBottomMarginForPanel(margin); | |
681 }; | |
682 | |
683 /** | |
684 * Updates the UI after the layout has changed. | |
685 */ | |
686 DirectoryTree.prototype.relayout = function() { | |
687 cr.dispatchSimpleEvent(this, 'relayout'); | |
688 }; | |
OLD | NEW |