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

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

Issue 12857002: Files.app: Add subfolders in the left nav (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed comments Created 7 years, 9 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
OLDNEW
(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 /**
6 * Update sub-elements of {@code parentElement} reading {@code DirectoryEntry}
mtomasz 2013/03/14 10:15:39 Update -> updates
yoshiki 2013/03/14 13:43:42 Done.
7 * with calling {@code iterator}.
8 *
9 * @param {DirectoryItem|DirectoryTree} parentElement Parent element of newly
10 * created items.
11 * @param {function(number): DirectoryEntry} iterator Function which returns
12 * the n-th Entry in the directory.
13 * @param {DirectoryModel} directoryModel Current DirectoryModel.
14 */
15 function updateSubElementsFromList(parentElement, iterator, directoryModel) {
16 var index = 0;
17 while (iterator(index)) {
18 var currentEntry = iterator(index);
19 var currentElement = parentElement.items[index];
20
21 if (index >= parentElement.items.length) {
22 var item = new DirectoryItem(currentEntry, parentElement, directoryModel);
23 parentElement.add(item);
24 index++;
25 } else if (currentEntry.fullPath === currentElement.fullPath) {
26 index++;
27 } else if (currentEntry.fullPath < currentElement.fullPath) {
28 var item = new DirectoryItem(currentEntry, parentElement, directoryModel);
29 parentElement.addAt(item, index);
30 index++;
31 } else if (currentEntry.fullPath > currentElement.fullPath) {
32 parentElement.remove(currentElement);
33 }
34 }
35
36 var removedChild;
37 while (removedChild = parentElement.items[index]) {
38 parentElement.remove(removedChild);
39 }
40
41 if (index === 0) {
42 parentElement.hasChildren = false;
43 parentElement.expanded = false;
44 } else {
45 parentElement.hasChildren = true;
46 }
47 }
48
49 /**
50 * A directory in the tree. One this element reprecents one directory. One this
mtomasz 2013/03/14 10:15:39 reprecents -> represents One this -> each
yoshiki 2013/03/14 13:43:42 Done. Thanks!
51 * element reprecents one director.
52 *
53 * @param {DirectoryEntry} parentDirEntry DirectoryEntry of this item.
54 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
55 * @param {DirectoryModel} directoryModel Current DirectoryModel.
56 * @extends {cr.ui.TreeItem}
57 * @constructor
58 */
59 function DirectoryItem(parentDirEntry, parentDirItem, directoryModel) {
60 var item = cr.doc.createElement('div');
61 DirectoryItem.decorate(item, parentDirEntry, parentDirItem, directoryModel);
62 return item;
63 }
64
65 /**
66 * @param {HTMLElement} el Element to be DirectoryItem.
67 * @param {DirectoryEntry} parentDirEntry DirectoryEntry of this item.
68 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
69 * @param {DirectoryModel} directoryModel Current DirectoryModel.
70 */
71 DirectoryItem.decorate =
72 function(el, parentDirEntry, parentDirItem, directoryModel) {
73 el.__proto__ = DirectoryItem.prototype;
74 (/** @type {DirectoryItem} */ el).decorate(
75 parentDirEntry, parentDirItem, directoryModel);
76 };
77
78 DirectoryItem.prototype = {
79 __proto__: cr.ui.TreeItem.prototype,
80
81 /**
82 * The element containing the label text and the icon.
83 * @type {!HTMLElement}
84 * @override
85 **/
86 get labelElement() {
87 return this.firstElementChild.querySelector('.label');
88 }
89 };
90
91 /**
92 * @param {DirectoryEntry} parentDirEntry DirectoryEntry of this item.
93 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item.
94 * @param {DirectoryModel} directoryModel Current DirectoryModel.
95 */
96 DirectoryItem.prototype.decorate =
mtomasz 2013/03/14 10:15:39 This indentation looks strange. I think we never d
yoshiki 2013/03/14 13:43:42 I prefer to (1). But there are some 'decorate =\n
97 function(parentDirEntry, parentDirItem, directoryModel) {
98 var path = parentDirEntry.fullPath;
99 var label = PathUtil.isRootPath(path) ?
100 PathUtil.getRootLabel(path) : parentDirEntry.name;
mtomasz 2013/03/14 10:15:39 Indentation is off. http://google-styleguide.googl
yoshiki 2013/03/14 13:43:42 Thanks!
101
102 this.className = 'tree-item';
103 this.innerHTML =
mtomasz 2013/03/14 10:15:39 1. nit: It's suprising that in html5 quoting is no
yoshiki 2013/03/14 13:43:42 nit: It's suprising that in html5 quoting is not a
104 '<div class=tree-row>' +
mtomasz 2013/03/14 10:15:39 Indentation off. 6 -> 4 spaces.
yoshiki 2013/03/14 13:43:42 Done.
105 '<span class=expand-icon></span>' +
106 '<span class=icon></span>' +
107 '<span class=label></span>' +
108 '<div class=root-eject></div>' +
109 '</div>' +
110 '<div class=tree-children></div>';
111 this.setAttribute('role', 'treeitem');
mtomasz 2013/03/14 10:15:39 nit: Does ChromeVox work fine with the new sidebar
yoshiki 2013/03/14 13:43:42 As I tested, it partially works but it's not compl
112
113 this.directoryModel_ = directoryModel;
114 this.parent_ = parentDirItem;
115 this.label = label;
116 this.fullPath = path;
117
118 // Sets hasChildren=true tentatively. This will be overridden after
119 // scanning sub-directories in updateSubElementsFromList.
120 this.hasChildren = true;
121
122 this.addEventListener('expand', this.onExpand_.bind(this), true);
123
124 var volumeManager = VolumeManager.getInstance();
125 var icon = this.querySelector('.icon');
126 if (PathUtil.isRootPath(path)) {
127 icon.classList.add('volume-icon');
128 var iconType = PathUtil.getRootType(path);
129 icon.setAttribute('volume-type-icon', iconType);
130
131 if (iconType === RootType.REMOVABLE)
mtomasz 2013/03/14 10:15:39 == should be sufficient here.
yoshiki 2013/03/14 13:43:42 Done.
132 icon.setAttribute('volume-subtype', volumeManager.getDeviceType(path));
133 }
134
135 var eject = this.querySelector('.root-eject');
136 eject.hidden = !PathUtil.isUnmountableByUser(path);
137 eject.addEventListener('click',
138 function(event) {
139 event.stopPropagation();
140 if (!PathUtil.isUnmountableByUser(path))
141 return;
142
143 volumeManager.unmount(path, function() {}, function() {});
144 }.bind(this));
145
146 if ('expanded' in parentDirItem || parentDirItem.expanded)
147 this.updateSubDirectoriesWithEntry_(parentDirEntry);
148 };
149
150 /**
151 * Invoked when the item is being expanded.
152 * @param {!UIEvent} e Event.
153 * @private
154 **/
155 DirectoryItem.prototype.onExpand_ = function(e) {
156 this.updateSubDirectories(function() {
157 this.expanded = false;
158 }.bind(this));
159
160 e.stopPropagation();
161 };
162
163 /**
164 * Retrieve the latest subdirectories and update them on the tree.
165 *
mtomasz 2013/03/14 10:15:39 Remove line here, since it is only 2 line jsdoc. I
yoshiki 2013/03/14 13:43:42 Done.
166 * @param {function()=} opt_errorCallback Callback called on error.
167 */
168 DirectoryItem.prototype.updateSubDirectories = function(opt_errorCallback) {
169 this.directoryModel_.resolveDirectory(
170 this.fullPath,
171 function(entry) {
172 this.updateSubDirectoriesWithEntry_(entry, opt_errorCallback);
173 }.bind(this),
174 opt_errorCallback);
175 };
176
177 /**
178 * Retrieve the latest subdirectories and update them on the tree.
179 *
180 * @param {!DirectoryEntry} dirEntry DirectoryEntry to read from.
181 * @param {function()=} opt_errorCallback Callback called on error.
182 * @private
183 */
184 DirectoryItem.prototype.updateSubDirectoriesWithEntry_ =
185 function(dirEntry, opt_errorCallback) {
186 // Skips if the entry is dummy.
187 if (!('createReader' in dirEntry)) {
mtomasz 2013/03/14 10:15:39 instanceof doesn't work here?
yoshiki 2013/03/14 13:43:42 instanceof doesn't work here, since we can't get t
mtomasz 2013/03/15 04:23:20 Got it.
188 if (opt_errorCallback)
189 opt_errorCallback();
190 return;
191 }
192
193 var reader = dirEntry.createReader();
194 var entries = [];
195
196 var readEntry = function() {
197 reader.readEntries(function(results) {
198 if (results.length === 0) {
mtomasz 2013/03/14 10:15:39 nit: I think == 0 is sufficient, or even if (!resu
yoshiki 2013/03/14 13:43:42 Done.
199 this.entries_ = entries.sort();
200 this.redrawSubDirectoryList_();
201 return;
202 }
203
204 for (var i = 0; i < results.length; i++) {
205 var entry = results[i];
206 if (entry.isDirectory)
207 entries.push(entry);
208 }
209 readEntry();
210 }.bind(this));
211 }.bind(this);
212 readEntry();
213 };
214
215 /**
216 * @private
217 */
218 DirectoryItem.prototype.redrawSubDirectoryList_ = function() {
219 var entries = this.entries_;
220 updateSubElementsFromList(this,
221 function(i) { return entries[i]; },
222 this.directoryModel_);
223 };
224
225 /**
226 * Tree of directories on sidebar. This element is also the root of items, in
mtomasz 2013/03/14 10:15:39 nit: on sidebar -> on the sidebar.
yoshiki 2013/03/14 13:43:42 Done.
227 * other words, this is the parent of the top-level items.
228 *
229 * @constructor
230 * @extends {cr.ui.Tree}
231 */
232 function DirectoryTree() {}
233
234 /**
235 * Decorates element.
mtomasz 2013/03/14 10:15:39 nit: Decorates an element.
yoshiki 2013/03/14 13:43:42 Done.
236 * @param {HTMLElement} el Element to be DirectoryTree.
237 * @param {DirectoryModel} directoryModel Current DirectoryModel.
238 */
239 DirectoryTree.decorate = function(el, directoryModel) {
240 el.__proto__ = DirectoryTree.prototype;
241 (/** @type {DirectoryTree} */ el).decorate(directoryModel);
242 };
243
244 DirectoryTree.prototype = {
245 __proto__: cr.ui.Tree.prototype,
246 };
247
248 /**
249 * Decorates element.
250 * @param {DirectoryModel} directoryModel Current DirectoryModel.
251 */
252 DirectoryTree.prototype.decorate = function(directoryModel) {
253 cr.ui.Tree.prototype.decorate.call(this);
254
255 this.directoryModel_ = directoryModel;
256
257 this.rootsList_ = this.directoryModel_.getRootsList();
258 this.rootsList_.addEventListener('change',
259 this.onRootsListChanged_.bind(this));
260 this.rootsList_.addEventListener('permuted',
261 this.onRootsListChanged_.bind(this));
262 this.onRootsListChanged_();
263 };
264
265 /**
266 * Sets a context menu. Context menu is enabled only archive and removable
mtomasz 2013/03/14 10:15:39 only -> only on
yoshiki 2013/03/14 13:43:42 Done. Thanks!
267 * volumes as of now.
268 *
269 * @param {cr.ui.Menu} menu Context menu.
270 */
271 DirectoryTree.prototype.setContextMenu = function(menu) {
272 this.contextMenu_ = menu;
273
274 for (var i = 0; i < this.rootsList_.length; i++) {
275 var item = this.rootsList_.item(i);
276 var type = PathUtil.getRootType(item.fullPath);
277 // Context menu is set only to archive and removable volumes.
278 if (type === RootType.ARCHIVE || type === RootType.REMOVABLE) {
279 cr.ui.contextMenuHandler.setContextMenu(this.items[i].rowElement,
280 this.contextMenu_);
281 }
282 }
283 };
284
285 /**
286 * Invoked when the root list is changed.
287 * @private
288 */
289 DirectoryTree.prototype.onRootsListChanged_ = function() {
290 var rootsList = this.rootsList_;
291 updateSubElementsFromList(this,
292 rootsList.item.bind(rootsList),
293 this.directoryModel_);
294 this.setContextMenu(this.contextMenu_);
295 };
296
297 /**
298 * Returns the path of the current selected item.
mtomasz 2013/03/14 10:15:39 nit: current -> currently (or remove).
yoshiki 2013/03/14 13:43:42 Done.
299 * @return {string} The current path.
300 */
301 DirectoryTree.prototype.getCurrentPath = function() {
302 return this.selectedItem ? this.selectedItem.fullPath : null;
303 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698