Index: chrome/browser/resources/file_manager/js/file_manager.js |
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js |
index 03bc6c065b833340ae98ae18fba8097f88ebef3b..1e7fac2939fab224d1cd4bf3d4017f4228027d37 100644 |
--- a/chrome/browser/resources/file_manager/js/file_manager.js |
+++ b/chrome/browser/resources/file_manager/js/file_manager.js |
@@ -30,6 +30,8 @@ function FileManager(dialogDom, rootEntries, params) { |
this.filesystem_ = rootEntries[0].filesystem; |
this.params_ = params || {}; |
+ this.listType_ = null; |
+ |
this.document_ = dialogDom.ownerDocument; |
this.dialogType_ = |
this.params_.type || FileManager.DialogType.FULL_PAGE; |
@@ -52,7 +54,9 @@ function FileManager(dialogDom, rootEntries, params) { |
chrome.fileBrowserPrivate.onDiskChanged.addListener( |
this.onDiskChanged_.bind(this)); |
- this.table.querySelector('.list').focus(); |
+ // TODO(rginda) Add a focus() method to the various list classes to take care |
+ // of this. |
+ // this.currentList_.list_.focus(); |
} |
FileManager.prototype = { |
@@ -146,29 +150,40 @@ FileManager.prototype = { |
* 'unknown'. |
*/ |
function getIconType(entry) { |
- if (entry.isDirectory) |
- return 'folder'; |
- |
- for (var name in iconTypes) { |
- var value = iconTypes[name]; |
- |
- if (value instanceof RegExp) { |
- if (value.test(entry.name)) |
- return name; |
- } else if (typeof value == 'function') { |
- try { |
- if (value(entry)) |
- return name; |
- } catch (ex) { |
- console.error('Caught exception while evaluating iconType: ' + |
- name, ex); |
+ if (entry.cachedIconType_) |
+ return entry.cachedIconType_; |
+ |
+ var rv = 'unknown'; |
+ |
+ if (entry.isDirectory) { |
+ rv = 'folder'; |
+ } else { |
+ for (var name in iconTypes) { |
+ var value = iconTypes[name]; |
+ |
+ if (value instanceof RegExp) { |
+ if (value.test(entry.name)) { |
+ rv = name; |
+ break; |
+ } |
+ } else if (typeof value == 'function') { |
+ try { |
+ if (value(entry)) { |
+ rv = name; |
+ break; |
+ } |
+ } catch (ex) { |
+ console.error('Caught exception while evaluating iconType: ' + |
+ name, ex); |
+ } |
+ } else { |
+ console.log('Unexpected value in iconTypes[' + name + ']: ' + value); |
} |
- } else { |
- console.log('Unexpected value in iconTypes[' + name + ']: ' + value); |
} |
} |
- return 'unknown'; |
+ entry.cachedIconType_ = rv; |
+ return rv; |
} |
/** |
@@ -328,7 +343,7 @@ FileManager.prototype = { |
* icon type is known. |
*/ |
function cacheEntryIconType(entry, successCallback) { |
- entry.cachedIconType_ = getIconType(entry); |
+ getIconType(entry); |
if (successCallback) |
setTimeout(function() { successCallback(entry) }, 0); |
} |
@@ -351,6 +366,11 @@ FileManager.prototype = { |
FULL_PAGE: 'full-page' |
}; |
+ FileManager.ListType = { |
+ DETAIL: 'detail', |
+ THUMBNAIL: 'thumb' |
+ }; |
+ |
/** |
* Load translated strings. |
*/ |
@@ -404,13 +424,80 @@ FileManager.prototype = { |
// Populate the static localized strings. |
i18nTemplate.process(this.document_, localStrings.templateData); |
- // Set up the detail table. |
- var dataModel = new cr.ui.table.TableDataModel([]); |
- dataModel.sort('name'); |
- dataModel.addEventListener('sorted', |
- this.onDataModelSorted_.bind(this)); |
- dataModel.prepareSort = this.prepareSort_.bind(this); |
+ this.dataModel_ = new cr.ui.table.TableDataModel([]); |
+ this.dataModel_.sort('name'); |
+ this.dataModel_.addEventListener('sorted', |
+ this.onDataModelSorted_.bind(this)); |
+ this.dataModel_.prepareSort = this.prepareSort_.bind(this); |
+ |
+ this.initTable_(); |
+ this.initGrid_(); |
+ this.setListType(FileManager.ListType.DETAIL); |
+ |
+ this.onResize_(); |
+ this.dialogDom_.style.opacity = '1'; |
+ }; |
+ |
+ |
+ FileManager.prototype.setListType = function(type) { |
+ console.log('set list: ' + type); |
+ |
+ if (type && type == this.listType_) { |
+ console.log('no change: ' + type); |
+ return; |
+ } |
+ |
+ if (type == FileManager.ListType.DETAIL) { |
+ this.table_.style.display = ''; |
+ this.grid_.style.display = 'none'; |
+ this.currentList_ = this.table_; |
+ this.dialogDom_.querySelector('button.detail-view').disabled = true; |
+ this.dialogDom_.querySelector('button.thumbnail-view').disabled = false; |
+ } else if (type == FileManager.ListType.THUMBNAIL) { |
+ this.grid_.style.display = ''; |
+ this.table_.style.display = 'none'; |
+ this.currentList_ = this.grid_; |
+ this.dialogDom_.querySelector('button.thumbnail-view').disabled = true; |
+ this.dialogDom_.querySelector('button.detail-view').disabled = false; |
+ } else { |
+ throw new Error('Unknown list type: ' + type); |
+ } |
+ |
+ this.listType_ = type; |
+ this.onResize_(); |
+ this.currentList_.redraw(); |
+ |
+ console.log('type now: ' + this.listType_); |
+ }; |
+ |
+ /** |
+ * Initialize the file thumbnail grid. |
+ */ |
+ FileManager.prototype.initGrid_ = function() { |
+ this.grid_ = this.dialogDom_.querySelector('.thumbnail-grid'); |
+ cr.ui.Grid.decorate(this.grid_); |
+ this.grid_.dataModel = this.dataModel_; |
+ |
+ var self = this; |
+ this.grid_.itemConstructor = function(entry) { |
+ return self.renderThumbnail_(entry); |
+ }; |
+ |
+ if (this.dialogType_ != FileManager.DialogType.SELECT_OPEN_MULTI_FILE) { |
+ this.grid_.selectionModel = new cr.ui.ListSingleSelectionModel(); |
+ } |
+ |
+ this.grid_.addEventListener( |
+ 'dblclick', this.onDetailDoubleClick_.bind(this)); |
+ this.grid_.selectionModel.addEventListener( |
+ 'change', this.onDetailSelectionChanged_.bind(this)); |
+ }; |
+ |
+ /** |
+ * Initialize the file list table. |
+ */ |
+ FileManager.prototype.initTable_ = function() { |
var columns = [ |
new cr.ui.table.TableColumn('cachedIconType_', '', 5.4), |
new cr.ui.table.TableColumn('name', str('NAME_COLUMN_LABEL'), 64), |
@@ -425,32 +512,42 @@ FileManager.prototype = { |
columns[2].renderFunction = this.renderSize_.bind(this); |
columns[3].renderFunction = this.renderDate_.bind(this); |
- this.table = this.dialogDom_.querySelector('.detail-table'); |
- cr.ui.Table.decorate(this.table); |
+ this.table_ = this.dialogDom_.querySelector('.detail-table'); |
+ cr.ui.Table.decorate(this.table_); |
- this.table.dataModel = dataModel; |
- this.table.columnModel = new cr.ui.table.TableColumnModel(columns); |
+ this.table_.dataModel = this.dataModel_; |
+ this.table_.columnModel = new cr.ui.table.TableColumnModel(columns); |
if (this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FILE || |
this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FOLDER || |
this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) { |
- this.table.selectionModel = new cr.ui.table.TableSingleSelectionModel(); |
+ this.table_.selectionModel = new cr.ui.table.TableSingleSelectionModel(); |
} |
- this.table.addEventListener( |
+ this.table_.addEventListener( |
'dblclick', this.onDetailDoubleClick_.bind(this)); |
- this.table.selectionModel.addEventListener( |
+ this.table_.selectionModel.addEventListener( |
'change', this.onDetailSelectionChanged_.bind(this)); |
- |
- this.onResize_(); |
- this.dialogDom_.style.opacity = '1'; |
}; |
FileManager.prototype.onResize_ = function() { |
- // TODO(rginda): Remove this hack when cr.ui.List supports resizing. |
- this.table.list_.style.height = |
- (this.table.clientHeight - this.table.header_.clientHeight) + 'px'; |
- this.table.redraw(); |
+ console.log('onResize'); |
+ |
+ this.table_.style.height = this.grid_.style.height = |
+ this.grid_.parentNode.clientHeight + 'px'; |
+ this.table_.style.width = this.grid_.style.width = |
+ this.grid_.parentNode.clientWidth + 'px'; |
+ |
+ this.table_.list_.style.width = this.table_.parentNode.clientWidth + 'px'; |
+ this.table_.list_.style.height = (this.table_.clientHeight - 1 - |
+ this.table_.header_.clientHeight) + 'px'; |
+ |
+ if (this.listType_ == FileManager.ListType.THUMBNAIL) { |
+ var self = this; |
+ setTimeout(function () { self.grid_.columns = 0 }, 100); |
+ } else { |
+ this.currentList_.redraw(); |
+ } |
}; |
/** |
@@ -566,7 +663,7 @@ FileManager.prototype = { |
} |
} |
- var dataModel = this.table.dataModel; |
+ var dataModel = this.dataModel_; |
var uncachedCount = dataModel.length; |
for (var i = uncachedCount - 1; i >= 0 ; i--) { |
@@ -584,6 +681,24 @@ FileManager.prototype = { |
checkCount(); |
} |
+ FileManager.prototype.renderThumbnail_ = function(entry) { |
+ var li = this.document_.createElement('li'); |
+ li.className = 'thumbnail-item'; |
+ |
+ var img = this.document_.createElement('img'); |
+ this.setIconSrc(entry, img); |
+ li.appendChild(img); |
+ |
+ var div = this.document_.createElement('div'); |
+ div.textContent = entry.name; |
+ li.appendChild(div); |
+ |
+ cr.defineProperty(li, 'lead', cr.PropertyKind.BOOL_ATTR); |
+ cr.defineProperty(li, 'selected', cr.PropertyKind.BOOL_ATTR); |
+ |
+ return li; |
+ } |
+ |
/** |
* Render the type column of the detail table. |
* |
@@ -687,7 +802,7 @@ FileManager.prototype = { |
FileManager.prototype.summarizeSelection_ = function() { |
var selection = this.selection = { |
entries: [], |
- uris: [], |
+ urls: [], |
leadEntry: null, |
totalCount: 0, |
fileCount: 0, |
@@ -699,7 +814,7 @@ FileManager.prototype = { |
this.previewSummary_.textContent = str('COMPUTING_SELECTION'); |
this.taskButtons_.innerHTML = ''; |
- var selectedIndexes = this.table.selectionModel.selectedIndexes; |
+ var selectedIndexes = this.currentList_.selectionModel.selectedIndexes; |
if (!selectedIndexes.length) { |
cr.dispatchSimpleEvent(this, 'selection-summarized'); |
return; |
@@ -710,10 +825,11 @@ FileManager.prototype = { |
var pendingFiles = []; |
for (var i = 0; i < selectedIndexes.length; i++) { |
- var entry = this.table.dataModel.item(selectedIndexes[i]); |
+ var entry = this.dataModel_.item(selectedIndexes[i]); |
selection.entries.push(entry); |
- selection.uris.push(entry.toURI()); |
+ |
+ selection.urls.push(entry.toURL()); |
if (selection.iconType == null) { |
selection.iconType = getIconType(entry); |
@@ -743,9 +859,9 @@ FileManager.prototype = { |
} |
} |
- var leadIndex = this.table.selectionModel.leadIndex; |
+ var leadIndex = this.currentList_.selectionModel.leadIndex; |
if (leadIndex > -1) { |
- selection.leadEntry = this.table.dataModel.item(leadIndex); |
+ selection.leadEntry = this.dataModel_.item(leadIndex); |
} else { |
selection.leadEntry = selection.entries[0]; |
} |
@@ -768,7 +884,7 @@ FileManager.prototype = { |
}; |
if (this.dialogType_ == FileManager.DialogType.FULL_PAGE) { |
- chrome.fileBrowserPrivate.getFileTasks(selection.uris, |
+ chrome.fileBrowserPrivate.getFileTasks(selection.urls, |
this.onTasksFound_.bind(this)); |
} |
@@ -796,7 +912,7 @@ FileManager.prototype = { |
FileManager.prototype.onTaskButtonClicked_ = function(event) { |
chrome.fileBrowserPrivate.executeTask(event.srcElement.task.taskId, |
- this.selection.uris); |
+ this.selection.urls); |
} |
/** |
@@ -867,30 +983,29 @@ FileManager.prototype = { |
this.previewFilename_.textContent = previewName; |
- var entry = this.selection.leadEntry; |
+ var iconType = getIconType(this.selection.leadEntry); |
+ if (iconType == 'image') { |
+ this.previewImage_.classList.add('transparent-background'); |
+ if (fileManager.selection.totalCount > 1) |
+ this.previewImage_.classList.add('multiple-selected'); |
+ } |
+ |
+ this.setIconSrc(this.selection.leadEntry, this.previewImage_); |
+ |
+ }; |
+ |
+ FileManager.prototype.setIconSrc = function(entry, img, callback) { |
var iconType = getIconType(entry); |
if (iconType != 'image') { |
// Not an image, display a canned clip-art graphic. |
- this.previewImage_.src = previewArt[iconType]; |
+ img.src = previewArt[iconType]; |
} else { |
// File is an image, fetch the thumbnail. |
- var fileManager = this; |
- |
- batchAsyncCall(entry, 'file', function(file) { |
- var reader = new FileReader(); |
- |
- reader.onerror = util.ferr('Error reading preview: ' + entry.fullPath); |
- reader.onloadend = function(e) { |
- fileManager.previewImage_.src = this.result; |
- fileManager.previewImage_.classList.add('transparent-background'); |
- if (fileManager.selection.totalCount > 1) |
- fileManager.previewImage_.classList.add('multiple-selected'); |
- }; |
- |
- reader.readAsDataURL(file); |
- }); |
+ img.src = entry.toURL(); |
} |
+ if (callback) |
+ callback(); |
}; |
/** |
@@ -939,8 +1054,8 @@ FileManager.prototype = { |
* We use this hook to make sure selected files stay visible after a sort. |
*/ |
FileManager.prototype.onDataModelSorted_ = function() { |
- var i = this.table.selectionModel.leadIndex; |
- this.table.scrollIntoView(i); |
+ var i = this.currentList_.selectionModel.leadIndex; |
+ this.currentList_.scrollIntoView(i); |
} |
/** |
@@ -1012,8 +1127,8 @@ FileManager.prototype = { |
* @param {Event} event The click event. |
*/ |
FileManager.prototype.onDetailDoubleClick_ = function(event) { |
- var i = this.table.selectionModel.leadIndex; |
- var entry = this.table.dataModel.item(i); |
+ var i = this.currentList_.selectionModel.leadIndex; |
+ var entry = this.dataModel_.item(i); |
if (entry.isDirectory) |
return this.changeDirectory(entry.fullPath); |
@@ -1053,8 +1168,8 @@ FileManager.prototype = { |
function onReadSome(entries) { |
if (entries.length == 0) { |
- if (self.table.dataModel.sortStatus.field != 'name') |
- self.table.dataModel.updateIndex(0); |
+ if (self.dataModel_.sortStatus.field != 'name') |
+ self.dataModel_.updateIndex(0); |
if (opt_callback) |
opt_callback(); |
@@ -1073,14 +1188,14 @@ FileManager.prototype = { |
}); |
spliceArgs.unshift(0, 0); // index, deleteCount |
- self.table.dataModel.splice.apply(self.table.dataModel, spliceArgs); |
+ self.dataModel_.splice.apply(self.dataModel_, spliceArgs); |
// Keep reading until entries.length is 0. |
reader.readEntries(onReadSome); |
}; |
// Clear the table first. |
- this.table.dataModel.splice(0, this.table.dataModel.length); |
+ this.dataModel_.splice(0, this.dataModel_.length); |
this.updateBreadcrumbs_(); |
@@ -1096,8 +1211,8 @@ FileManager.prototype = { |
// harness) can't be enumerated yet. |
var spliceArgs = [].slice.call(this.rootEntries_); |
spliceArgs.unshift(0, 0); // index, deleteCount |
- self.table.dataModel.splice.apply(self.table.dataModel, spliceArgs); |
- self.table.dataModel.updateIndex(0); |
+ self.dataModel_.splice.apply(self.dataModel_, spliceArgs); |
+ self.dataModel_.updateIndex(0); |
if (opt_callback) |
opt_callback(); |
@@ -1145,11 +1260,11 @@ FileManager.prototype = { |
function onSuccess(dirEntry) { |
self.rescanDirectory_(function () { |
- for (var i = 0; i < self.table.dataModel.length; i++) { |
- if (self.table.dataModel.item(i).name == dirEntry.name) { |
- self.table.selectionModel.selectedIndex = i; |
- self.table.scrollIndexIntoView(i); |
- self.table.focus(); |
+ for (var i = 0; i < self.dataModel_.length; i++) { |
+ if (self.dataModel_.item(i).name == dirEntry.name) { |
+ self.currentList_.selectionModel.selectedIndex = i; |
+ self.currentList_.scrollIndexIntoView(i); |
+ self.currentList_.focus(); |
return; |
} |
}; |
@@ -1236,7 +1351,7 @@ FileManager.prototype = { |
} |
var ary = []; |
- var selectedIndexes = this.table.selectionModel.selectedIndexes; |
+ var selectedIndexes = this.currentList_.selectionModel.selectedIndexes; |
// All other dialog types require at least one selected list item. |
// The logic to control whether or not the ok button is enabled should |
@@ -1245,7 +1360,7 @@ FileManager.prototype = { |
throw new Error('Nothing selected!'); |
for (var i = 0; i < selectedIndexes.length; i++) { |
- var entry = this.table.dataModel.item(selectedIndexes[i]); |
+ var entry = this.dataModel_.item(selectedIndexes[i]); |
if (!entry) { |
console.log('Error locating selected file at index: ' + i); |
continue; |