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

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

Issue 9802024: Refactoring copy/paste code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 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
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 // 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 7
8 /** 8 /**
9 * FileManager constructor. 9 * FileManager constructor.
10 * 10 *
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 cr.ui.Grid.decorate(this.grid_); 642 cr.ui.Grid.decorate(this.grid_);
643 643
644 this.downloadsWarning_ = 644 this.downloadsWarning_ =
645 this.dialogDom_.querySelector('.downloads-warning'); 645 this.dialogDom_.querySelector('.downloads-warning');
646 var html = util.htmlUnescape(str('DOWNLOADS_DIRECTORY_WARNING')); 646 var html = util.htmlUnescape(str('DOWNLOADS_DIRECTORY_WARNING'));
647 this.downloadsWarning_.lastElementChild.innerHTML = html; 647 this.downloadsWarning_.lastElementChild.innerHTML = html;
648 var link = this.downloadsWarning_.querySelector('a'); 648 var link = this.downloadsWarning_.querySelector('a');
649 link.addEventListener('click', this.onDownloadsWarningClick_.bind(this)); 649 link.addEventListener('click', this.onDownloadsWarningClick_.bind(this));
650 650
651 this.document_.addEventListener('keydown', this.onKeyDown_.bind(this)); 651 this.document_.addEventListener('keydown', this.onKeyDown_.bind(this));
652 this.document_.addEventListener('copy', 652 this.document_.addEventListener('copy', this.onCopy_.bind(this));
653 this.onCopy_.bind(this)); 653 this.document_.addEventListener('beforecopy',
654 this.onBeforeCopy_.bind(this));
654 // Disable the default browser context menu. 655 // Disable the default browser context menu.
655 this.document_.addEventListener('contextmenu', 656 this.document_.addEventListener('contextmenu',
656 function (e) { e.preventDefault() }); 657 function (e) { e.preventDefault() });
657 658
658 // We need to store a reference to the function returned by bind. Later, in 659 this.document_.addEventListener('paste', this.onPaste_.bind(this));
659 // canPaste function, we need to temporarily remove this event handler and 660 // HACK(serya): 'paste'/'beforepaste' must be used.
660 // use another 'paste' event handler to check the state of system clipboard. 661 // But 'beforepaste' is apparently broken.
661 this.onPasteBound_ = this.onPaste_.bind(this); 662 var iframe = this.document_.querySelector('#command-dispatcher');
662 this.document_.addEventListener('paste', this.onPasteBound_); 663 this.commandProbbingDoc_ = iframe.contentDocument;
663 664 this.commandProbbingDoc_.addEventListener('paste',
664 // In pasteFromClipboard function, we need to reset system clipboard after 665 this.onBeforePaste_.bind(this));
665 // 'cut' and 'paste' command sequence. The clipboardData.clearData doesn't 666 this.document_.addEventListener('cut', this.onCut_.bind(this));
666 // seem to work. We reset the system clipboard in another 'cut' event 667 this.document_.addEventListener('beforecut', this.onBeforeCut_.bind(this));
667 // handler as a workaround. This reference is used to temporarily remove
668 // 'cut' event handler as well.
669 this.onCutBound_ = this.onCut_.bind(this);
670 this.document_.addEventListener('cut', this.onCutBound_);
671 668
672 this.renameInput_ = this.document_.createElement('input'); 669 this.renameInput_ = this.document_.createElement('input');
673 this.renameInput_.className = 'rename'; 670 this.renameInput_.className = 'rename';
674 671
675 this.renameInput_.addEventListener( 672 this.renameInput_.addEventListener(
676 'keydown', this.onRenameInputKeyDown_.bind(this)); 673 'keydown', this.onRenameInputKeyDown_.bind(this));
677 this.renameInput_.addEventListener( 674 this.renameInput_.addEventListener(
678 'blur', this.onRenameInputBlur_.bind(this)); 675 'blur', this.onRenameInputBlur_.bind(this));
679 676
680 this.filenameInput_.addEventListener( 677 this.filenameInput_.addEventListener(
681 'keyup', this.onFilenameInputKeyUp_.bind(this)); 678 'keyup', this.onFilenameInputKeyUp_.bind(this));
682 this.filenameInput_.addEventListener( 679 this.filenameInput_.addEventListener(
683 'focus', this.onFilenameInputFocus_.bind(this)); 680 'focus', this.onFilenameInputFocus_.bind(this));
684 681
685 var listContainer = this.dialogDom_.querySelector('.list-container'); 682 var listContainer = this.dialogDom_.querySelector('.list-container');
686 listContainer.addEventListener('keydown', this.onListKeyDown_.bind(this)); 683 listContainer.addEventListener('keydown', this.onListKeyDown_.bind(this));
687 listContainer.addEventListener('keypress', this.onListKeyPress_.bind(this)); 684 listContainer.addEventListener('keypress', this.onListKeyPress_.bind(this));
688 this.okButton_.addEventListener('click', this.onOk_.bind(this)); 685 this.okButton_.addEventListener('click', this.onOk_.bind(this));
689 this.cancelButton_.addEventListener('click', this.onCancel_.bind(this)); 686 this.cancelButton_.addEventListener('click', this.onCancel_.bind(this));
690 687
691 this.dialogDom_.querySelector('div.open-sidebar').addEventListener( 688 this.dialogDom_.querySelector('div.open-sidebar').addEventListener(
692 'click', this.onToggleSidebar_.bind(this)); 689 'click', this.onToggleSidebar_.bind(this));
693 this.dialogDom_.querySelector('div.open-sidebar').addEventListener( 690 this.dialogDom_.querySelector('div.open-sidebar').addEventListener(
694 'keypress', this.onToggleSidebarPress_.bind(this)); 691 'keypress', this.onToggleSidebarPress_.bind(this));
695 this.dialogDom_.querySelector('div.close-sidebar').addEventListener( 692 this.dialogDom_.querySelector('div.close-sidebar').addEventListener(
696 'click', this.onToggleSidebar_.bind(this)); 693 'click', this.onToggleSidebar_.bind(this));
697 this.dialogDom_.querySelector('div.close-sidebar').addEventListener( 694 this.dialogDom_.querySelector('div.close-sidebar').addEventListener(
698 'keypress', this.onToggleSidebarPress_.bind(this)); 695 'keypress', this.onToggleSidebarPress_.bind(this));
699 this.dialogContainer_ = this.dialogDom_.querySelector('.dialog-container'); 696 this.dialogContainer_ = this.dialogDom_.querySelector('.dialog-container');
700
701 this.dialogDom_.querySelector('button.detail-view').addEventListener( 697 this.dialogDom_.querySelector('button.detail-view').addEventListener(
702 'click', this.onDetailViewButtonClick_.bind(this)); 698 'click', this.onDetailViewButtonClick_.bind(this));
703 this.dialogDom_.querySelector('button.thumbnail-view').addEventListener( 699 this.dialogDom_.querySelector('button.thumbnail-view').addEventListener(
704 'click', this.onThumbnailViewButtonClick_.bind(this)); 700 'click', this.onThumbnailViewButtonClick_.bind(this));
705 701
706 cr.ui.ComboButton.decorate(this.taskItems_); 702 cr.ui.ComboButton.decorate(this.taskItems_);
707 this.taskItems_.addEventListener('select', 703 this.taskItems_.addEventListener('select',
708 this.onTaskItemClicked_.bind(this)); 704 this.onTaskItemClicked_.bind(this));
709 705
710 this.dialogDom_.ownerDocument.defaultView.addEventListener( 706 this.dialogDom_.ownerDocument.defaultView.addEventListener(
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 }; 1082 };
1087 1083
1088 /** 1084 /**
1089 * Force the canExecute events to be dispatched. 1085 * Force the canExecute events to be dispatched.
1090 */ 1086 */
1091 FileManager.prototype.updateCommands_ = function() { 1087 FileManager.prototype.updateCommands_ = function() {
1092 for (var key in this.commands_) 1088 for (var key in this.commands_)
1093 this.commands_[key].disabled = !this.canExecute_(key); 1089 this.commands_[key].disabled = !this.canExecute_(key);
1094 }; 1090 };
1095 1091
1096 FileManager.prototype.canPaste_ = function(readonly) { 1092 FileManager.prototype.canPaste_ = function(clipboard) {
1097 /** 1093 return clipboard &&
1098 * Fire a paste event and check the "paste" command can be executed. 1094 clipboard.types &&
1099 * 1095 clipboard.types.indexOf('fs/iscut') != -1;
dgozman 2012/03/28 08:28:14 This method is not used.
SeRya 2012/03/28 08:43:07 Done.
1100 * We need to peek the content in system clipboard. Only cut/copy/paste
1101 * events contain clipboard data. So we need to fire a paste event and then
1102 * peek the system clipboard immediately.
1103 *
1104 * @return {boolean} True if "paste" command can be executed for current
1105 * directory.
1106 */
1107
1108 var canPaste = false;
1109 var clipboardCanPaste = function(event) {
1110 event.preventDefault();
1111 // Here we need to use lower case as clipboardData.types return lower
1112 // case DomStringList.
1113 if (event.clipboardData &&
1114 event.clipboardData.types &&
1115 event.clipboardData.types.indexOf('fs/iscut') != -1)
1116 canPaste = true;
1117 };
1118
1119 this.document_.removeEventListener('paste', this.onPasteBound_);
1120 this.document_.addEventListener('paste', clipboardCanPaste);
1121 this.document_.execCommand('paste');
1122 this.document_.removeEventListener('paste', clipboardCanPaste);
1123 this.document_.addEventListener('paste', this.onPasteBound_);
1124 return canPaste && !readonly;
1125 }; 1096 };
1126 1097
1127 /** 1098 /**
1128 * @param {string} commandId Command identifier. 1099 * @param {string} commandId Command identifier.
1129 * @return {boolean} True if the command can be executed for current 1100 * @return {boolean} True if the command can be executed for current
1130 * selection. 1101 * selection.
1131 */ 1102 */
1132 FileManager.prototype.canExecute_ = function(commandId) { 1103 FileManager.prototype.canExecute_ = function(commandId) {
1133 var readonly = this.directoryModel_.readonly; 1104 var readonly = this.directoryModel_.readonly;
1134 var path = this.directoryModel_.currentEntry.fullPath; 1105 var path = this.directoryModel_.currentEntry.fullPath;
1135 switch (commandId) { 1106 switch (commandId) {
1107 case 'copy':
1136 case 'cut': 1108 case 'cut':
1137 return !readonly && 1109 return this.document_.queryCommandEnabled(commandId);
1138 this.selection &&
1139 this.selection.totalCount > 0;
1140
1141 case 'copy':
1142 return path != '/' &&
1143 this.selection &&
1144 this.selection.totalCount > 0;
1145 1110
1146 case 'paste': 1111 case 'paste':
1147 return this.canPaste_(readonly); 1112 // HACK(serya): return this.document_.queryCommandEnabled('paste')
1113 // should be used.
1114 this.commandProbbingDoc_.execCommand('paste');
1115 return !this.commands_.paste.disabled;
1148 1116
1149 case 'rename': 1117 case 'rename':
1150 return (// Initialized to the point where we have a current directory 1118 return (// Initialized to the point where we have a current directory
1151 !readonly && 1119 !readonly &&
1152 // Rename not in progress. 1120 // Rename not in progress.
1153 !this.isRenamingInProgress() && 1121 !this.isRenamingInProgress() &&
1154 // Only one file selected. 1122 // Only one file selected.
1155 this.selection && 1123 this.selection &&
1156 this.selection.totalCount == 1); 1124 this.selection.totalCount == 1);
1157 1125
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1303 cr.ui.contextMenuHandler.setContextMenu(this.table_.querySelector('.list'), 1271 cr.ui.contextMenuHandler.setContextMenu(this.table_.querySelector('.list'),
1304 this.fileContextMenu_); 1272 this.fileContextMenu_);
1305 1273
1306 this.table_.addEventListener('mousedown', 1274 this.table_.addEventListener('mousedown',
1307 this.onGridOrTableMouseDown_.bind(this)); 1275 this.onGridOrTableMouseDown_.bind(this));
1308 this.setupDragAndDrop_(this.table_.list); 1276 this.setupDragAndDrop_(this.table_.list);
1309 }; 1277 };
1310 1278
1311 FileManager.prototype.setupDragAndDrop_ = function(list) { 1279 FileManager.prototype.setupDragAndDrop_ = function(list) {
1312 list.addEventListener('dragstart', this.onDragStart_.bind(this)); 1280 list.addEventListener('dragstart', this.onDragStart_.bind(this));
1281 list.addEventListener('dragend', this.onDragEnd_.bind(this));
1282 list.addEventListener('dragover', this.onDragOver_.bind(this));
1283 list.addEventListener('drop', this.onDrop_.bind(this));
1313 }; 1284 };
1314 1285
1315 FileManager.prototype.onDragStart_ = function(event) { 1286 FileManager.prototype.onDragStart_ = function(event) {
1316 var dt = event.dataTransfer; 1287 var dt = event.dataTransfer;
1317 var container = this.document_.querySelector('#drag-image-container'); 1288 var container = this.document_.querySelector('#drag-image-container');
1318 container.textContent = ''; 1289 var length = this.selection.dragNodes.length;
1319 for (var i = 0; i < this.selection.dragNodes.length; i++) { 1290 for (var i = 0; i < length; i++) {
1320 var listItem = this.selection.dragNodes[i]; 1291 var listItem = this.selection.dragNodes[i];
1321 listItem.selected = true; 1292 listItem.selected = true;
1293 listItem.style.zIndex = length - i;
1322 container.appendChild(listItem); 1294 container.appendChild(listItem);
1323 } 1295 }
1324 1296
1325 this.cutOrCopyToClipboard_(dt, false); 1297 this.cutOrCopyToClipboard_(dt, false);
1326 1298
1327 dt.setDragImage(container, 0, 0); 1299 dt.setDragImage(container, 0, 0);
1328 dt.effectAllowed = 'copyMove'; 1300 dt.effectAllowed = 'copyMove';
1329 }; 1301 };
1330 1302
1303 FileManager.prototype.onDragEnd_ = function(event) {
1304 var container = this.document_.querySelector('#drag-image-container');
1305 container.textContent = '';
1306 };
1307
1308 FileManager.prototype.onDragOver_ = function(event) {
1309 if (this.canPasteOrDrop_(event.dataTransfer)) {
1310 event.preventDefault();
dgozman 2012/03/28 08:28:14 It would be good to show cursor 'no-drop' otherwis
SeRya 2012/03/28 08:43:07 Let's do it later.
1311 }
1312 };
1313
1314 FileManager.prototype.onDrop_ = function(event) {
1315 if (!this.canPasteOrDrop_(event.dataTransfer))
1316 return;
1317 event.preventDefault();
1318 this.pasteFromClipboard_(event.dataTransfer);
1319 };
1320
1331 FileManager.prototype.initButter_ = function() { 1321 FileManager.prototype.initButter_ = function() {
1332 var self = this; 1322 var self = this;
1333 var progress = this.copyManager_.getProgress(); 1323 var progress = this.copyManager_.getProgress();
1334 1324
1335 var options = {progress: progress.percentage, actions:{}}; 1325 var options = {progress: progress.percentage, actions:{}};
1336 options.actions[str('CANCEL_LABEL')] = function cancelPaste() { 1326 options.actions[str('CANCEL_LABEL')] = function cancelPaste() {
1337 self.copyManager_.requestCancel(); 1327 self.copyManager_.requestCancel();
1338 }; 1328 };
1339 this.showButter(strf('PASTE_ITEMS_REMAINING', progress.pendingItems), 1329 this.showButter(strf('PASTE_ITEMS_REMAINING', progress.pendingItems),
1340 options); 1330 options);
(...skipping 1808 matching lines...) Expand 10 before | Expand all | Expand 10 after
3149 clipboard.setData('fs/directories', directories); 3139 clipboard.setData('fs/directories', directories);
3150 clipboard.setData('fs/files', files); 3140 clipboard.setData('fs/files', files);
3151 3141
3152 var files = this.selection.files; 3142 var files = this.selection.files;
3153 for(var i = 0; i < files.length; i++) { 3143 for(var i = 0; i < files.length; i++) {
3154 clipboard.items.add(files[i]); 3144 clipboard.items.add(files[i]);
3155 } 3145 }
3156 } 3146 }
3157 3147
3158 FileManager.prototype.onCopy_ = function(event) { 3148 FileManager.prototype.onCopy_ = function(event) {
3159 if (!this.selection || this.selection.totalCount == 0 || 3149 if (this.document_.activeElement.tagName == 'INPUT' ||
3160 this.document_.activeElement.tagName == 'INPUT') 3150 !this.canCopyOrDrag_()) {
3161 return; 3151 return;
3162 3152 }
3163 event.preventDefault(); 3153 event.preventDefault();
3164 this.cutOrCopyToClipboard_(event.clipboardData, false); 3154 this.cutOrCopyToClipboard_(event.clipboardData, false);
3165
3166 this.blinkSelection(); 3155 this.blinkSelection();
3167 }; 3156 };
3168 3157
3158 FileManager.prototype.onBeforeCopy_ = function(event) {
3159 event.returnValue = !this.canCopyOrDrag_();
dgozman 2012/03/28 08:28:14 Please, add a comment that returnValue==false init
SeRya 2012/03/28 08:43:07 Done.
3160 };
3161
3162 FileManager.prototype.canCopyOrDrag_ = function() {
3163 return this.selection && this.selection.totalCount > 0;
3164 };
3165
3169 FileManager.prototype.onCut_ = function(event) { 3166 FileManager.prototype.onCut_ = function(event) {
3170 if (!this.selection || this.selection.totalCount == 0 || 3167 if (!this.document_.activeElement.tagName == 'INPUT' ||
3171 this.commands_['cut'].disabled || 3168 this.canCutOrDrag_()) {
3172 this.document_.activeElement.tagName == 'INPUT')
3173 return; 3169 return;
3174 3170 }
3175 event.preventDefault(); 3171 event.preventDefault();
3176 this.cutOrCopyToClipboard_(event.clipboardData, true); 3172 this.cutOrCopyToClipboard_(event.clipboardData, true);
3177 3173
3178 this.blinkSelection(); 3174 this.blinkSelection();
3179 }; 3175 };
3180 3176
3177 FileManager.prototype.onBeforeCut_ = function(event) {
3178 event.returnValue = !this.canCutOrDrag_();
3179 };
3180
3181 FileManager.prototype.canCutOrDrag_ = function() {
3182 var ro = this.directoryModel_.readonly;
3183 return !ro && this.selection && this.selection.totalCount > 0;
3184 };
3185
3181 FileManager.prototype.onPaste_ = function(event) { 3186 FileManager.prototype.onPaste_ = function(event) {
3182 // Check that the data copied by ourselves. 3187 if (this.document_.activeElement.tagName == 'INPUT' ||
3183 if (!event.clipboardData.getData('fs/isCut') || 3188 !this.canPasteOrDrop_(event.clipboardData)) {
3184 this.document_.activeElement.tagName == 'INPUT')
3185 return; 3189 return;
3190 }
3186 event.preventDefault(); 3191 event.preventDefault();
3187 this.pasteFromClipboard_(event.clipboardData); 3192 this.pasteFromClipboard_(event.clipboardData);
3188 }; 3193 };
3189 3194
3195 FileManager.prototype.onBeforePaste_ = function(event) {
3196 // TODO(serya) should be:
3197 // event.returnValue = !this.canPasteOrDrop_(event.clipboardData);
3198 this.commands_.paste.disabled =
3199 !this.canPasteOrDrop_(event.clipboardData);
3200 };
3201
3202 FileManager.prototype.canPasteOrDrop_ = function(clipboardData) {
3203 var ro = this.directoryModel_.readonly;
3204 return !ro && !!clipboardData.getData('fs/isCut');
3205 };
3206
3190 /** 3207 /**
3191 * Queue up a file copy operation based on the current system clipboard. 3208 * Queue up a file copy operation based on the current system clipboard.
3192 */ 3209 */
3193 FileManager.prototype.pasteFromClipboard_ = function(clipboard) { 3210 FileManager.prototype.pasteFromClipboard_ = function(clipboard) {
3194 var operationInfo = { 3211 var operationInfo = {
3195 isCut: clipboard.getData('fs/isCut'), 3212 isCut: clipboard.getData('fs/isCut'),
3196 isOnGData: clipboard.getData('fs/isOnGData'), 3213 isOnGData: clipboard.getData('fs/isOnGData'),
3197 sourceDir: clipboard.getData('fs/sourceDir'), 3214 sourceDir: clipboard.getData('fs/sourceDir'),
3198 directories: clipboard.getData('fs/directories'), 3215 directories: clipboard.getData('fs/directories'),
3199 files: clipboard.getData('fs/files') 3216 files: clipboard.getData('fs/files')
(...skipping 1232 matching lines...) Expand 10 before | Expand all | Expand 10 after
4432 }); 4449 });
4433 }, onError); 4450 }, onError);
4434 4451
4435 function onError(err) { 4452 function onError(err) {
4436 console.log('Error while checking free space: ' + err); 4453 console.log('Error while checking free space: ' + err);
4437 setTimeout(doCheck, 1000 * 60); 4454 setTimeout(doCheck, 1000 * 60);
4438 } 4455 }
4439 } 4456 }
4440 } 4457 }
4441 })(); 4458 })();
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/resources/file_manager/main.html » ('j') | chrome/browser/resources/file_manager/main.html » ('J')

Powered by Google App Engine
This is Rietveld 408576698