OLD | NEW |
---|---|
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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 metrics.recordEnum('Create', this.dialogType_, | 60 metrics.recordEnum('Create', this.dialogType_, |
61 [FileManager.DialogType.SELECT_FOLDER, | 61 [FileManager.DialogType.SELECT_FOLDER, |
62 FileManager.DialogType.SELECT_SAVEAS_FILE, | 62 FileManager.DialogType.SELECT_SAVEAS_FILE, |
63 FileManager.DialogType.SELECT_OPEN_FILE, | 63 FileManager.DialogType.SELECT_OPEN_FILE, |
64 FileManager.DialogType.SELECT_OPEN_MULTI_FILE, | 64 FileManager.DialogType.SELECT_OPEN_MULTI_FILE, |
65 FileManager.DialogType.FULL_PAGE]); | 65 FileManager.DialogType.FULL_PAGE]); |
66 | 66 |
67 // TODO(dgozman): This will be changed to LocaleInfo. | 67 // TODO(dgozman): This will be changed to LocaleInfo. |
68 this.locale_ = new v8Locale(navigator.language); | 68 this.locale_ = new v8Locale(navigator.language); |
69 | 69 |
70 this.resolveRoots_(); | 70 this.requestFileSystem_(); |
71 this.initDom_(); | 71 this.initDom_(); |
72 this.initDialogType_(); | 72 this.initDialogType_(); |
73 this.dialogDom_.style.opacity = '1'; | 73 this.dialogDom_.style.opacity = '1'; |
74 } | 74 } |
75 | 75 |
76 FileManager.prototype = { | 76 FileManager.prototype = { |
77 __proto__: cr.EventTarget.prototype | 77 __proto__: cr.EventTarget.prototype |
78 }; | 78 }; |
79 | 79 |
80 // Anonymous "namespace". | 80 // Anonymous "namespace". |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
462 chrome.fileBrowserPrivate.getStrings(function(strings) { | 462 chrome.fileBrowserPrivate.getStrings(function(strings) { |
463 localStrings = new LocalStrings(strings); | 463 localStrings = new LocalStrings(strings); |
464 if (callback) | 464 if (callback) |
465 callback(); | 465 callback(); |
466 }); | 466 }); |
467 }; | 467 }; |
468 | 468 |
469 // Instance methods. | 469 // Instance methods. |
470 | 470 |
471 /** | 471 /** |
472 * Request file system and get root entries asynchronously. Invokes init_ | 472 * Request local file system, resolve roots and init_ after that. |
473 * when have finished. | |
474 */ | 473 */ |
475 FileManager.prototype.resolveRoots_ = function(callback) { | 474 FileManager.prototype.requestFileSystem_ = function() { |
Dmitry Zvorygin
2011/11/22 14:42:47
It might be better to move requestFileSystem_ to i
dgozman
2011/11/22 14:51:37
Renamed.
| |
476 var rootPaths = ['Downloads', 'removable', 'archive']; | 475 util.installFileErrorToString(); |
476 metrics.startInterval('RequestLocalFileSystem'); | |
477 | 477 |
478 metrics.startInterval('RequestLocalFileSystem'); | |
479 var self = this; | 478 var self = this; |
480 chrome.fileBrowserPrivate.requestLocalFileSystem(function(filesystem) { | 479 chrome.fileBrowserPrivate.requestLocalFileSystem(function(filesystem) { |
481 self.filesystem_ = filesystem; | |
482 util.installFileErrorToString(); | |
483 | |
484 metrics.recordTime('RequestLocalFileSystem'); | 480 metrics.recordTime('RequestLocalFileSystem'); |
485 console.log('Found filesystem: ' + filesystem.name, filesystem); | 481 console.log('Found filesystem: ' + filesystem.name, filesystem); |
486 | 482 |
487 var rootEntries = []; | 483 self.filesystem_ = filesystem; |
488 | 484 self.resolveRoots_(function(rootEntries) { |
489 function onAllRootsFound() { | |
490 self.rootEntries_ = rootEntries; | 485 self.rootEntries_ = rootEntries; |
491 self.init_(); | 486 self.init_(); |
492 } | 487 }); |
493 | |
494 function onPathError(path, err) { | |
495 console.error('Error locating root path: ' + path + ': ' + err); | |
496 } | |
497 | |
498 function onEntryFound(entry) { | |
499 if (entry) { | |
500 rootEntries.push(entry); | |
501 } else { | |
502 onAllRootsFound(); | |
503 } | |
504 } | |
505 | |
506 metrics.startInterval('EnumerateRoots'); | |
507 if (filesystem.name.match(/^chrome-extension_\S+:external/i)) { | |
508 // We've been handed the local filesystem, whose root directory | |
509 // cannot be enumerated. | |
510 util.getDirectories(filesystem.root, {create: false}, rootPaths, | |
511 onEntryFound, onPathError); | |
512 } else { | |
513 util.forEachDirEntry(filesystem.root, onEntryFound); | |
514 } | |
515 }); | 488 }); |
516 }; | 489 }; |
517 | 490 |
518 /** | 491 /** |
492 * Get root entries asynchronously. Invokes callback | |
493 * when have finished. | |
494 */ | |
495 FileManager.prototype.resolveRoots_ = function(callback) { | |
496 var rootPaths = [DOWNLOADS_DIRECTORY, ARCHIVE_DIRECTORY, | |
497 REMOVABLE_DIRECTORY].map(function(s) { return s.substring(1); }); | |
498 var rootEntries = []; | |
499 | |
500 // The number of entries left to enumerate to get all roots. | |
501 // When equals to zero, we are done. | |
502 // Initially is 100 to prevent finishing before these entries themselves | |
503 // are found. | |
504 var entriesToEnumerate = 100; | |
Vladislav Kaznacheev
2011/11/22 13:16:35
Seems quite hacky. How about having a set of direc
dgozman
2011/11/22 14:15:14
We do not know the whole set in advance. Even wors
| |
505 | |
506 function onAllRootsFound() { | |
Vladislav Kaznacheev
2011/11/22 13:16:35
It is only called from one place, lets inline it.
dgozman
2011/11/22 14:15:14
Done.
| |
507 callback(rootEntries); | |
508 } | |
509 | |
510 function onPathError(path, err) { | |
511 console.error('Error locating root path: ' + path + ': ' + err); | |
512 } | |
513 | |
514 function onRootFound(root) { | |
515 if (root) { | |
516 rootEntries.push(root); | |
517 } else { | |
518 entriesToEnumerate--; | |
519 if (entriesToEnumerate == 0) | |
520 onAllRootsFound(); | |
521 } | |
522 } | |
523 | |
524 function onEntryFound(entry) { | |
525 if (entry) { | |
526 entriesToEnumerate++; | |
527 var path = entry.fullPath; | |
528 if (path == ARCHIVE_DIRECTORY || path == REMOVABLE_DIRECTORY) { | |
529 // All removable devices and mounted archives are considered | |
530 // roots, and are shown in the sidebar. | |
531 util.forEachDirEntry(entry, onRootFound); | |
532 } else { | |
533 onRootFound(entry); | |
534 onRootFound(null); | |
535 } | |
536 } else { | |
537 // No more entries to enumerate - remove fake 100. | |
538 entriesToEnumerate -= 100; | |
539 } | |
540 } | |
541 | |
542 metrics.startInterval('EnumerateRoots'); | |
Dmitry Zvorygin
2011/11/22 14:42:47
Should be corresponding metrics.recordTime or some
dgozman
2011/11/22 14:51:37
Done.
| |
543 if (this.filesystem_.name.match(/^chrome-extension_\S+:external/i)) { | |
544 // We've been handed the local filesystem, whose root directory | |
545 // cannot be enumerated. | |
546 util.getDirectories(this.filesystem_.root, {create: false}, rootPaths, | |
547 onEntryFound, onPathError); | |
548 } else { | |
549 util.forEachDirEntry(this.filesystem_.root, onEntryFound); | |
550 } | |
551 }; | |
552 | |
553 /** | |
519 * Continue initializing the file manager after resolving roots. | 554 * Continue initializing the file manager after resolving roots. |
520 */ | 555 */ |
521 FileManager.prototype.init_ = function() { | 556 FileManager.prototype.init_ = function() { |
522 metrics.startInterval('InitFileManager'); | 557 metrics.startInterval('InitFileManager'); |
558 this.initCommands_(); | |
523 this.initFileList_(); | 559 this.initFileList_(); |
524 this.initDialogs_(); | 560 this.initDialogs_(); |
525 | 561 |
526 // TODO(rginda): 6/22/11: Remove this test when createDateTimeFormat is | 562 // TODO(rginda): 6/22/11: Remove this test when createDateTimeFormat is |
527 // available in all chrome trunk builds. | 563 // available in all chrome trunk builds. |
528 if ('createDateTimeFormat' in this.locale_) { | 564 if ('createDateTimeFormat' in this.locale_) { |
529 this.shortDateFormatter_ = | 565 this.shortDateFormatter_ = |
530 this.locale_.createDateTimeFormat({'dateType': 'medium'}); | 566 this.locale_.createDateTimeFormat({'dateType': 'medium'}); |
531 } else { | 567 } else { |
532 this.shortDateFormatter_ = { | 568 this.shortDateFormatter_ = { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
586 | 622 |
587 // The list of callbacks to be invoked during the directory rescan after | 623 // The list of callbacks to be invoked during the directory rescan after |
588 // all paste tasks are complete. | 624 // all paste tasks are complete. |
589 this.pasteSuccessCallbacks_ = []; | 625 this.pasteSuccessCallbacks_ = []; |
590 | 626 |
591 // The list of active mount points to distinct them from other directories. | 627 // The list of active mount points to distinct them from other directories. |
592 chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) { | 628 chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) { |
593 self.mountPoints_ = mountPoints; | 629 self.mountPoints_ = mountPoints; |
594 }); | 630 }); |
595 | 631 |
596 this.initCommands_(); | |
597 | |
598 this.setupCurrentDirectory_(); | 632 this.setupCurrentDirectory_(); |
599 | 633 |
600 this.summarizeSelection_(); | 634 this.summarizeSelection_(); |
601 | 635 |
602 this.dataModel_.sort('cachedMtime_', 'desc'); | 636 this.dataModel_.sort('cachedMtime_', 'desc'); |
603 | 637 |
604 this.refocus(); | 638 this.refocus(); |
605 | 639 |
606 this.createMetadataProvider_(); | 640 this.createMetadataProvider_(); |
607 metrics.recordTime('InitFileManager'); | 641 metrics.recordTime('InitFileManager'); |
608 metrics.recordTime('TotalLoad'); | 642 metrics.recordTime('TotalLoad'); |
609 }; | 643 }; |
610 | 644 |
611 /** | 645 /** |
612 * One-time initialization of commands. | 646 * One-time initialization of commands. |
613 */ | 647 */ |
614 FileManager.prototype.initCommands_ = function() { | 648 FileManager.prototype.initCommands_ = function() { |
615 var commands = this.dialogDom_.querySelectorAll('command'); | 649 var commands = this.dialogDom_.querySelectorAll('command'); |
616 for (var i = 0; i < commands.length; i++) { | 650 for (var i = 0; i < commands.length; i++) { |
617 var command = commands[i]; | 651 var command = commands[i]; |
618 cr.ui.Command.decorate(command); | 652 cr.ui.Command.decorate(command); |
653 command.label = command.textContent; | |
654 command.textContent = ''; | |
619 this.commands_[command.id] = command; | 655 this.commands_[command.id] = command; |
620 } | 656 } |
621 | 657 |
622 this.fileContextMenu_ = this.dialogDom_.querySelector('.file-context-menu'); | 658 this.fileContextMenu_ = this.dialogDom_.querySelector('.file-context-menu'); |
623 cr.ui.Menu.decorate(this.fileContextMenu_); | 659 cr.ui.Menu.decorate(this.fileContextMenu_); |
624 | 660 |
625 this.document_.addEventListener('canExecute', | 661 this.document_.addEventListener('canExecute', |
626 this.onCanExecute_.bind(this)); | 662 this.onCanExecute_.bind(this)); |
627 this.document_.addEventListener('command', this.onCommand_.bind(this)); | 663 this.document_.addEventListener('command', this.onCommand_.bind(this)); |
628 } | 664 } |
(...skipping 17 matching lines...) Expand all Loading... | |
646 this.previewThumbnails_ = | 682 this.previewThumbnails_ = |
647 this.dialogDom_.querySelector('.preview-thumbnails'); | 683 this.dialogDom_.querySelector('.preview-thumbnails'); |
648 this.previewPanel_ = this.dialogDom_.querySelector('.preview-panel'); | 684 this.previewPanel_ = this.dialogDom_.querySelector('.preview-panel'); |
649 this.previewFilename_ = this.dialogDom_.querySelector('.preview-filename'); | 685 this.previewFilename_ = this.dialogDom_.querySelector('.preview-filename'); |
650 this.previewSummary_ = this.dialogDom_.querySelector('.preview-summary'); | 686 this.previewSummary_ = this.dialogDom_.querySelector('.preview-summary'); |
651 this.previewMetadata_ = this.dialogDom_.querySelector('.preview-metadata'); | 687 this.previewMetadata_ = this.dialogDom_.querySelector('.preview-metadata'); |
652 this.filenameInput_ = this.dialogDom_.querySelector('.filename-input'); | 688 this.filenameInput_ = this.dialogDom_.querySelector('.filename-input'); |
653 this.taskButtons_ = this.dialogDom_.querySelector('.task-buttons'); | 689 this.taskButtons_ = this.dialogDom_.querySelector('.task-buttons'); |
654 this.okButton_ = this.dialogDom_.querySelector('.ok'); | 690 this.okButton_ = this.dialogDom_.querySelector('.ok'); |
655 this.cancelButton_ = this.dialogDom_.querySelector('.cancel'); | 691 this.cancelButton_ = this.dialogDom_.querySelector('.cancel'); |
656 this.newFolderButton_ = this.dialogDom_.querySelector('.new-folder'); | |
657 this.deleteButton_ = this.dialogDom_.querySelector('.delete-button'); | 692 this.deleteButton_ = this.dialogDom_.querySelector('.delete-button'); |
658 | 693 |
659 this.downloadsWarning_ = | 694 this.downloadsWarning_ = |
660 this.dialogDom_.querySelector('.downloads-warning'); | 695 this.dialogDom_.querySelector('.downloads-warning'); |
661 var html = util.htmlUnescape(str('DOWNLOADS_DIRECTORY_WARNING')); | 696 var html = util.htmlUnescape(str('DOWNLOADS_DIRECTORY_WARNING')); |
662 this.downloadsWarning_.lastElementChild.innerHTML = html; | 697 this.downloadsWarning_.lastElementChild.innerHTML = html; |
663 var link = this.downloadsWarning_.querySelector('a'); | 698 var link = this.downloadsWarning_.querySelector('a'); |
664 link.addEventListener('click', this.onDownloadsWarningClick_.bind(this)); | 699 link.addEventListener('click', this.onDownloadsWarningClick_.bind(this)); |
665 | 700 |
666 this.document_.addEventListener('keydown', this.onKeyDown_.bind(this)); | 701 this.document_.addEventListener('keydown', this.onKeyDown_.bind(this)); |
(...skipping 10 matching lines...) Expand all Loading... | |
677 'keyup', this.onFilenameInputKeyUp_.bind(this)); | 712 'keyup', this.onFilenameInputKeyUp_.bind(this)); |
678 this.filenameInput_.addEventListener( | 713 this.filenameInput_.addEventListener( |
679 'focus', this.onFilenameInputFocus_.bind(this)); | 714 'focus', this.onFilenameInputFocus_.bind(this)); |
680 | 715 |
681 var listContainer = this.dialogDom_.querySelector('.list-container'); | 716 var listContainer = this.dialogDom_.querySelector('.list-container'); |
682 listContainer.addEventListener('keydown', this.onListKeyDown_.bind(this)); | 717 listContainer.addEventListener('keydown', this.onListKeyDown_.bind(this)); |
683 listContainer.addEventListener('keypress', this.onListKeyPress_.bind(this)); | 718 listContainer.addEventListener('keypress', this.onListKeyPress_.bind(this)); |
684 this.okButton_.addEventListener('click', this.onOk_.bind(this)); | 719 this.okButton_.addEventListener('click', this.onOk_.bind(this)); |
685 this.cancelButton_.addEventListener('click', this.onCancel_.bind(this)); | 720 this.cancelButton_.addEventListener('click', this.onCancel_.bind(this)); |
686 | 721 |
687 this.dialogDom_.querySelector('button.new-folder').addEventListener( | 722 this.dialogDom_.querySelector('div.open-sidebar').addEventListener( |
688 'click', this.onNewFolderButtonClick_.bind(this)); | 723 'click', this.onToggleSidebar_.bind(this)); |
724 this.dialogDom_.querySelector('div.close-sidebar').addEventListener( | |
725 'click', this.onToggleSidebar_.bind(this)); | |
726 this.dialogContainer_ = this.dialogDom_.querySelector('.dialog-container'); | |
689 | 727 |
690 this.dialogDom_.querySelector('button.detail-view').addEventListener( | 728 this.dialogDom_.querySelector('button.detail-view').addEventListener( |
691 'click', this.onDetailViewButtonClick_.bind(this)); | 729 'click', this.onDetailViewButtonClick_.bind(this)); |
692 this.dialogDom_.querySelector('button.thumbnail-view').addEventListener( | 730 this.dialogDom_.querySelector('button.thumbnail-view').addEventListener( |
693 'click', this.onThumbnailViewButtonClick_.bind(this)); | 731 'click', this.onThumbnailViewButtonClick_.bind(this)); |
694 | 732 |
695 this.dialogDom_.ownerDocument.defaultView.addEventListener( | 733 this.dialogDom_.ownerDocument.defaultView.addEventListener( |
696 'resize', this.onResize_.bind(this)); | 734 'resize', this.onResize_.bind(this)); |
697 | 735 |
698 var ary = this.dialogDom_.querySelectorAll('[visibleif]'); | 736 var ary = this.dialogDom_.querySelectorAll('[visibleif]'); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
731 if (this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FILE || | 769 if (this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FILE || |
732 this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FOLDER || | 770 this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FOLDER || |
733 this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) { | 771 this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) { |
734 this.selectionModelClass_ = cr.ui.ListSingleSelectionModel; | 772 this.selectionModelClass_ = cr.ui.ListSingleSelectionModel; |
735 } else { | 773 } else { |
736 this.selectionModelClass_ = cr.ui.ListSelectionModel; | 774 this.selectionModelClass_ = cr.ui.ListSelectionModel; |
737 } | 775 } |
738 | 776 |
739 this.initTable_(); | 777 this.initTable_(); |
740 this.initGrid_(); | 778 this.initGrid_(); |
779 this.initRootsList_(); | |
741 | 780 |
742 this.setListType(FileManager.ListType.DETAIL); | 781 this.setListType(FileManager.ListType.DETAIL); |
743 | 782 |
744 this.onResize_(); | 783 this.onResize_(); |
745 | 784 |
746 this.textSearchState_ = {text: '', date: new Date()}; | 785 this.textSearchState_ = {text: '', date: new Date()}; |
747 }; | 786 }; |
748 | 787 |
788 FileManager.prototype.initRootsList_ = function() { | |
789 this.rootsList_ = this.dialogDom_.querySelector('.roots-list'); | |
790 cr.ui.List.decorate(this.rootsList_); | |
791 | |
792 var self = this; | |
793 this.rootsList_.itemConstructor = function(entry) { | |
794 return self.renderRoot_(entry); | |
795 }; | |
796 | |
797 this.rootsList_.selectionModel = new cr.ui.ListSingleSelectionModel(); | |
798 this.rootsList_.selectionModel.addEventListener( | |
799 'change', this.onRootsSelectionChanged_.bind(this)); | |
800 | |
801 // TODO(dgozman): add "Add a drive" item. | |
802 this.rootsList_.dataModel = new cr.ui.ArrayDataModel(this.rootEntries_); | |
803 }; | |
804 | |
805 FileManager.prototype.updateRoots_ = function(opt_changeDirectoryTo) { | |
806 var self = this; | |
807 this.resolveRoots_(function(rootEntries) { | |
808 self.rootEntries_ = rootEntries; | |
809 | |
810 var dataModel = this.rootsList_.dataModel; | |
811 var args = [0, dataModel.length].concat(rootEntries); | |
812 dataModel.splice.apply(dataModel, args); | |
813 | |
814 this.updateRootsListSelection_(); | |
815 | |
816 if (opt_changeDirectoryTo) | |
817 self.changeDirectory(opt_changeDirectoryTo); | |
818 }); | |
819 }; | |
820 | |
749 /** | 821 /** |
750 * Get the icon type for a given Entry. | 822 * Get the icon type for a given Entry. |
751 * | 823 * |
752 * @param {Entry} entry An Entry subclass (FileEntry or DirectoryEntry). | 824 * @param {Entry} entry An Entry subclass (FileEntry or DirectoryEntry). |
753 * @return {string} | 825 * @return {string} |
754 */ | 826 */ |
755 FileManager.prototype.getIconType = function(entry) { | 827 FileManager.prototype.getIconType = function(entry) { |
756 if (!('cachedIconType_' in entry)) | 828 if (!('cachedIconType_' in entry)) |
757 entry.cachedIconType_ = this.computeIconType_(entry); | 829 entry.cachedIconType_ = this.computeIconType_(entry); |
758 return entry.cachedIconType_; | 830 return entry.cachedIconType_; |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1058 !isSystemDirEntry(this.currentDirEntry_)); | 1130 !isSystemDirEntry(this.currentDirEntry_)); |
1059 | 1131 |
1060 case 'delete': | 1132 case 'delete': |
1061 return (// Initialized to the point where we have a current directory | 1133 return (// Initialized to the point where we have a current directory |
1062 this.currentDirEntry_ && | 1134 this.currentDirEntry_ && |
1063 // Rename not in progress. | 1135 // Rename not in progress. |
1064 !this.renameInput_.currentEntry && | 1136 !this.renameInput_.currentEntry && |
1065 !isSystemDirEntry(this.currentDirEntry_)) && | 1137 !isSystemDirEntry(this.currentDirEntry_)) && |
1066 this.selection && | 1138 this.selection && |
1067 this.selection.totalCount > 0; | 1139 this.selection.totalCount > 0; |
1140 | |
1141 case 'newfolder': | |
1142 return this.currentDirEntry_ && | |
1143 (this.dialogType_ == 'saveas-file' || | |
1144 this.dialogType_ == 'full-page'); | |
1068 } | 1145 } |
1069 }; | 1146 }; |
1070 | 1147 |
1071 FileManager.prototype.updateCommonActionButtons_ = function() { | 1148 FileManager.prototype.updateCommonActionButtons_ = function() { |
1072 if (this.deleteButton_) | 1149 if (this.deleteButton_) |
1073 this.deleteButton_.disabled = !this.canExecute_('delete'); | 1150 this.deleteButton_.disabled = !this.canExecute_('delete'); |
1074 }; | 1151 }; |
1075 | 1152 |
1076 FileManager.prototype.setListType = function(type) { | 1153 FileManager.prototype.setListType = function(type) { |
1077 if (type && type == this.listType_) | 1154 if (type && type == this.listType_) |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1263 leadIndex); | 1340 leadIndex); |
1264 return; | 1341 return; |
1265 } | 1342 } |
1266 | 1343 |
1267 this.initiateRename_(label); | 1344 this.initiateRename_(label); |
1268 return; | 1345 return; |
1269 | 1346 |
1270 case 'delete': | 1347 case 'delete': |
1271 this.deleteEntries(this.selection.entries); | 1348 this.deleteEntries(this.selection.entries); |
1272 return; | 1349 return; |
1350 | |
1351 case 'newfolder': | |
1352 this.onNewFolderCommand_(event); | |
1353 return; | |
1273 } | 1354 } |
1274 }; | 1355 }; |
1275 | 1356 |
1276 /** | 1357 /** |
1277 * Respond to the back and forward buttons. | 1358 * Respond to the back and forward buttons. |
1278 */ | 1359 */ |
1279 FileManager.prototype.onPopState_ = function(event) { | 1360 FileManager.prototype.onPopState_ = function(event) { |
1280 // TODO(serya): We should restore selected items here. | 1361 // TODO(serya): We should restore selected items here. |
1281 if (this.rootEntries_) | 1362 if (this.rootEntries_) |
1282 this.setupCurrentDirectory_(); | 1363 this.setupCurrentDirectory_(); |
1283 }; | 1364 }; |
1284 | 1365 |
1285 FileManager.prototype.requestResize_ = function(timeout) { | 1366 FileManager.prototype.requestResize_ = function(timeout) { |
1286 var self = this; | 1367 var self = this; |
1287 setTimeout(function() { self.onResize_() }, timeout || 0); | 1368 setTimeout(function() { self.onResize_() }, timeout || 0); |
1288 }; | 1369 }; |
1289 | 1370 |
1290 /** | 1371 /** |
1291 * Resize details and thumb views to fit the new window size. | 1372 * Resize details and thumb views to fit the new window size. |
1292 */ | 1373 */ |
1293 FileManager.prototype.onResize_ = function() { | 1374 FileManager.prototype.onResize_ = function() { |
1294 this.table_.style.height = this.grid_.style.height = | 1375 this.table_.style.height = this.grid_.style.height = |
1295 this.grid_.parentNode.clientHeight + 'px'; | 1376 this.grid_.parentNode.clientHeight + 'px'; |
1296 this.table_.style.width = this.grid_.style.width = | |
1297 this.grid_.parentNode.clientWidth + 'px'; | |
1298 | |
1299 this.table_.list_.style.width = this.table_.parentNode.clientWidth + 'px'; | |
1300 this.table_.list_.style.height = (this.table_.clientHeight - 1 - | 1377 this.table_.list_.style.height = (this.table_.clientHeight - 1 - |
1301 this.table_.header_.clientHeight) + 'px'; | 1378 this.table_.header_.clientHeight) + 'px'; |
1302 | 1379 |
1303 if (this.listType_ == FileManager.ListType.THUMBNAIL) { | 1380 if (this.listType_ == FileManager.ListType.THUMBNAIL) { |
1304 var self = this; | 1381 var self = this; |
1305 setTimeout(function() { | 1382 setTimeout(function() { |
1306 self.grid_.columns = 0; | 1383 self.grid_.columns = 0; |
1307 self.grid_.redraw(); | 1384 self.grid_.redraw(); |
1308 }, 0); | 1385 }, 0); |
1309 } else { | 1386 } else { |
1310 this.currentList_.redraw(); | 1387 this.currentList_.redraw(); |
1311 } | 1388 } |
1389 | |
1390 this.rootsList_.style.height = | |
1391 this.rootsList_.parentNode.clientHeight + 'px'; | |
1392 this.rootsList_.redraw(); | |
1312 }; | 1393 }; |
1313 | 1394 |
1314 FileManager.prototype.resolvePath = function( | 1395 FileManager.prototype.resolvePath = function( |
1315 path, resultCallback, errorCallback) { | 1396 path, resultCallback, errorCallback) { |
1316 return util.resolvePath(this.filesystem_.root, path, resultCallback, | 1397 return util.resolvePath(this.filesystem_.root, path, resultCallback, |
1317 errorCallback); | 1398 errorCallback); |
1318 }; | 1399 }; |
1319 | 1400 |
1320 /** | 1401 /** |
1321 * Restores current directory and may be a selected item after page load (or | 1402 * Restores current directory and may be a selected item after page load (or |
(...skipping 13 matching lines...) Expand all Loading... | |
1335 this.setupPath_(this.params_.defaultPath); | 1416 this.setupPath_(this.params_.defaultPath); |
1336 } else { | 1417 } else { |
1337 this.setupDefaultPath_(); | 1418 this.setupDefaultPath_(); |
1338 } | 1419 } |
1339 }; | 1420 }; |
1340 | 1421 |
1341 FileManager.prototype.setupDefaultPath_ = function() { | 1422 FileManager.prototype.setupDefaultPath_ = function() { |
1342 // No preset given, find a good place to start. | 1423 // No preset given, find a good place to start. |
1343 // Check for removable devices, if there are none, go to Downloads. | 1424 // Check for removable devices, if there are none, go to Downloads. |
1344 var removableDirectoryEntry = this.rootEntries_.filter(function(rootEntry) { | 1425 var removableDirectoryEntry = this.rootEntries_.filter(function(rootEntry) { |
1345 return rootEntry.fullPath == REMOVABLE_DIRECTORY; | 1426 return isParentPath(REMOVABLE_DIRECTORY, rootEntry.fullPath); |
1346 })[0]; | 1427 })[0]; |
1347 if (!removableDirectoryEntry) { | 1428 this.changeDirectory( |
1348 this.changeDirectory(DOWNLOADS_DIRECTORY, CD_NO_HISTORY); | 1429 removableDirectoryEntry.fullPath || DOWNLOADS_DIRECTORY, |
1349 return; | 1430 CD_NO_HISTORY); |
1350 } | |
1351 | |
1352 var foundRemovable = false; | |
1353 util.forEachDirEntry(removableDirectoryEntry, function(result) { | |
1354 if (result) { | |
1355 foundRemovable = true; | |
1356 } else { // Done enumerating, and we know the answer. | |
1357 this.changeDirectory(foundRemovable ? '/' : DOWNLOADS_DIRECTORY, | |
1358 CD_NO_HISTORY); | |
1359 } | |
1360 }.bind(this)); | |
1361 }; | 1431 }; |
1362 | 1432 |
1363 FileManager.prototype.setupPath_ = function(path) { | 1433 FileManager.prototype.setupPath_ = function(path) { |
1364 // Split the dirname from the basename. | 1434 // Split the dirname from the basename. |
1365 var ary = path.match(/^(?:(.*)\/)?([^\/]*)$/); | 1435 var ary = path.match(/^(?:(.*)\/)?([^\/]*)$/); |
1366 if (!ary) { | 1436 if (!ary) { |
1367 console.warn('Unable to split default path: ' + path); | 1437 console.warn('Unable to split default path: ' + path); |
1368 self.changeDirectory('/', CD_NO_HISTORY); | 1438 self.changeDirectory('/', CD_NO_HISTORY); |
1369 return; | 1439 return; |
1370 } | 1440 } |
(...skipping 16 matching lines...) Expand all Loading... | |
1387 return; | 1457 return; |
1388 } | 1458 } |
1389 | 1459 |
1390 // Leaf is an existing file, cd to its parent directory and select it. | 1460 // Leaf is an existing file, cd to its parent directory and select it. |
1391 self.changeDirectoryEntry(baseDirEntry, CD_NO_HISTORY, leafEntry.name); | 1461 self.changeDirectoryEntry(baseDirEntry, CD_NO_HISTORY, leafEntry.name); |
1392 } | 1462 } |
1393 | 1463 |
1394 function onLeafError(err) { | 1464 function onLeafError(err) { |
1395 // Set filename first so OK button will update in changeDirectoryEntry. | 1465 // Set filename first so OK button will update in changeDirectoryEntry. |
1396 self.filenameInput_.value = leafName; | 1466 self.filenameInput_.value = leafName; |
1467 self.selectDefaultPathInFilenameInput_(); | |
1397 if (err = FileError.NOT_FOUND_ERR) { | 1468 if (err = FileError.NOT_FOUND_ERR) { |
1398 // Leaf does not exist, it's just a suggested file name. | 1469 // Leaf does not exist, it's just a suggested file name. |
1399 self.changeDirectoryEntry(baseDirEntry, CD_NO_HISTORY); | 1470 self.changeDirectoryEntry(baseDirEntry, CD_NO_HISTORY); |
1400 } else { | 1471 } else { |
1401 console.log('Unexpected error resolving default leaf: ' + err); | 1472 console.log('Unexpected error resolving default leaf: ' + err); |
1402 self.changeDirectoryEntry('/', CD_NO_HISTORY); | 1473 self.changeDirectoryEntry('/', CD_NO_HISTORY); |
1403 } | 1474 } |
1404 } | 1475 } |
1405 | 1476 |
1406 self.resolvePath(path, onLeafFound, onLeafError); | 1477 self.resolvePath(path, onLeafFound, onLeafError); |
1407 } | 1478 } |
1408 | 1479 |
1409 function onBaseError(err) { | 1480 function onBaseError(err) { |
1410 // Set filename first so OK button will update in changeDirectory. | 1481 // Set filename first so OK button will update in changeDirectory. |
1411 self.filenameInput_.value = leafName; | 1482 self.filenameInput_.value = leafName; |
1483 self.selectDefaultPathInFilenameInput_(); | |
1412 console.log('Unexpected error resolving default base "' + | 1484 console.log('Unexpected error resolving default base "' + |
1413 baseName + '": ' + err); | 1485 baseName + '": ' + err); |
1414 self.changeDirectory('/', CD_NO_HISTORY); | 1486 self.changeDirectory('/', CD_NO_HISTORY); |
1415 } | 1487 } |
1416 | 1488 |
1417 if (baseName) { | 1489 if (baseName) { |
1418 this.filesystem_.root.getDirectory( | 1490 this.filesystem_.root.getDirectory( |
1419 baseName, {create: false}, onBaseFound, onBaseError); | 1491 baseName, {create: false}, onBaseFound, onBaseError); |
1420 } else { | 1492 } else { |
1421 onBaseFound(this.filesystem_.root); | 1493 onBaseFound(this.filesystem_.root); |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1642 icon.className = 'detail-icon'; | 1714 icon.className = 'detail-icon'; |
1643 this.getIconType(entry); | 1715 this.getIconType(entry); |
1644 icon.setAttribute('iconType', entry.cachedIconType_); | 1716 icon.setAttribute('iconType', entry.cachedIconType_); |
1645 div.appendChild(icon); | 1717 div.appendChild(icon); |
1646 | 1718 |
1647 return div; | 1719 return div; |
1648 }; | 1720 }; |
1649 | 1721 |
1650 FileManager.prototype.getLabelForRootPath_ = function(path) { | 1722 FileManager.prototype.getLabelForRootPath_ = function(path) { |
1651 // This hack lets us localize the top level directories. | 1723 // This hack lets us localize the top level directories. |
1652 if (path == 'Downloads') | 1724 if (path == DOWNLOADS_DIRECTORY) |
1653 return str('DOWNLOADS_DIRECTORY_LABEL'); | 1725 return str('CHROMEBOOK_DIRECTORY_LABEL'); |
1654 | 1726 |
1655 if (path == 'archive') | 1727 if (path == ARCHIVE_DIRECTORY) |
1656 return str('ARCHIVE_DIRECTORY_LABEL'); | 1728 return str('ARCHIVE_DIRECTORY_LABEL'); |
1729 if (isParentPath(ARCHIVE_DIRECTORY, path)) | |
1730 return path.substring(ARCHIVE_DIRECTORY.length + 1); | |
1657 | 1731 |
1658 if (path == 'removable') | 1732 if (path == REMOVABLE_DIRECTORY) |
1659 return str('REMOVABLE_DIRECTORY_LABEL'); | 1733 return str('REMOVABLE_DIRECTORY_LABEL'); |
1734 if (isParentPath(REMOVABLE_DIRECTORY, path)) | |
1735 return path.substring(REMOVABLE_DIRECTORY.length + 1); | |
1660 | 1736 |
1661 return path || str('ROOT_DIRECTORY_LABEL'); | 1737 return path || str('ROOT_DIRECTORY_LABEL'); |
1662 }; | 1738 }; |
1663 | 1739 |
1740 FileManager.prototype.getRootIconUrl_ = function(path, opt_small) { | |
1741 var iconUrl = opt_small ? 'images/chromebook_28x28.png' : | |
1742 'images/chromebook_24x24.png'; | |
1743 if (isParentPath(REMOVABLE_DIRECTORY, path)) | |
1744 iconUrl = 'images/filetype_device.png'; | |
1745 if (isParentPath(ARCHIVE_DIRECTORY, path)) | |
1746 iconUrl = 'images/icon_mount_archive_16x16.png'; | |
1747 return chrome.extension.getURL(iconUrl); | |
1748 }; | |
1749 | |
1750 FileManager.prototype.renderRoot_ = function(entry) { | |
1751 var li = this.document_.createElement('li'); | |
1752 li.className = 'root-item'; | |
1753 | |
1754 var icon = this.document_.createElement('img'); | |
1755 icon.setAttribute('src', this.getRootIconUrl_(entry.fullPath, false)); | |
1756 li.appendChild(icon); | |
1757 | |
1758 var div = this.document_.createElement('div'); | |
1759 div.textContent = this.getLabelForRootPath_(entry.fullPath); | |
1760 li.appendChild(div); | |
1761 | |
1762 if (isParentPath(REMOVABLE_DIRECTORY, entry.fullPath) || | |
1763 isParentPath(ARCHIVE_DIRECTORY, entry.fullPath)) { | |
1764 var spacer = this.document_.createElement('div'); | |
1765 spacer.className = 'spacer'; | |
1766 li.appendChild(spacer); | |
1767 | |
1768 var eject = this.document_.createElement('img'); | |
1769 eject.className = 'root-eject'; | |
1770 eject.setAttribute('src', chrome.extension.getURL('images/eject.png')); | |
1771 eject.addEventListener('click', this.onEjectClick_.bind(this, entry)); | |
1772 li.appendChild(eject); | |
1773 } | |
1774 | |
1775 cr.defineProperty(li, 'lead', cr.PropertyKind.BOOL_ATTR); | |
1776 cr.defineProperty(li, 'selected', cr.PropertyKind.BOOL_ATTR); | |
1777 return li; | |
1778 }; | |
1779 | |
1780 /** | |
1781 * Handler for eject button clicked. | |
1782 * @param {Entry} entry Entry to eject. | |
1783 * @param {Event} event The event. | |
1784 */ | |
1785 FileManager.prototype.onEjectClick_ = function(entry, event) { | |
1786 chrome.fileBrowserPrivate.removeMount(entry.fullPath); | |
1787 }; | |
1788 | |
1664 /** | 1789 /** |
1665 * Render the Name column of the detail table. | 1790 * Render the Name column of the detail table. |
1666 * | 1791 * |
1667 * Invoked by cr.ui.Table when a file needs to be rendered. | 1792 * Invoked by cr.ui.Table when a file needs to be rendered. |
1668 * | 1793 * |
1669 * @param {Entry} entry The Entry object to render. | 1794 * @param {Entry} entry The Entry object to render. |
1670 * @param {string} columnId The id of the column to be rendered. | 1795 * @param {string} columnId The id of the column to be rendered. |
1671 * @param {cr.ui.Table} table The table doing the rendering. | 1796 * @param {cr.ui.Table} table The table doing the rendering. |
1672 */ | 1797 */ |
1673 FileManager.prototype.renderName_ = function(entry, columnId, table) { | 1798 FileManager.prototype.renderName_ = function(entry, columnId, table) { |
1674 var label = this.document_.createElement('div'); | 1799 var label = this.document_.createElement('div'); |
1675 label.entry = entry; | 1800 label.entry = entry; |
1676 label.className = 'detail-name filename-label'; | 1801 label.className = 'detail-name filename-label'; |
1677 if (this.currentDirEntry_.name == '') { | 1802 label.textContent = entry.name; |
1678 label.textContent = this.getLabelForRootPath_(entry.name); | |
1679 } else { | |
1680 label.textContent = entry.name; | |
1681 } | |
1682 | 1803 |
1683 return label; | 1804 return label; |
1684 }; | 1805 }; |
1685 | 1806 |
1686 /** | 1807 /** |
1687 * Render the Size column of the detail table. | 1808 * Render the Size column of the detail table. |
1688 * | 1809 * |
1689 * @param {Entry} entry The Entry object to render. | 1810 * @param {Entry} entry The Entry object to render. |
1690 * @param {string} columnId The id of the column to be rendered. | 1811 * @param {string} columnId The id of the column to be rendered. |
1691 * @param {cr.ui.Table} table The table doing the rendering. | 1812 * @param {cr.ui.Table} table The table doing the rendering. |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1983 // Skip the button creation. | 2104 // Skip the button creation. |
1984 if (!str('ENABLE_PHOTO_EDITOR')) continue; | 2105 if (!str('ENABLE_PHOTO_EDITOR')) continue; |
1985 this.galleryTask_ = task; | 2106 this.galleryTask_ = task; |
1986 } | 2107 } |
1987 } | 2108 } |
1988 this.renderTaskButton_(task); | 2109 this.renderTaskButton_(task); |
1989 } | 2110 } |
1990 | 2111 |
1991 // These are done in separate functions, as the checks require | 2112 // These are done in separate functions, as the checks require |
1992 // asynchronous function calls. | 2113 // asynchronous function calls. |
1993 this.maybeRenderUnmountTask_(selection); | |
1994 this.maybeRenderFormattingTask_(selection); | 2114 this.maybeRenderFormattingTask_(selection); |
1995 }; | 2115 }; |
1996 | 2116 |
1997 FileManager.prototype.renderTaskButton_ = function(task) { | 2117 FileManager.prototype.renderTaskButton_ = function(task) { |
1998 var button = this.document_.createElement('button'); | 2118 var button = this.document_.createElement('button'); |
1999 button.addEventListener('click', | 2119 button.addEventListener('click', |
2000 this.onTaskButtonClicked_.bind(this, task)); | 2120 this.onTaskButtonClicked_.bind(this, task)); |
2001 button.className = 'task-button'; | 2121 button.className = 'task-button'; |
2002 | 2122 |
2003 var img = this.document_.createElement('img'); | 2123 var img = this.document_.createElement('img'); |
2004 img.src = task.iconUrl; | 2124 img.src = task.iconUrl; |
2005 | 2125 |
2006 button.appendChild(img); | 2126 button.appendChild(img); |
2007 var label = this.document_.createElement('div'); | 2127 var label = this.document_.createElement('div'); |
2008 label.appendChild(this.document_.createTextNode(task.title)) | 2128 label.appendChild(this.document_.createTextNode(task.title)) |
2009 button.appendChild(label); | 2129 button.appendChild(label); |
2010 | 2130 |
2011 this.taskButtons_.appendChild(button); | 2131 this.taskButtons_.appendChild(button); |
2012 }; | 2132 }; |
2013 | 2133 |
2014 /** | 2134 /** |
2015 * Checks whether unmount task should be displayed and if the answer is | |
2016 * affirmative renders it. | |
2017 * @param {Object} selection Selected files object. | |
2018 */ | |
2019 FileManager.prototype.maybeRenderUnmountTask_ = function(selection) { | |
2020 for (var index = 0; index < selection.urls.length; ++index) { | |
2021 // Each url should be a mount point. | |
2022 var path = selection.entries[index].fullPath; | |
2023 var found = false; | |
2024 for (var i = 0; i < this.mountPoints_.length; i++) { | |
2025 var mountPath = this.mountPoints_[i].mountPath; | |
2026 if (mountPath[0] != '/') { | |
2027 mountPath = '/' + mountPath; | |
2028 } | |
2029 if (mountPath == path && this.mountPoints_[i].mountType == 'file') { | |
2030 found = true; | |
2031 break; | |
2032 } | |
2033 } | |
2034 if (!found) | |
2035 return; | |
2036 } | |
2037 this.renderTaskButton_({ | |
2038 taskId: this.getExtensionId_() + '|unmount-archive', | |
2039 iconUrl: | |
2040 chrome.extension.getURL('images/icon_unmount_archive_16x16.png'), | |
2041 title: str('UNMOUNT_ARCHIVE'), | |
2042 internal: true | |
2043 }); | |
2044 }; | |
2045 | |
2046 /** | |
2047 * Checks whether formatting task should be displayed and if the answer is | 2135 * Checks whether formatting task should be displayed and if the answer is |
2048 * affirmative renders it. Includes asynchronous calls, so it's splitted into | 2136 * affirmative renders it. Includes asynchronous calls, so it's splitted into |
2049 * three parts. | 2137 * three parts. |
2050 * @param {Object} selection Selected files object. | 2138 * @param {Object} selection Selected files object. |
2051 */ | 2139 */ |
2052 FileManager.prototype.maybeRenderFormattingTask_ = function(selection) { | 2140 FileManager.prototype.maybeRenderFormattingTask_ = function(selection) { |
2053 // Not to make unnecessary getMountPoints() call we doublecheck if there is | 2141 // Not to make unnecessary getMountPoints() call we doublecheck if there is |
2054 // only one selected entry. | 2142 // only one selected entry. |
2055 if (selection.entries.length != 1) | 2143 if (selection.entries.length != 1) |
2056 return; | 2144 return; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2116 } | 2204 } |
2117 chrome.fileBrowserPrivate.executeTask(task.taskId, urls); | 2205 chrome.fileBrowserPrivate.executeTask(task.taskId, urls); |
2118 }; | 2206 }; |
2119 | 2207 |
2120 /** | 2208 /** |
2121 * Event handler called when some volume was mounted or unmouted. | 2209 * Event handler called when some volume was mounted or unmouted. |
2122 */ | 2210 */ |
2123 FileManager.prototype.onMountCompleted_ = function(event) { | 2211 FileManager.prototype.onMountCompleted_ = function(event) { |
2124 var self = this; | 2212 var self = this; |
2125 chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) { | 2213 chrome.fileBrowserPrivate.getMountPoints(function(mountPoints) { |
2214 // TODO(dgozman): update rootsList in sidebar. | |
2126 self.mountPoints_ = mountPoints; | 2215 self.mountPoints_ = mountPoints; |
2127 if (event.eventType == 'mount') { | 2216 if (event.eventType == 'mount') { |
2128 for (var index = 0; index < self.mountRequests_.length; ++index) { | 2217 for (var index = 0; index < self.mountRequests_.length; ++index) { |
2129 if (self.mountRequests_[index] == event.sourceUrl) { | 2218 if (self.mountRequests_[index] == event.sourceUrl) { |
2130 self.mountRequests_.splice(index, 1); | 2219 self.mountRequests_.splice(index, 1); |
2131 if (event.status == 'success') { | 2220 if (event.status == 'success') { |
2132 self.changeDirectory(event.mountPath); | 2221 self.updateRoots_(event.mountPath); |
2133 } else { | 2222 } else { |
2134 // Report mount error. | 2223 // Report mount error. |
2135 if (event.mountType == 'file') { | 2224 if (event.mountType == 'file') { |
2136 var fileName = event.sourceUrl.substr( | 2225 var fileName = event.sourceUrl.substr( |
2137 event.sourceUrl.lastIndexOf('/') + 1); | 2226 event.sourceUrl.lastIndexOf('/') + 1); |
2138 self.alert.show(strf('ARCHIVE_MOUNT_FAILED', fileName, | 2227 self.alert.show(strf('ARCHIVE_MOUNT_FAILED', fileName, |
2139 event.status)); | 2228 event.status)); |
2140 } | 2229 } |
2141 } | 2230 } |
2142 return; | 2231 return; |
2143 } | 2232 } |
2144 } | 2233 } |
2145 } | 2234 } |
2146 | 2235 |
2147 if (event.eventType == 'unmount' && event.status == 'success' && | 2236 if (event.eventType == 'unmount' && event.status == 'success' && |
2148 self.currentDirEntry_ && | 2237 self.currentDirEntry_ && |
2149 isParentPath(event.mountPath, self.currentDirEntry_.fullPath)) { | 2238 isParentPath(event.mountPath, self.currentDirEntry_.fullPath)) { |
2150 self.changeDirectory(getParentPath(event.mountPath)); | 2239 self.changeDirectory(getParentPath(event.mountPath)); |
2151 return; | 2240 return; |
2152 } | 2241 } |
2153 | 2242 |
2154 var rescanDirectoryNeeded = (event.status == 'success'); | 2243 var rescanDirectoryNeeded = (event.status == 'success'); |
2155 for (var i = 0; i < mountPoints.length; i++) { | 2244 for (var i = 0; i < mountPoints.length; i++) { |
2156 if (event.sourceUrl == mountPoints[i].sourceUrl && | 2245 if (event.sourceUrl == mountPoints[i].sourceUrl && |
2157 mountPoints[i].mountCondition != '') { | 2246 mountPoints[i].mountCondition != '') { |
2158 rescanDirectoryNeeded = true; | 2247 rescanDirectoryNeeded = true; |
2159 } | 2248 } |
2160 } | 2249 } |
2161 // TODO(dgozman): rescan directory, only if it contains mounted points, | |
2162 // when mounts location will be decided. | |
2163 if (rescanDirectoryNeeded) | 2250 if (rescanDirectoryNeeded) |
2164 self.rescanDirectory_(null, 300); | 2251 self.rescanDirectory_(null, 300); |
2165 }); | 2252 }); |
2166 }; | 2253 }; |
2167 | 2254 |
2168 /** | 2255 /** |
2169 * Event handler called when some internal task should be executed. | 2256 * Event handler called when some internal task should be executed. |
2170 */ | 2257 */ |
2171 FileManager.prototype.onFileTaskExecute_ = function(id, details) { | 2258 FileManager.prototype.onFileTaskExecute_ = function(id, details) { |
2172 var urls = details.urls; | 2259 var urls = details.urls; |
2173 if (id == 'preview') { | 2260 if (id == 'preview') { |
2174 g_slideshow_data = urls; | 2261 g_slideshow_data = urls; |
2175 chrome.tabs.create({url: "slideshow.html"}); | 2262 chrome.tabs.create({url: "slideshow.html"}); |
2176 } else if (id == 'play' || id == 'enqueue') { | 2263 } else if (id == 'play' || id == 'enqueue') { |
2177 chrome.fileBrowserPrivate.viewFiles(urls, id); | 2264 chrome.fileBrowserPrivate.viewFiles(urls, id); |
2178 } else if (id == 'mount-archive') { | 2265 } else if (id == 'mount-archive') { |
2179 for (var index = 0; index < urls.length; ++index) { | 2266 for (var index = 0; index < urls.length; ++index) { |
2180 this.mountRequests_.push(urls[index]); | 2267 this.mountRequests_.push(urls[index]); |
2181 chrome.fileBrowserPrivate.addMount(urls[index], 'file', {}); | 2268 chrome.fileBrowserPrivate.addMount(urls[index], 'file', {}); |
2182 } | 2269 } |
2183 } else if (id == 'unmount-archive') { | |
2184 for (var index = 0; index < urls.length; ++index) { | |
2185 chrome.fileBrowserPrivate.removeMount(urls[index]); | |
2186 } | |
2187 } else if (id == 'format-device') { | 2270 } else if (id == 'format-device') { |
2188 this.confirm.show(str('FORMATTING_WARNING'), function() { | 2271 this.confirm.show(str('FORMATTING_WARNING'), function() { |
2189 chrome.fileBrowserPrivate.formatDevice(urls[0]); | 2272 chrome.fileBrowserPrivate.formatDevice(urls[0]); |
2190 }); | 2273 }); |
2191 } else if (id == 'gallery') { | 2274 } else if (id == 'gallery') { |
2192 // Pass to gallery all possible tasks except the gallery itself. | 2275 // Pass to gallery all possible tasks except the gallery itself. |
2193 var noGallery = []; | 2276 var noGallery = []; |
2194 for (var index = 0; index < details.task.allTasks.length; index++) { | 2277 for (var index = 0; index < details.task.allTasks.length; index++) { |
2195 var task = details.task.allTasks[index]; | 2278 var task = details.task.allTasks[index]; |
2196 if (task.taskId != this.getExtensionId_() + '|gallery') { | 2279 if (task.taskId != this.getExtensionId_() + '|gallery') { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2254 self.metadataProvider_, | 2337 self.metadataProvider_, |
2255 shareActions, | 2338 shareActions, |
2256 str); | 2339 str); |
2257 }; | 2340 }; |
2258 | 2341 |
2259 galleryFrame.src = 'js/image_editor/gallery.html'; | 2342 galleryFrame.src = 'js/image_editor/gallery.html'; |
2260 this.dialogDom_.appendChild(galleryFrame); | 2343 this.dialogDom_.appendChild(galleryFrame); |
2261 galleryFrame.focus(); | 2344 galleryFrame.focus(); |
2262 }; | 2345 }; |
2263 | 2346 |
2347 FileManager.prototype.getRootForPath_ = function(path) { | |
2348 for (var index = 0; index < this.rootEntries_.length; index++) { | |
2349 if (isParentPath(this.rootEntries_[index].fullPath, path)) { | |
2350 return this.rootEntries_[index]; | |
2351 } | |
2352 } | |
2353 return null; | |
2354 }; | |
2355 | |
2264 /** | 2356 /** |
2265 * Update the breadcrumb display to reflect the current directory. | 2357 * Update the breadcrumb display to reflect the current directory. |
2266 */ | 2358 */ |
2267 FileManager.prototype.updateBreadcrumbs_ = function() { | 2359 FileManager.prototype.updateBreadcrumbs_ = function() { |
2268 var bc = this.dialogDom_.querySelector('.breadcrumbs'); | 2360 var bc = this.dialogDom_.querySelector('.breadcrumbs'); |
2269 bc.innerHTML = ''; | 2361 bc.innerHTML = ''; |
2270 | 2362 |
2271 var fullPath = this.currentDirEntry_.fullPath.replace(/\/$/, ''); | 2363 var fullPath = this.currentDirEntry_.fullPath; |
2272 var pathNames = fullPath.split('/'); | 2364 var root = this.getRootForPath_(fullPath); |
2273 var path = ''; | 2365 if (!root) { |
2366 console.error('Not root for: ' + fullPath); | |
2367 return; | |
2368 } | |
2369 | |
2370 var icon = this.document_.createElement('img'); | |
2371 icon.className = 'breadcrumb-icon'; | |
2372 icon.setAttribute('src', this.getRootIconUrl_(root.fullPath, true)); | |
2373 bc.appendChild(icon); | |
2374 | |
2375 var rootPath = root.fullPath; | |
2376 var relativePath = fullPath.substring(rootPath.length); | |
2377 var pathNames = relativePath.replace(/\/$/, '').split('/'); | |
2378 if (pathNames[0] == '') | |
2379 pathNames.splice(0, 1); | |
2380 | |
2381 // We need a first breadcrumb for root, so placing last name from | |
2382 // rootPath as first name of relativePath. | |
2383 var rootPathNames = rootPath.replace(/\/$/, '').split('/'); | |
2384 pathNames.splice(0, 0, rootPathNames[rootPathNames.length - 1]); | |
2385 rootPathNames.splice(rootPathNames.length - 1, 1); | |
2386 var path = rootPathNames.join('/') + '/'; | |
2274 | 2387 |
2275 for (var i = 0; i < pathNames.length; i++) { | 2388 for (var i = 0; i < pathNames.length; i++) { |
2276 var pathName = pathNames[i]; | 2389 var pathName = pathNames[i]; |
2277 path += pathName + '/'; | 2390 path += pathName; |
2278 | 2391 |
2279 var div = this.document_.createElement('div'); | 2392 var div = this.document_.createElement('div'); |
2280 div.className = 'breadcrumb-path'; | 2393 div.className = 'breadcrumb-path'; |
2281 if (i <= 1) { | 2394 if (i == 0) { |
2282 // i == 0: root directory itself, i == 1: the files it contains. | 2395 div.textContent = this.getLabelForRootPath_(path); |
2283 div.textContent = this.getLabelForRootPath_(pathName); | |
2284 } else { | 2396 } else { |
2285 div.textContent = pathName; | 2397 div.textContent = pathName; |
2286 } | 2398 } |
2287 | 2399 |
2400 path = path + '/'; | |
2288 div.path = path; | 2401 div.path = path; |
2289 div.addEventListener('click', this.onBreadcrumbClick_.bind(this)); | 2402 div.addEventListener('click', this.onBreadcrumbClick_.bind(this)); |
2290 | 2403 |
2291 bc.appendChild(div); | 2404 bc.appendChild(div); |
2292 | 2405 |
2293 if (i == pathNames.length - 1) { | 2406 if (i == pathNames.length - 1) { |
2294 div.classList.add('breadcrumb-last'); | 2407 div.classList.add('breadcrumb-last'); |
2295 } else { | 2408 } else { |
2296 var spacer = this.document_.createElement('div'); | 2409 var spacer = this.document_.createElement('div'); |
2297 spacer.className = 'breadcrumb-spacer'; | 2410 spacer.className = 'breadcrumb-spacer'; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2410 for (var i = 0; i < this.dataModel_.length; i++) { | 2523 for (var i = 0; i < this.dataModel_.length; i++) { |
2411 if (this.dataModel_.item(i).name == name) { | 2524 if (this.dataModel_.item(i).name == name) { |
2412 this.currentList_.selectionModel.selectedIndex = i; | 2525 this.currentList_.selectionModel.selectedIndex = i; |
2413 this.currentList_.scrollIndexIntoView(i); | 2526 this.currentList_.scrollIndexIntoView(i); |
2414 this.currentList_.focus(); | 2527 this.currentList_.focus(); |
2415 return; | 2528 return; |
2416 } | 2529 } |
2417 } | 2530 } |
2418 }; | 2531 }; |
2419 | 2532 |
2533 FileManager.prototype.updateRootsListSelection_ = function() { | |
2534 if (!this.currentDirEntry_) return; | |
2535 for (var index = 0; index < this.rootEntries_.length; index++) { | |
Vladislav Kaznacheev
2011/11/22 13:16:35
Consider having getRootPathFor_ return an index an
dgozman
2011/11/22 14:15:14
Done.
| |
2536 if (isParentPath(this.rootEntries_[index].fullPath, | |
2537 this.currentDirEntry_.fullPath)) { | |
2538 this.rootsList_.selectionModel.selectedIndex = index; | |
2539 return; | |
2540 } | |
2541 } | |
2542 this.rootsList_.selectionModel.selectedIndex = 0; | |
2543 console.error('No corresponding root for: ' + | |
2544 this.currentDirEntry_.fullPath); | |
2545 }; | |
2546 | |
2420 /** | 2547 /** |
2421 * Add the file/directory with given name to the current selection. | 2548 * Add the file/directory with given name to the current selection. |
2422 * | 2549 * |
2423 * @param {string} name The name of the entry to select. | 2550 * @param {string} name The name of the entry to select. |
2424 * @return {boolean} Whether entry exists. | 2551 * @return {boolean} Whether entry exists. |
2425 */ | 2552 */ |
2426 FileManager.prototype.addItemToSelection = function(name) { | 2553 FileManager.prototype.addItemToSelection = function(name) { |
2427 var entryExists = false; | 2554 var entryExists = false; |
2428 for (var i = 0; i < this.dataModel_.length; i++) { | 2555 for (var i = 0; i < this.dataModel_.length; i++) { |
2429 if (this.dataModel_.item(i).name == name) { | 2556 if (this.dataModel_.item(i).name == name) { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2525 FileManager.prototype.changeDirectoryEntry = function(dirEntry, | 2652 FileManager.prototype.changeDirectoryEntry = function(dirEntry, |
2526 opt_saveHistory, | 2653 opt_saveHistory, |
2527 opt_selectedEntry, | 2654 opt_selectedEntry, |
2528 opt_callback) { | 2655 opt_callback) { |
2529 if (typeof opt_saveHistory == 'undefined') { | 2656 if (typeof opt_saveHistory == 'undefined') { |
2530 opt_saveHistory = true; | 2657 opt_saveHistory = true; |
2531 } else { | 2658 } else { |
2532 opt_saveHistory = !!opt_saveHistory; | 2659 opt_saveHistory = !!opt_saveHistory; |
2533 } | 2660 } |
2534 | 2661 |
2662 if (dirEntry.fullPath == '/' || dirEntry.fullPath == DOWNLOADS_DIRECTORY || | |
2663 dirEntry.fullPath == ARCHIVE_DIRECTORY) { | |
Vladislav Kaznacheev
2011/11/22 13:16:35
Why? It would be nice to have a comment here.
dgozman
2011/11/22 14:15:14
Comment added.
| |
2664 dirEntry = this.rootEntries_[0] || dirEntry; | |
2665 } | |
2666 | |
2535 var location = '#' + encodeURI(dirEntry.fullPath); | 2667 var location = '#' + encodeURI(dirEntry.fullPath); |
2536 if (opt_saveHistory) { | 2668 if (opt_saveHistory) { |
2537 history.pushState(undefined, dirEntry.fullPath, location); | 2669 history.pushState(undefined, dirEntry.fullPath, location); |
2538 } else if (window.location.hash != location) { | 2670 } else if (window.location.hash != location) { |
2539 // If the user typed URL manually that is not canonical it would be fixed | 2671 // If the user typed URL manually that is not canonical it would be fixed |
2540 // here. However it seems history.replaceState doesn't work properly | 2672 // here. However it seems history.replaceState doesn't work properly |
2541 // with rewritable URLs (while does with history.pushState). It changes | 2673 // with rewritable URLs (while does with history.pushState). It changes |
2542 // window.location but doesn't change content of the ombibox. | 2674 // window.location but doesn't change content of the ombibox. |
2543 history.replaceState(undefined, dirEntry.fullPath, location); | 2675 history.replaceState(undefined, dirEntry.fullPath, location); |
2544 } | 2676 } |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2761 // then the default action of this click event fires and toggles the | 2893 // then the default action of this click event fires and toggles the |
2762 // checkbox back off. | 2894 // checkbox back off. |
2763 // | 2895 // |
2764 // Since we're going to force checkboxes into the correct state for any | 2896 // Since we're going to force checkboxes into the correct state for any |
2765 // multi-selection, we can prevent this shift click from toggling the | 2897 // multi-selection, we can prevent this shift click from toggling the |
2766 // checkbox and avoid the trouble. | 2898 // checkbox and avoid the trouble. |
2767 event.preventDefault(); | 2899 event.preventDefault(); |
2768 } | 2900 } |
2769 }; | 2901 }; |
2770 | 2902 |
2903 FileManager.prototype.onRootsSelectionChanged_ = function(event) { | |
2904 var root = this.rootEntries_[this.rootsList_.selectionModel.selectedIndex]; | |
2905 this.changeDirectory(root.fullPath); | |
2906 }; | |
2907 | |
2908 FileManager.prototype.selectDefaultPathInFilenameInput_ = function() { | |
2909 var input = this.filenameInput_; | |
2910 input.focus(); | |
2911 var selectionEnd = input.value.lastIndexOf('.'); | |
2912 if (selectionEnd == -1) { | |
2913 input.select(); | |
2914 } else { | |
2915 input.selectionStart = 0; | |
2916 input.selectionEnd = selectionEnd; | |
2917 } | |
2918 // Clear, so we never do this again. | |
2919 this.params_.defaultPath = ''; | |
2920 }; | |
2921 | |
2771 /** | 2922 /** |
2772 * Update the UI when the selection model changes. | 2923 * Update the UI when the selection model changes. |
2773 * | 2924 * |
2774 * @param {cr.Event} event The change event. | 2925 * @param {cr.Event} event The change event. |
2775 */ | 2926 */ |
2776 FileManager.prototype.onSelectionChanged_ = function(event) { | 2927 FileManager.prototype.onSelectionChanged_ = function(event) { |
2777 this.summarizeSelection_(); | 2928 this.summarizeSelection_(); |
2778 | 2929 |
2779 if (this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) { | 2930 if (this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) { |
2780 // If this is a save-as dialog, copy the selected file into the filename | 2931 // If this is a save-as dialog, copy the selected file into the filename |
2781 // input text box. | 2932 // input text box. |
2782 | 2933 |
2783 if (this.selection && | 2934 if (this.selection && |
2784 this.selection.totalCount == 1 && | 2935 this.selection.totalCount == 1 && |
2785 this.selection.entries[0].isFile) | 2936 this.selection.entries[0].isFile && |
2937 this.filenameInput_.value != this.selection.entries[0].name) { | |
2786 this.filenameInput_.value = this.selection.entries[0].name; | 2938 this.filenameInput_.value = this.selection.entries[0].name; |
2939 if (this.params_.defaultPath == this.selection.entries[0].fullPath) | |
2940 this.selectDefaultPathInFilenameInput_(); | |
2941 } | |
2787 } | 2942 } |
2788 | 2943 |
2789 this.updateOkButton_(); | 2944 this.updateOkButton_(); |
2790 | 2945 |
2791 var self = this; | 2946 var self = this; |
2792 setTimeout(function() { self.onSelectionChangeComplete_(event) }, 0); | 2947 setTimeout(function() { self.onSelectionChangeComplete_(event) }, 0); |
2793 }; | 2948 }; |
2794 | 2949 |
2795 /** | 2950 /** |
2796 * Handle selection change related tasks that won't run properly during | 2951 * Handle selection change related tasks that won't run properly during |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2925 * Update the UI when the current directory changes. | 3080 * Update the UI when the current directory changes. |
2926 * | 3081 * |
2927 * @param {cr.Event} event The directory-changed event. | 3082 * @param {cr.Event} event The directory-changed event. |
2928 */ | 3083 */ |
2929 FileManager.prototype.onDirectoryChanged_ = function(event) { | 3084 FileManager.prototype.onDirectoryChanged_ = function(event) { |
2930 this.updateCommands_(); | 3085 this.updateCommands_(); |
2931 this.updateOkButton_(); | 3086 this.updateOkButton_(); |
2932 | 3087 |
2933 this.checkFreeSpace_(this.currentDirEntry_.fullPath); | 3088 this.checkFreeSpace_(this.currentDirEntry_.fullPath); |
2934 | 3089 |
2935 // New folder should never be enabled in the root or media/ directories. | 3090 // TODO(dgozman): title may be better than this. |
2936 this.newFolderButton_.disabled = isSystemDirEntry(this.currentDirEntry_); | |
2937 | |
2938 this.document_.title = this.currentDirEntry_.fullPath; | 3091 this.document_.title = this.currentDirEntry_.fullPath; |
2939 | 3092 |
2940 var self = this; | 3093 var self = this; |
2941 | 3094 |
2942 if (this.subscribedOnDirectoryChanges_) { | 3095 if (this.subscribedOnDirectoryChanges_) { |
2943 chrome.fileBrowserPrivate.removeFileWatch(event.previousDirEntry.toURL(), | 3096 chrome.fileBrowserPrivate.removeFileWatch(event.previousDirEntry.toURL(), |
2944 function(result) { | 3097 function(result) { |
2945 if (!result) { | 3098 if (!result) { |
2946 console.log('Failed to remove file watch'); | 3099 console.log('Failed to remove file watch'); |
2947 } | 3100 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3023 // Updated when a user clicks on the label of a file, used to detect | 3176 // Updated when a user clicks on the label of a file, used to detect |
3024 // when a click is eligible to trigger a rename. Can be null, or | 3177 // when a click is eligible to trigger a rename. Can be null, or |
3025 // an object with 'path' and 'date' properties. | 3178 // an object with 'path' and 'date' properties. |
3026 this.lastLabelClick_ = null; | 3179 this.lastLabelClick_ = null; |
3027 | 3180 |
3028 // Clear the table first. | 3181 // Clear the table first. |
3029 this.dataModel_.splice(0, this.dataModel_.length); | 3182 this.dataModel_.splice(0, this.dataModel_.length); |
3030 this.currentList_.selectionModel.clear(); | 3183 this.currentList_.selectionModel.clear(); |
3031 | 3184 |
3032 this.updateBreadcrumbs_(); | 3185 this.updateBreadcrumbs_(); |
3186 this.updateRootsListSelection_(); | |
3033 | 3187 |
3034 if (this.currentDirEntry_.fullPath != '/') { | 3188 if (this.currentDirEntry_.fullPath != '/') { |
3035 // Add current request to pending result list | 3189 // Add current request to pending result list |
3036 this.pendingRescanQueue_.push({ | 3190 this.pendingRescanQueue_.push({ |
3037 onSuccess:opt_callback, | 3191 onSuccess:opt_callback, |
3038 onError:opt_onError | 3192 onError:opt_onError |
3039 }); | 3193 }); |
3040 | 3194 |
3041 if (this.rescanRunning_) | 3195 if (this.rescanRunning_) |
3042 return; | 3196 return; |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3358 var selectionEnd = input.value.lastIndexOf('.'); | 3512 var selectionEnd = input.value.lastIndexOf('.'); |
3359 if (selectionEnd == -1) { | 3513 if (selectionEnd == -1) { |
3360 input.select(); | 3514 input.select(); |
3361 } else { | 3515 } else { |
3362 input.selectionStart = 0; | 3516 input.selectionStart = 0; |
3363 input.selectionEnd = selectionEnd; | 3517 input.selectionEnd = selectionEnd; |
3364 } | 3518 } |
3365 }, 0); | 3519 }, 0); |
3366 }; | 3520 }; |
3367 | 3521 |
3368 FileManager.prototype.onNewFolderButtonClick_ = function(event) { | 3522 FileManager.prototype.onToggleSidebar_ = function(event) { |
3523 if (this.dialogContainer_.hasAttribute('sidebar')) { | |
3524 this.dialogContainer_.removeAttribute('sidebar'); | |
3525 } else { | |
3526 this.dialogContainer_.setAttribute('sidebar', 'sidebar'); | |
3527 } | |
3528 setTimeout(this.onResize_.bind(this), 300); | |
3529 }; | |
3530 | |
3531 FileManager.prototype.onNewFolderCommand_ = function(event) { | |
3369 var self = this; | 3532 var self = this; |
3370 | 3533 |
3371 function onNameSelected(name) { | 3534 function onNameSelected(name) { |
3372 var valid = self.validateFileName_(name, function() { | 3535 var valid = self.validateFileName_(name, function() { |
3373 promptForName(name); | 3536 promptForName(name); |
3374 }); | 3537 }); |
3375 | 3538 |
3376 if (!valid) { | 3539 if (!valid) { |
3377 // Validation failed. User will be prompted for a new name after they | 3540 // Validation failed. User will be prompted for a new name after they |
3378 // dismiss the validation error dialog. | 3541 // dismiss the validation error dialog. |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3487 this.dialogType_ != FileManager.SELECT_FOLDER) { | 3650 this.dialogType_ != FileManager.SELECT_FOLDER) { |
3488 event.preventDefault(); | 3651 event.preventDefault(); |
3489 this.onDirectoryAction(this.selection.entries[0]); | 3652 this.onDirectoryAction(this.selection.entries[0]); |
3490 } else if (!this.okButton_.disabled) { | 3653 } else if (!this.okButton_.disabled) { |
3491 event.preventDefault(); | 3654 event.preventDefault(); |
3492 this.onOk_(); | 3655 this.onOk_(); |
3493 } | 3656 } |
3494 break; | 3657 break; |
3495 | 3658 |
3496 case 32: // Ctrl-Space => New Folder. | 3659 case 32: // Ctrl-Space => New Folder. |
3497 if (this.newFolderButton_.style.display != 'none' && event.ctrlKey) { | 3660 if ((this.dialogType_ == 'saveas-file' || |
3661 this.dialogType_ == 'full-page') && event.ctrlKey) { | |
3498 event.preventDefault(); | 3662 event.preventDefault(); |
3499 this.onNewFolderButtonClick_(); | 3663 this.onNewFolderCommand_(); |
3500 } | 3664 } |
3501 break; | 3665 break; |
3502 | 3666 |
3503 case 88: // Ctrl-X => Cut. | 3667 case 88: // Ctrl-X => Cut. |
3504 this.updateCommands_(); | 3668 this.updateCommands_(); |
3505 if (!this.commands_['cut'].disabled) { | 3669 if (!this.commands_['cut'].disabled) { |
3506 event.preventDefault(); | 3670 event.preventDefault(); |
3507 this.commands_['cut'].execute(); | 3671 this.commands_['cut'].execute(); |
3508 } | 3672 } |
3509 break; | 3673 break; |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3793 }); | 3957 }); |
3794 }, onError); | 3958 }, onError); |
3795 | 3959 |
3796 function onError(err) { | 3960 function onError(err) { |
3797 console.log('Error while checking free space: ' + err); | 3961 console.log('Error while checking free space: ' + err); |
3798 setTimeout(doCheck, 1000 * 60); | 3962 setTimeout(doCheck, 1000 * 60); |
3799 } | 3963 } |
3800 } | 3964 } |
3801 } | 3965 } |
3802 })(); | 3966 })(); |
OLD | NEW |