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

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

Issue 10342010: Add gdata content search to file_manager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: feedback Created 8 years, 7 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
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 /** 5 /**
6 * FileManager constructor. 6 * FileManager constructor.
7 * 7 *
8 * FileManager objects encapsulate the functionality of the file selector 8 * FileManager objects encapsulate the functionality of the file selector
9 * dialogs, as well as the full screen file manager application (though the 9 * dialogs, as well as the full screen file manager application (though the
10 * latter is not yet implemented). 10 * latter is not yet implemented).
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 FileManager.DialogType.SELECT_OPEN_MULTI_FILE, 46 FileManager.DialogType.SELECT_OPEN_MULTI_FILE,
47 FileManager.DialogType.FULL_PAGE]); 47 FileManager.DialogType.FULL_PAGE]);
48 48
49 // TODO(dgozman): This will be changed to LocaleInfo. 49 // TODO(dgozman): This will be changed to LocaleInfo.
50 this.locale_ = new v8Locale(navigator.language); 50 this.locale_ = new v8Locale(navigator.language);
51 51
52 this.initFileSystem_(); 52 this.initFileSystem_();
53 this.initDom_(); 53 this.initDom_();
54 this.initDialogType_(); 54 this.initDialogType_();
55 this.dialogDom_.style.opacity = '1'; 55 this.dialogDom_.style.opacity = '1';
56
57 this.lastNonGDataSearchPath_ = null;
56 } 58 }
57 59
58 FileManager.prototype = { 60 FileManager.prototype = {
59 __proto__: cr.EventTarget.prototype 61 __proto__: cr.EventTarget.prototype
60 }; 62 };
61 63
62 // Anonymous "namespace". 64 // Anonymous "namespace".
63 (function() { 65 (function() {
64 66
65 // Private variables and helper functions. 67 // Private variables and helper functions.
(...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 this.commands_[key].disabled = !this.canExecute_(key); 973 this.commands_[key].disabled = !this.canExecute_(key);
972 }; 974 };
973 975
974 /** 976 /**
975 * @param {string} commandId Command identifier. 977 * @param {string} commandId Command identifier.
976 * @return {boolean} True if the command can be executed for current 978 * @return {boolean} True if the command can be executed for current
977 * selection. 979 * selection.
978 */ 980 */
979 FileManager.prototype.canExecute_ = function(commandId) { 981 FileManager.prototype.canExecute_ = function(commandId) {
980 var readonly = this.isOnReadonlyDirectory(); 982 var readonly = this.isOnReadonlyDirectory();
983 var shouldCreate = !util.isSpecialReadonlyDirectory(
984 this.directoryModel_.getCurrentDirEntry().fullPath);
981 switch (commandId) { 985 switch (commandId) {
982 case 'copy': 986 case 'copy':
983 case 'cut': 987 case 'cut':
984 return this.document_.queryCommandEnabled(commandId); 988 return this.document_.queryCommandEnabled(commandId);
985 989
986 case 'paste': 990 case 'paste':
987 return !!this.fileTransferController_ && 991 return !!this.fileTransferController_ &&
988 this.fileTransferController_.queryPasteCommandEnabled(); 992 this.fileTransferController_.queryPasteCommandEnabled() &&
SeRya 2012/05/04 10:26:17 What about dropping files into the search results?
tbarzic 2012/05/05 00:56:06 Done.
993 shouldCreate;
989 994
990 case 'rename': 995 case 'rename':
991 return (// Initialized to the point where we have a current directory 996 return (// Initialized to the point where we have a current directory
992 !readonly && 997 !readonly &&
993 // Rename not in progress. 998 // Rename not in progress.
994 !this.isRenamingInProgress() && 999 !this.isRenamingInProgress() &&
995 // Only one file selected. 1000 // Only one file selected.
996 this.selection && 1001 this.selection &&
997 this.selection.totalCount == 1); 1002 this.selection.totalCount == 1);
998 1003
999 case 'delete': 1004 case 'delete':
1000 return (// Initialized to the point where we have a current directory 1005 return (// Initialized to the point where we have a current directory
1001 !readonly && 1006 !readonly &&
1002 // Rename not in progress. 1007 // Rename not in progress.
1003 !this.isRenamingInProgress() && 1008 !this.isRenamingInProgress() &&
1004 this.selection && 1009 this.selection &&
1005 this.selection.totalCount > 0); 1010 this.selection.totalCount > 0);
1006 1011
1007 case 'newfolder': 1012 case 'newfolder':
1008 return !readonly && 1013 return !readonly &&
1014 shouldCreate &&
1009 (this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE || 1015 (this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE ||
1010 this.dialogType_ == FileManager.DialogType.FULL_PAGE); 1016 this.dialogType_ == FileManager.DialogType.FULL_PAGE);
1011 1017
1012 case 'unmount': 1018 case 'unmount':
1013 return true; 1019 return true;
1014 1020
1015 case 'format': 1021 case 'format':
1016 var entry = this.directoryModel_.getCurrentRootDirEntry(); 1022 var entry = this.directoryModel_.getCurrentRootDirEntry();
1017 1023
1018 return entry && DirectoryModel.getRootType(entry.fullPath) == 1024 return entry && DirectoryModel.getRootType(entry.fullPath) ==
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after
1823 * Render filename label for grid and list view. 1829 * Render filename label for grid and list view.
1824 * @param {Entry} entry The Entry object to render. 1830 * @param {Entry} entry The Entry object to render.
1825 * @return {HTMLDivElement} The label. 1831 * @return {HTMLDivElement} The label.
1826 */ 1832 */
1827 FileManager.prototype.renderFileNameLabel_ = function(entry) { 1833 FileManager.prototype.renderFileNameLabel_ = function(entry) {
1828 // Filename need to be in a '.filename-label' container for correct 1834 // Filename need to be in a '.filename-label' container for correct
1829 // work of inplace renaming. 1835 // work of inplace renaming.
1830 var fileName = this.document_.createElement('div'); 1836 var fileName = this.document_.createElement('div');
1831 fileName.className = 'filename-label'; 1837 fileName.className = 'filename-label';
1832 1838
1839 // If the entry is gdata search result, we should calculate name to use
1840 // instead of using |entry.name|.
1841 var gdataSearchResult =
1842 util.getFileAndDisplayNameForGDataSearchResult(entry.fullPath);
1843 var displayName = gdataSearchResult ? gdataSearchResult.displayName :
1844 entry.name;
1845
1833 fileName.textContent = 1846 fileName.textContent =
1834 this.directoryModel_.getCurrentDirEntry().name == '' ? 1847 this.directoryModel_.getCurrentDirEntry().name == '' ?
1835 this.getRootLabel_(entry.name) : entry.name; 1848 this.getRootLabel_(displayName) : displayName;
1836 return fileName; 1849 return fileName;
1837 }; 1850 };
1838 1851
1839 /** 1852 /**
1840 * Render the Size column of the detail table. 1853 * Render the Size column of the detail table.
1841 * 1854 *
1842 * @param {Entry} entry The Entry object to render. 1855 * @param {Entry} entry The Entry object to render.
1843 * @param {string} columnId The id of the column to be rendered. 1856 * @param {string} columnId The id of the column to be rendered.
1844 * @param {cr.ui.Table} table The table doing the rendering. 1857 * @param {cr.ui.Table} table The table doing the rendering.
1845 */ 1858 */
(...skipping 1017 matching lines...) Expand 10 before | Expand all | Expand 10 after
2863 div.textContent = i == 0 ? this.getRootLabel_(path) : pathName; 2876 div.textContent = i == 0 ? this.getRootLabel_(path) : pathName;
2864 2877
2865 path = path + '/'; 2878 path = path + '/';
2866 div.path = path; 2879 div.path = path;
2867 2880
2868 bc.appendChild(div); 2881 bc.appendChild(div);
2869 2882
2870 if (i == pathNames.length - 1) { 2883 if (i == pathNames.length - 1) {
2871 div.classList.add('breadcrumb-last'); 2884 div.classList.add('breadcrumb-last');
2872 } else { 2885 } else {
2873 div.addEventListener('click', this.onBreadcrumbClick_.bind(this)); 2886 // This is virtual, inaccessible directory.
2887 if (path == util.GDATA_SEARCH_ROOT_PATH) {
2888 div.classList.add('breadcrumb-last');
SeRya 2012/05/04 10:26:17 breadcrumb-last in the middle of the path looks st
tbarzic 2012/05/05 00:56:06 Done
2889 } else {
2890 div.addEventListener('click', this.onBreadcrumbClick_.bind(this));
2891 }
2874 2892
2875 var spacer = doc.createElement('div'); 2893 var spacer = doc.createElement('div');
2876 spacer.className = 'separator'; 2894 spacer.className = 'separator';
2877 bc.appendChild(spacer); 2895 bc.appendChild(spacer);
2878 } 2896 }
2879 } 2897 }
2880 this.truncateBreadcrumbs_(); 2898 this.truncateBreadcrumbs_();
2881 }; 2899 };
2882 2900
2883 FileManager.prototype.isRenamingInProgress = function() { 2901 FileManager.prototype.isRenamingInProgress = function() {
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after
3533 }; 3551 };
3534 3552
3535 FileManager.prototype.onRenameInputBlur_ = function(event) { 3553 FileManager.prototype.onRenameInputBlur_ = function(event) {
3536 if (this.isRenamingInProgress() && !this.renameInput_.validation_) 3554 if (this.isRenamingInProgress() && !this.renameInput_.validation_)
3537 this.commitRename_(); 3555 this.commitRename_();
3538 }; 3556 };
3539 3557
3540 FileManager.prototype.commitRename_ = function() { 3558 FileManager.prototype.commitRename_ = function() {
3541 var input = this.renameInput_; 3559 var input = this.renameInput_;
3542 var entry = input.currentEntry; 3560 var entry = input.currentEntry;
3543 var newName = input.value; 3561 var newNameInput = input.value;
3562
3563 // If we are renaming gdata search result, we'll have to format newName we
3564 // use in file system operations like: <resource_id>.<file_name>.
3565 var searchResultName =
3566 util.getFileAndDisplayNameForGDataSearchResult(entry.fullPath);
3567
3568 var newName =
3569 searchResultName ? searchResultName.resourceId + '.' + newNameInput :
3570 newNameInput;
3571 var oldName = searchResultName ? searchResultName.displayName : entry.name;
3544 3572
3545 if (newName == entry.name) { 3573 if (newName == entry.name) {
3546 this.cancelRename_(); 3574 this.cancelRename_();
3547 return; 3575 return;
3548 } 3576 }
3549 3577
3550 var nameNode = this.findListItemForNode_(this.renameInput_). 3578 var nameNode = this.findListItemForNode_(this.renameInput_).
3551 querySelector('.filename-label'); 3579 querySelector('.filename-label');
3552 3580
3553 input.validation_ = true; 3581 input.validation_ = true;
3554 function validationDone() { 3582 function validationDone() {
3555 input.validation_ = false; 3583 input.validation_ = false;
3556 // Alert dialog restores focus unless the item removed from DOM. 3584 // Alert dialog restores focus unless the item removed from DOM.
3557 if (this.document_.activeElement != input) 3585 if (this.document_.activeElement != input)
3558 this.cancelRename_(); 3586 this.cancelRename_();
3559 } 3587 }
3560 3588
3561 if (!this.validateFileName_(newName, validationDone.bind(this))) 3589 if (!this.validateFileName_(newNameInput, validationDone.bind(this)))
3562 return; 3590 return;
3563 3591
3564 function onError(err) { 3592 function onError(err) {
3565 nameNode.textContent = entry.name; 3593 nameNode.textContent = entry.name;
3566 this.alert.show(strf('ERROR_RENAMING', entry.name, 3594 this.alert.show(strf('ERROR_RENAMING', entry.name,
3567 util.getFileErrorMnemonic(err.code))); 3595 util.getFileErrorMnemonic(err.code)));
3568 } 3596 }
3569 3597
3570 this.cancelRename_(); 3598 this.cancelRename_();
3571 // Optimistically apply new name immediately to avoid flickering in 3599 // Optimistically apply new name immediately to avoid flickering in
3572 // case of success. 3600 // case of success.
3573 nameNode.textContent = newName; 3601 nameNode.textContent = newNameInput;
3574 3602
3575 this.directoryModel_.doesExist(newName, function(exists, isFile) { 3603 this.directoryModel_.doesExist(newName, function(exists, isFile) {
SeRya 2012/05/04 10:26:17 I'd suggest to isolate the UI from knowlage about
tbarzic 2012/05/05 00:56:06 Really good point, that's much cleaner :)
3576 if (!exists) { 3604 if (!exists) {
3577 this.directoryModel_.renameEntry(entry, newName, onError.bind(this)); 3605 this.directoryModel_.renameEntry(entry, newName, onError.bind(this));
3578 } else { 3606 } else {
3579 nameNode.textContent = entry.name; 3607 nameNode.textContent = oldName;
3580 var message = isFile ? 'FILE_ALREADY_EXISTS' : 3608 var message = isFile ? 'FILE_ALREADY_EXISTS' :
3581 'DIRECTORY_ALREADY_EXISTS'; 3609 'DIRECTORY_ALREADY_EXISTS';
3582 this.alert.show(strf(message, newName)); 3610 this.alert.show(strf(message, newNameInput));
3583 } 3611 }
3584 }.bind(this)); 3612 }.bind(this));
3585 }; 3613 };
3586 3614
3587 FileManager.prototype.cancelRename_ = function() { 3615 FileManager.prototype.cancelRename_ = function() {
3588 this.renameInput_.currentEntry = null; 3616 this.renameInput_.currentEntry = null;
3589 3617
3590 var parent = this.renameInput_.parentNode; 3618 var parent = this.renameInput_.parentNode;
3591 if (parent) { 3619 if (parent) {
3592 parent.removeAttribute('renaming'); 3620 parent.removeAttribute('renaming');
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after
4256 if (oldValue) { 4284 if (oldValue) {
4257 event.target.removeAttribute('checked'); 4285 event.target.removeAttribute('checked');
4258 } else { 4286 } else {
4259 event.target.setAttribute('checked', 'checked'); 4287 event.target.setAttribute('checked', 'checked');
4260 } 4288 }
4261 }; 4289 };
4262 4290
4263 FileManager.prototype.onSearchBoxUpdate_ = function(event) { 4291 FileManager.prototype.onSearchBoxUpdate_ = function(event) {
4264 var searchString = this.dialogDom_.querySelector('#search-box').value; 4292 var searchString = this.dialogDom_.querySelector('#search-box').value;
4265 if (searchString) { 4293 if (searchString) {
4266 this.directoryModel_.addFilter( 4294 if (!this.isOnGData()) {
SeRya 2012/05/04 10:26:17 I think this is too low level logic. It should be
tbarzic 2012/05/05 00:56:06 Done.
4267 'searchbox', 4295 this.directoryModel_.addFilter(
4268 function(e) { 4296 'searchbox',
4269 return e.name.substr(0, searchString.length) == searchString; 4297 function(e) {
4270 }); 4298 return e.name.substr(0, searchString.length) == searchString;
4299 });
4300 } else {
4301 // If current path is not under gdata search dir, remeber it, so we can
4302 // navigate to it when we exit search mode.
4303 var currentDirPath = this.directoryModel_.getCurrentDirEntry().fullPath;
4304 if (currentDirPath.search(util.GDATA_SEARCH_ROOT_PATH) != 0)
4305 this.lastNonGDataSearchPath_ = currentDirPath;
4306
4307 this.directoryModel_.changeDirectory(
SeRya 2012/05/04 10:26:17 changeDirectory causes putting the new directory i
tbarzic 2012/05/05 00:56:06 Done.
4308 util.createGDataSearchPath(searchString));
4309 }
4271 } else { 4310 } else {
4272 this.directoryModel_.removeFilter('searchbox'); 4311 if (!this.isOnGData()) {
4312 this.directoryModel_.removeFilter('searchbox');
4313 } else {
4314 // Go to last known non gdata search directory.
4315 var newDirectory = this.lastNonGDataSearchPath_ ||
4316 '/' + DirectoryModel.GDATA_DIRECTORY;
SeRya 2012/05/04 10:26:17 You set GData root even if search started in a sub
tbarzic 2012/05/05 00:56:06 are you sure? What am I missing?
4317 this.lastNonGDataSearchPath_ = null;
4318 this.directoryModel_.changeDirectory(newDirectory);
4319 }
4273 } 4320 }
4274 }; 4321 };
4275 4322
4276 FileManager.prototype.decorateSplitter = function(splitterElement) { 4323 FileManager.prototype.decorateSplitter = function(splitterElement) {
4277 var self = this; 4324 var self = this;
4278 4325
4279 var Splitter = cr.ui.Splitter; 4326 var Splitter = cr.ui.Splitter;
4280 4327
4281 var customSplitter = cr.ui.define('div'); 4328 var customSplitter = cr.ui.define('div');
4282 4329
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
4397 4444
4398 this.directoryModel_.addEventListener('scan-completed', maybeShowBanner); 4445 this.directoryModel_.addEventListener('scan-completed', maybeShowBanner);
4399 this.directoryModel_.addEventListener('rescan-completed', maybeShowBanner); 4446 this.directoryModel_.addEventListener('rescan-completed', maybeShowBanner);
4400 4447
4401 var style = this.document_.createElement('link'); 4448 var style = this.document_.createElement('link');
4402 style.rel = 'stylesheet'; 4449 style.rel = 'stylesheet';
4403 style.href = 'css/gdrive_welcome.css'; 4450 style.href = 'css/gdrive_welcome.css';
4404 this.document_.head.appendChild(style); 4451 this.document_.head.appendChild(style);
4405 }; 4452 };
4406 })(); 4453 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698