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

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

Issue 7584004: Keeping the current directory in URL. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Small fixes. Created 9 years, 4 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // Setting the src of an img to an empty string can crash the browser, so we 5 // Setting the src of an img to an empty string can crash the browser, so we
6 // use an empty 1x1 gif instead. 6 // use an empty 1x1 gif instead.
7 const EMPTY_IMAGE_URI = 'data:image/gif;base64,' 7 const EMPTY_IMAGE_URI = 'data:image/gif;base64,'
8 + 'R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D'; 8 + 'R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D';
9 9
10 var g_slideshow_data = null; 10 var g_slideshow_data = null;
(...skipping 13 matching lines...) Expand all
24 * the root filesystem for the new FileManager. 24 * the root filesystem for the new FileManager.
25 * @param {Object} params A map of parameter names to values controlling the 25 * @param {Object} params A map of parameter names to values controlling the
26 * appearance of the FileManager. Names are: 26 * appearance of the FileManager. Names are:
27 * - type: A value from FileManager.DialogType defining what kind of 27 * - type: A value from FileManager.DialogType defining what kind of
28 * dialog to present. Defaults to FULL_PAGE. 28 * dialog to present. Defaults to FULL_PAGE.
29 * - title: The title for the dialog. Defaults to a localized string based 29 * - title: The title for the dialog. Defaults to a localized string based
30 * on the dialog type. 30 * on the dialog type.
31 * - defaultPath: The default path for the dialog. The default path should 31 * - defaultPath: The default path for the dialog. The default path should
32 * end with a trailing slash if it represents a directory. 32 * end with a trailing slash if it represents a directory.
33 */ 33 */
34 function FileManager(dialogDom, filesystem, rootEntries, params) { 34 function FileManager(dialogDom, filesystem, rootEntries) {
35 console.log('Init FileManager: ' + dialogDom); 35 console.log('Init FileManager: ' + dialogDom);
36 36
37 this.dialogDom_ = dialogDom; 37 this.dialogDom_ = dialogDom;
38 this.rootEntries_ = rootEntries; 38 this.rootEntries_ = rootEntries;
39 this.filesystem_ = filesystem; 39 this.filesystem_ = filesystem;
40 this.params_ = params || {}; 40 this.params_ = location.search ?
41 JSON.parse(decodeURIComponent(location.search.substr(1))) :
42 {};
41 43
42 this.listType_ = null; 44 this.listType_ = null;
43 45
44 this.metadataCache_ = {}; 46 this.metadataCache_ = {};
45 47
46 this.selection = null; 48 this.selection = null;
47 49
48 this.clipboard_ = null; // Current clipboard, or null if empty. 50 this.clipboard_ = null; // Current clipboard, or null if empty.
49 51
50 this.butterTimer_ = null; 52 this.butterTimer_ = null;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) { 127 chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) {
126 self.mountPoints_ = mountPoints; 128 self.mountPoints_ = mountPoints;
127 }); 129 });
128 130
129 chrome.fileBrowserHandler.onExecute.addListener( 131 chrome.fileBrowserHandler.onExecute.addListener(
130 this.onFileTaskExecute_.bind(this)); 132 this.onFileTaskExecute_.bind(this));
131 133
132 this.initCommands_(); 134 this.initCommands_();
133 this.initDom_(); 135 this.initDom_();
134 this.initDialogType_(); 136 this.initDialogType_();
135 this.initDefaultDirectory_(this.params_.defaultPath); 137 this.setupCurrentDirectory_();
136 138
137 this.summarizeSelection_(); 139 this.summarizeSelection_();
138 this.updatePreview_(); 140 this.updatePreview_();
139 141
140 chrome.fileBrowserPrivate.onDiskChanged.addListener( 142 chrome.fileBrowserPrivate.onDiskChanged.addListener(
141 this.onDiskChanged_.bind(this)); 143 this.onDiskChanged_.bind(this));
142 144
143 this.refocus(); 145 this.refocus();
144 146
145 // Pass all URLs to the metadata reader until we have a correct filter. 147 // Pass all URLs to the metadata reader until we have a correct filter.
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 this.pasteButton_.disabled = !event.canExecute; 791 this.pasteButton_.disabled = !event.canExecute;
790 break; 792 break;
791 793
792 case 'rename': 794 case 'rename':
793 event.canExecute = 795 event.canExecute =
794 (// Initialized to the point where we have a current directory 796 (// Initialized to the point where we have a current directory
795 this.currentDirEntry_ && 797 this.currentDirEntry_ &&
796 // Rename not in progress. 798 // Rename not in progress.
797 !this.renameInput_.currentEntry && 799 !this.renameInput_.currentEntry &&
798 // Only one file selected. 800 // Only one file selected.
801 this.selection &&
799 this.selection.totalCount == 1 && 802 this.selection.totalCount == 1 &&
800 !isSystemDirEntry(this.currentDirEntry_)); 803 !isSystemDirEntry(this.currentDirEntry_));
801 break; 804 break;
802 805
803 case 'delete': 806 case 'delete':
804 event.canExecute = 807 event.canExecute =
805 (// Initialized to the point where we have a current directory 808 (// Initialized to the point where we have a current directory
806 this.currentDirEntry_ && 809 this.currentDirEntry_ &&
807 // Rename not in progress. 810 // Rename not in progress.
808 !this.renameInput_.currentEntry && 811 !this.renameInput_.currentEntry &&
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 this.initiateRename_(label); 994 this.initiateRename_(label);
992 return; 995 return;
993 996
994 case 'delete': 997 case 'delete':
995 this.deleteEntries(this.selection.entries); 998 this.deleteEntries(this.selection.entries);
996 return; 999 return;
997 } 1000 }
998 }; 1001 };
999 1002
1000 /** 1003 /**
1001 * Respond to the back button. 1004 * Respond to the back and forward buttons.
1002 */ 1005 */
1003 FileManager.prototype.onPopState_ = function(event) { 1006 FileManager.prototype.onPopState_ = function(event) {
1004 this.changeDirectory(event.state, CD_NO_HISTORY); 1007 // TODO(serya): We should restore selected items here.
1008 this.setupCurrentDirectory_();
1005 }; 1009 };
1006 1010
1007 /** 1011 /**
1008 * Resize details and thumb views to fit the new window size. 1012 * Resize details and thumb views to fit the new window size.
1009 */ 1013 */
1010 FileManager.prototype.onResize_ = function() { 1014 FileManager.prototype.onResize_ = function() {
1011 this.table_.style.height = this.grid_.style.height = 1015 this.table_.style.height = this.grid_.style.height =
1012 this.grid_.parentNode.clientHeight + 'px'; 1016 this.grid_.parentNode.clientHeight + 'px';
1013 this.table_.style.width = this.grid_.style.width = 1017 this.table_.style.width = this.grid_.style.width =
1014 this.grid_.parentNode.clientWidth + 'px'; 1018 this.grid_.parentNode.clientWidth + 'px';
(...skipping 12 matching lines...) Expand all
1027 this.currentList_.redraw(); 1031 this.currentList_.redraw();
1028 } 1032 }
1029 }; 1033 };
1030 1034
1031 FileManager.prototype.resolvePath = function( 1035 FileManager.prototype.resolvePath = function(
1032 path, resultCallback, errorCallback) { 1036 path, resultCallback, errorCallback) {
1033 return util.resolvePath(this.filesystem_.root, path, resultCallback, 1037 return util.resolvePath(this.filesystem_.root, path, resultCallback,
1034 errorCallback); 1038 errorCallback);
1035 }; 1039 };
1036 1040
1037 FileManager.prototype.initDefaultDirectory_ = function(path) { 1041 /**
1038 if (!path) { 1042 * Restores current directory and may be a selected item after page load (or
1039 // No preset given, find a good place to start. 1043 * reload) or popping a state (after ckick on back/forward). If location.hash
Vladislav Kaznacheev 2011/08/05 13:01:36 typo: ckick -> click presents -> is present
SeRya 2011/08/05 13:45:42 Done.
1040 // Check for removable devices, if there are none, go to Downloads. 1044 * presents it means that the user has navigated somewhere and that place will
1041 for (var i = 0; i != this.rootEntries_.length; i++) { 1045 * be restored. defaultPath primarily is used with save/open dialogs. Default
1042 var rootEntry = this.rootEntries_[i]; 1046 * path may also contain a file name. Freshly opened file manager window
1043 if (rootEntry.fullPath == REMOVABLE_DIRECTORY) { 1047 * has neither.
1044 var foundRemovable = false; 1048 */
1045 var self = this; 1049 FileManager.prototype.setupCurrentDirectory_ = function() {
1046 util.forEachDirEntry(rootEntry, function(result) { 1050 if (location.hash) {
1047 if (result) { 1051 // Location hash has the highest priority.
1048 foundRemovable = true; 1052 var path = decodeURI(location.hash.substr(1));
1049 } else { // Done enumerating, and we know the answer. 1053 this.changeDirectory(path, CD_NO_HISTORY);
1050 self.initDefaultDirectory_( 1054 return;
1051 foundRemovable ? '/' : DOWNLOADS_DIRECTORY); 1055 } else if (this.params_.defaultPath) {
1052 } 1056 this.setupPath_(this.params_.defaultPath);
1053 }); 1057 } else {
1054 return; 1058 this.setupDefaultPath_();
1055 } 1059 }
1056 } 1060 };
1057 1061
1058 // Removable root directory is missing altogether. 1062 FileManager.prototype.setupDefaultPath_ = function() {
1059 path = DOWNLOADS_DIRECTORY; 1063 // No preset given, find a good place to start.
1064 // Check for removable devices, if there are none, go to Downloads.
1065 var removableDirectoryEntry = this.rootEntries_.filter(function(rootEntry) {
1066 return rootEntry.fullPath == REMOVABLE_DIRECTORY;
1067 })[0];
1068 if (!removableDirectoryEntry) {
1069 this.changeDirectory(DOWNLOADS_DIRECTORY, CD_NO_HISTORY);
1070 return;
1060 } 1071 }
1061 1072
1073 var foundRemovable = false;
1074 util.forEachDirEntry(removableDirectoryEntry, function(result) {
1075 if (result) {
1076 foundRemovable = true;
1077 } else { // Done enumerating, and we know the answer.
1078 this.changeDirectory(foundRemovable ? '/' : DOWNLOADS_DIRECTORY,
1079 CD_NO_HISTORY);
1080 }
1081 }.bind(this));
1082 };
1083
1084 FileManager.prototype.setupPath_ = function(path) {
1062 // Split the dirname from the basename. 1085 // Split the dirname from the basename.
1063 var ary = path.match(/^(.*?)(?:\/([^\/]+))?$/); 1086 var ary = path.match(/^(.*?)(?:\/([^\/]+))?$/);
1064 if (!ary) { 1087 if (!ary) {
1065 console.warn('Unable to split default path: ' + path); 1088 console.warn('Unable to split default path: ' + path);
1066 self.changeDirectory('/', CD_NO_HISTORY); 1089 self.changeDirectory('/', CD_NO_HISTORY);
1067 return; 1090 return;
1068 } 1091 }
1069 1092
1070 var baseName = ary[1]; 1093 var baseName = ary[1];
1071 var leafName = ary[2]; 1094 var leafName = ary[2];
(...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after
1979 * 2002 *
1980 * @param {string} path The absolute path to the new directory. 2003 * @param {string} path The absolute path to the new directory.
1981 * @param {bool} opt_saveHistory Save this in the history stack (defaults 2004 * @param {bool} opt_saveHistory Save this in the history stack (defaults
1982 * to true). 2005 * to true).
1983 * @param {string} opt_selectedEntry The name of the file to select after 2006 * @param {string} opt_selectedEntry The name of the file to select after
1984 * changing directories. 2007 * changing directories.
1985 */ 2008 */
1986 FileManager.prototype.changeDirectoryEntry = function(dirEntry, 2009 FileManager.prototype.changeDirectoryEntry = function(dirEntry,
1987 opt_saveHistory, 2010 opt_saveHistory,
1988 opt_selectedEntry) { 2011 opt_selectedEntry) {
2012 if (typeof opt_saveHistory == 'undefined') {
2013 opt_saveHistory = true;
2014 } else {
2015 opt_saveHistory = !!opt_saveHistory;
2016 }
2017
2018 var location = '#' + encodeURI(dirEntry.fullPath);
2019 if (opt_saveHistory) {
2020 console.log('Push state: ' + location);
Vladislav Kaznacheev 2011/08/05 13:01:36 I do not think we need this logging in production
SeRya 2011/08/05 13:45:42 Removed.
2021 history.pushState(undefined, dirEntry.fullPath, location);
2022 } else if (window.location.hash != location) {
2023 // If the user typed URL manually that is not canonical it would be fixed
2024 // here. However it seems history.replaceState doesn't work properly
2025 // with rewritable URLs (while does with history.pushState). It changes
2026 // window.location but doesn't change content of the ombibox.
2027 console.log('Replace state: ' + location);
2028 history.replaceState(undefined, dirEntry.fullPath, location);
2029 }
2030
1989 if (this.currentDirEntry_ && 2031 if (this.currentDirEntry_ &&
1990 this.currentDirEntry_.fullPath == dirEntry.fullPath) { 2032 this.currentDirEntry_.fullPath == dirEntry.fullPath) {
1991 // Directory didn't actually change. 2033 // Directory didn't actually change.
1992 if (opt_selectedEntry) 2034 if (opt_selectedEntry)
1993 this.selectEntry(opt_selectedEntry); 2035 this.selectEntry(opt_selectedEntry);
1994 return; 2036 return;
1995 } 2037 }
1996 2038
1997 if (typeof opt_saveHistory == 'undefined') {
1998 opt_saveHistory = true;
1999 } else {
2000 opt_saveHistory = !!opt_saveHistory;
2001 }
2002
2003 var e = new cr.Event('directory-changed'); 2039 var e = new cr.Event('directory-changed');
2004 e.previousDirEntry = this.currentDirEntry_; 2040 e.previousDirEntry = this.currentDirEntry_;
2005 e.newDirEntry = dirEntry; 2041 e.newDirEntry = dirEntry;
2006 e.saveHistory = opt_saveHistory; 2042 e.saveHistory = opt_saveHistory;
2007 e.selectedEntry = opt_selectedEntry; 2043 e.selectedEntry = opt_selectedEntry;
2008 this.currentDirEntry_ = dirEntry; 2044 this.currentDirEntry_ = dirEntry;
2009 this.dispatchEvent(e); 2045 this.dispatchEvent(e);
2010 } 2046 }
2011 2047
2012 /** 2048 /**
2013 * Change the current directory to the directory represented by a string 2049 * Change the current directory to the directory represented by a string
2014 * path. 2050 * path.
2015 * 2051 *
2016 * Dispatches the 'directory-changed' event when the directory is successfully 2052 * Dispatches the 'directory-changed' event when the directory is successfully
2017 * changed. 2053 * changed.
2018 * 2054 *
2019 * @param {string} path The absolute path to the new directory. 2055 * @param {string} path The absolute path to the new directory.
2020 * @param {bool} opt_saveHistory Save this in the history stack (defaults 2056 * @param {bool} opt_saveHistory Save this in the history stack (defaults
2021 * to true). 2057 * to true).
2022 * @param {string} opt_selectedEntry The name of the file to select after 2058 * @param {string} opt_selectedEntry The name of the file to select after
2023 * changing directories. 2059 * changing directories.
2024 */ 2060 */
2025 FileManager.prototype.changeDirectory = function(path, 2061 FileManager.prototype.changeDirectory = function(path,
2026 opt_saveHistory, 2062 opt_saveHistory,
2027 opt_selectedEntry) { 2063 opt_selectedEntry) {
2028 if (path == '/') 2064 if (path == '/')
2029 return this.changeDirectoryEntry(this.filesystem_.root); 2065 return this.changeDirectoryEntry(this.filesystem_.root,
2066 opt_saveHistory,
2067 opt_selectedEntry);
2030 2068
2031 var self = this; 2069 var self = this;
2032 2070
2033 this.filesystem_.root.getDirectory( 2071 this.filesystem_.root.getDirectory(
2034 path, {create: false}, 2072 path, {create: false},
2035 function(dirEntry) { 2073 function(dirEntry) {
2036 self.changeDirectoryEntry( 2074 self.changeDirectoryEntry(
2037 dirEntry, opt_saveHistory, opt_selectedEntry); 2075 dirEntry, opt_saveHistory, opt_selectedEntry);
2038 }, 2076 },
2039 function(err) { 2077 function(err) {
2040 console.error('Error changing directory to: ' + path + ', ' + err); 2078 console.error('Error changing directory to: ' + path + ', ' + err);
2041 if (!self.currentDirEntry_) { 2079 if (self.currentDirEntry_) {
2080 var location = '#' + encodeURI(self.currentDirEntry_.fullPath);
2081 history.replaceState(undefined,
2082 self.currentDirEntry_.fullPath,
2083 location);
2084 } else {
2042 // If we've never successfully changed to a directory, force them 2085 // If we've never successfully changed to a directory, force them
2043 // to the root. 2086 // to the root.
2044 self.changeDirectory('/', false); 2087 self.changeDirectory('/', false);
2045 } 2088 }
2046 }); 2089 });
2047 }; 2090 };
2048 2091
2049 FileManager.prototype.deleteEntries = function(entries, force) { 2092 FileManager.prototype.deleteEntries = function(entries, force) {
2050 if (!force) { 2093 if (!force) {
2051 var self = this; 2094 var self = this;
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
2323 this.onOk_(); 2366 this.onOk_();
2324 2367
2325 }; 2368 };
2326 2369
2327 /** 2370 /**
2328 * Update the UI when the current directory changes. 2371 * Update the UI when the current directory changes.
2329 * 2372 *
2330 * @param {cr.Event} event The directory-changed event. 2373 * @param {cr.Event} event The directory-changed event.
2331 */ 2374 */
2332 FileManager.prototype.onDirectoryChanged_ = function(event) { 2375 FileManager.prototype.onDirectoryChanged_ = function(event) {
2333 if (event.saveHistory) {
2334 history.pushState(this.currentDirEntry_.fullPath,
2335 this.currentDirEntry_.fullPath,
2336 location.href);
2337 }
2338
2339 this.updateCommands_(); 2376 this.updateCommands_();
2340 this.updateOkButton_(); 2377 this.updateOkButton_();
2341 2378
2342 // New folder should never be enabled in the root or media/ directories. 2379 // New folder should never be enabled in the root or media/ directories.
2343 this.newFolderButton_.disabled = isSystemDirEntry(this.currentDirEntry_); 2380 this.newFolderButton_.disabled = isSystemDirEntry(this.currentDirEntry_);
2344 2381
2345 this.document_.title = this.currentDirEntry_.fullPath; 2382 this.document_.title = this.currentDirEntry_.fullPath;
2346 2383
2347 var self = this; 2384 var self = this;
2348 this.rescanDirectory_(function() { 2385 this.rescanDirectory_(function() {
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
2797 case 69: // Ctrl-E => Rename. 2834 case 69: // Ctrl-E => Rename.
2798 this.updateCommands_(); 2835 this.updateCommands_();
2799 if (!this.commands_['rename'].disabled) { 2836 if (!this.commands_['rename'].disabled) {
2800 event.preventDefault(); 2837 event.preventDefault();
2801 this.commands_['rename'].execute(); 2838 this.commands_['rename'].execute();
2802 } 2839 }
2803 break; 2840 break;
2804 2841
2805 case 46: // Delete. 2842 case 46: // Delete.
2806 if (this.dialogType_ == FileManager.DialogType.FULL_PAGE && 2843 if (this.dialogType_ == FileManager.DialogType.FULL_PAGE &&
2807 this.selection.totalCount > 0 && 2844 this.selection && this.selection.totalCount > 0 &&
2808 !isSystemDirEntry(this.currentDirEntry_)) { 2845 !isSystemDirEntry(this.currentDirEntry_)) {
2809 event.preventDefault(); 2846 event.preventDefault();
2810 this.deleteEntries(this.selection.entries); 2847 this.deleteEntries(this.selection.entries);
2811 } 2848 }
2812 break; 2849 break;
2813 } 2850 }
2814 }; 2851 };
2815 2852
2816 /** 2853 /**
2817 * KeyPress event handler for the div.list-container element. 2854 * KeyPress event handler for the div.list-container element.
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2995 3032
2996 if (msg) { 3033 if (msg) {
2997 console.log('no no no'); 3034 console.log('no no no');
2998 this.alert.show(msg, onAccept); 3035 this.alert.show(msg, onAccept);
2999 return false; 3036 return false;
3000 } 3037 }
3001 3038
3002 return true; 3039 return true;
3003 }; 3040 };
3004 })(); 3041 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698