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

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

Issue 12857002: Files.app: Add subfolders in the left nav (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: addressed comments Created 7 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 // This variable is checked in SelectFileDialogExtensionBrowserTest. 5 // This variable is checked in SelectFileDialogExtensionBrowserTest.
6 var JSErrorCount = 0; 6 var JSErrorCount = 0;
7 7
8 /** 8 /**
9 * Count uncaught exceptions. 9 * Count uncaught exceptions.
10 */ 10 */
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 this.onCopyManagerOperationComplete_.bind(this)); 510 this.onCopyManagerOperationComplete_.bind(this));
511 511
512 var controller = this.fileTransferController_ = 512 var controller = this.fileTransferController_ =
513 new FileTransferController(this.document_, 513 new FileTransferController(this.document_,
514 this.copyManager_, 514 this.copyManager_,
515 this.directoryModel_); 515 this.directoryModel_);
516 controller.attachDragSource(this.table_.list); 516 controller.attachDragSource(this.table_.list);
517 controller.attachDropTarget(this.table_.list); 517 controller.attachDropTarget(this.table_.list);
518 controller.attachDragSource(this.grid_); 518 controller.attachDragSource(this.grid_);
519 controller.attachDropTarget(this.grid_); 519 controller.attachDropTarget(this.grid_);
520 controller.attachDropTarget(this.rootsList_, true); 520 controller.attachDropTarget(this.directoryTree_,
521 true /* onlyIntoDirectories */);
521 controller.attachBreadcrumbsDropTarget(this.breadcrumbs_); 522 controller.attachBreadcrumbsDropTarget(this.breadcrumbs_);
522 controller.attachCopyPasteHandlers(); 523 controller.attachCopyPasteHandlers();
523 controller.addEventListener('selection-copied', 524 controller.addEventListener('selection-copied',
524 this.blinkSelection.bind(this)); 525 this.blinkSelection.bind(this));
525 controller.addEventListener('selection-cut', 526 controller.addEventListener('selection-cut',
526 this.blinkSelection.bind(this)); 527 this.blinkSelection.bind(this));
527 }; 528 };
528 529
529 /** 530 /**
530 * One-time initialization of context menus. 531 * One-time initialization of context menus.
531 */ 532 */
532 FileManager.prototype.initContextMenus_ = function() { 533 FileManager.prototype.initContextMenus_ = function() {
533 this.fileContextMenu_ = this.dialogDom_.querySelector('#file-context-menu'); 534 this.fileContextMenu_ = this.dialogDom_.querySelector('#file-context-menu');
534 cr.ui.Menu.decorate(this.fileContextMenu_); 535 cr.ui.Menu.decorate(this.fileContextMenu_);
535 536
536 cr.ui.contextMenuHandler.setContextMenu(this.grid_, this.fileContextMenu_); 537 cr.ui.contextMenuHandler.setContextMenu(this.grid_, this.fileContextMenu_);
537 cr.ui.contextMenuHandler.setContextMenu(this.table_.querySelector('.list'), 538 cr.ui.contextMenuHandler.setContextMenu(this.table_.querySelector('.list'),
538 this.fileContextMenu_); 539 this.fileContextMenu_);
539 cr.ui.contextMenuHandler.setContextMenu( 540 cr.ui.contextMenuHandler.setContextMenu(
540 this.document_.querySelector('.drive-welcome.page'), 541 this.document_.querySelector('.drive-welcome.page'),
541 this.fileContextMenu_); 542 this.fileContextMenu_);
542 543
543 this.rootsContextMenu_ = 544 this.rootsContextMenu_ =
544 this.dialogDom_.querySelector('#roots-context-menu'); 545 this.dialogDom_.querySelector('#roots-context-menu');
545 cr.ui.Menu.decorate(this.rootsContextMenu_); 546 cr.ui.Menu.decorate(this.rootsContextMenu_);
546 547
548 this.directoryTree_.setContextMenu(this.rootsContextMenu_);
549
547 this.textContextMenu_ = 550 this.textContextMenu_ =
548 this.dialogDom_.querySelector('#text-context-menu'); 551 this.dialogDom_.querySelector('#text-context-menu');
549 cr.ui.Menu.decorate(this.textContextMenu_); 552 cr.ui.Menu.decorate(this.textContextMenu_);
550 553
551 this.gearButton_ = this.dialogDom_.querySelector('#gear-button'); 554 this.gearButton_ = this.dialogDom_.querySelector('#gear-button');
552 this.gearButton_.addEventListener('menushow', 555 this.gearButton_.addEventListener('menushow',
553 this.refreshRemainingSpace_.bind(this, 556 this.refreshRemainingSpace_.bind(this,
554 false /* Without loading caption. */)); 557 false /* Without loading caption. */));
555 cr.ui.decorate(this.gearButton_, cr.ui.MenuButton); 558 cr.ui.decorate(this.gearButton_, cr.ui.MenuButton);
556 559
(...skipping 20 matching lines...) Expand all
577 cr.ui.Command.decorate(commands[i]); 580 cr.ui.Command.decorate(commands[i]);
578 581
579 var doc = this.document_; 582 var doc = this.document_;
580 583
581 CommandUtil.registerCommand(doc, 'newfolder', 584 CommandUtil.registerCommand(doc, 'newfolder',
582 Commands.newFolderCommand, this, this.directoryModel_); 585 Commands.newFolderCommand, this, this.directoryModel_);
583 586
584 CommandUtil.registerCommand(doc, 'newwindow', 587 CommandUtil.registerCommand(doc, 'newwindow',
585 Commands.newWindowCommand, this); 588 Commands.newWindowCommand, this);
586 589
587 CommandUtil.registerCommand(this.rootsList_, 'unmount', 590 CommandUtil.registerCommand(this.directoryTree_, 'unmount',
588 Commands.unmountCommand, this.rootsList_, this); 591 Commands.unmountCommand, this.directoryTree_, this);
589 592
590 CommandUtil.registerCommand(doc, 'format', 593 CommandUtil.registerCommand(doc, 'format',
591 Commands.formatCommand, this.rootsList_, this, this.directoryModel_); 594 Commands.formatCommand, this.directoryTree_, this,
595 this.directoryModel_);
592 596
593 CommandUtil.registerCommand(this.rootsList_, 'import-photos', 597 CommandUtil.registerCommand(this.directoryTree_, 'import-photos',
594 Commands.importCommand, this.rootsList_); 598 Commands.importCommand, this.directoryTree_);
595 599
596 CommandUtil.registerCommand(doc, 'delete', 600 CommandUtil.registerCommand(doc, 'delete',
597 Commands.deleteFileCommand, this); 601 Commands.deleteFileCommand, this);
598 602
599 CommandUtil.registerCommand(doc, 'rename', 603 CommandUtil.registerCommand(doc, 'rename',
600 Commands.renameFileCommand, this); 604 Commands.renameFileCommand, this);
601 605
602 CommandUtil.registerCommand(doc, 'volume-help', 606 CommandUtil.registerCommand(doc, 'volume-help',
603 Commands.volumeHelpCommand, this); 607 Commands.volumeHelpCommand, this);
604 608
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
902 906
903 var fileListFocusBound = this.onFileListFocus_.bind(this); 907 var fileListFocusBound = this.onFileListFocus_.bind(this);
904 var fileListBlurBound = this.onFileListBlur_.bind(this); 908 var fileListBlurBound = this.onFileListBlur_.bind(this);
905 909
906 this.table_.list.addEventListener('focus', fileListFocusBound); 910 this.table_.list.addEventListener('focus', fileListFocusBound);
907 this.grid_.addEventListener('focus', fileListFocusBound); 911 this.grid_.addEventListener('focus', fileListFocusBound);
908 912
909 this.table_.list.addEventListener('blur', fileListBlurBound); 913 this.table_.list.addEventListener('blur', fileListBlurBound);
910 this.grid_.addEventListener('blur', fileListBlurBound); 914 this.grid_.addEventListener('blur', fileListBlurBound);
911 915
912 this.initRootsList_(); 916 this.initSidebar_();
913 917
914 this.table_.addEventListener('column-resize-end', 918 this.table_.addEventListener('column-resize-end',
915 this.updateStartupPrefs_.bind(this)); 919 this.updateStartupPrefs_.bind(this));
916 920
917 this.setListType(prefs.listType || FileManager.ListType.DETAIL); 921 this.setListType(prefs.listType || FileManager.ListType.DETAIL);
918 922
919 if (prefs.columns) { 923 if (prefs.columns) {
920 var cm = this.table_.columnModel; 924 var cm = this.table_.columnModel;
921 for (var i = 0; i < cm.totalSize; i++) { 925 for (var i = 0; i < cm.totalSize; i++) {
922 if (prefs.columns[i] > 0) 926 if (prefs.columns[i] > 0)
(...skipping 12 matching lines...) Expand all
935 // Update metadata to change 'Today' and 'Yesterday' dates. 939 // Update metadata to change 'Today' and 'Yesterday' dates.
936 var today = new Date(); 940 var today = new Date();
937 today.setHours(0); 941 today.setHours(0);
938 today.setMinutes(0); 942 today.setMinutes(0);
939 today.setSeconds(0); 943 today.setSeconds(0);
940 today.setMilliseconds(0); 944 today.setMilliseconds(0);
941 setTimeout(this.dailyUpdateModificationTime_.bind(this), 945 setTimeout(this.dailyUpdateModificationTime_.bind(this),
942 today.getTime() + MILLISECONDS_IN_DAY - Date.now() + 1000); 946 today.getTime() + MILLISECONDS_IN_DAY - Date.now() + 1000);
943 }; 947 };
944 948
945 FileManager.prototype.initRootsList_ = function() { 949 FileManager.prototype.initSidebar_ = function() {
946 this.rootsList_ = this.dialogDom_.querySelector('#roots-list'); 950 this.directoryTree_ = this.dialogDom_.querySelector('#directory-tree');
947 cr.ui.List.decorate(this.rootsList_); 951 DirectoryTree.decorate(this.directoryTree_, this.directoryModel_);
948 952
949 // Overriding default role 'list' set by cr.ui.List.decorate() to 'listbox' 953 this.directoryTree_.addEventListener('change', function() {
950 // role for better accessibility on ChromeOS. 954 var currentPath = this.directoryTree_.getCurrentPath() ||
951 this.rootsList_.setAttribute('role', 'listbox'); 955 this.directoryModel_.getDefaultDirectory();
952 956 this.directoryModel_.changeDirectory(currentPath);
953 var self = this; 957 }.bind(this));
954 this.rootsList_.itemConstructor = function(entry) {
955 return self.renderRoot_(entry.fullPath);
956 };
957
958 this.rootsList_.selectionModel =
959 this.directoryModel_.getRootsListSelectionModel();
960
961 // TODO(dgozman): add "Add a drive" item.
962 this.rootsList_.dataModel = this.directoryModel_.getRootsList();
963 }; 958 };
964 959
965 FileManager.prototype.updateStartupPrefs_ = function() { 960 FileManager.prototype.updateStartupPrefs_ = function() {
966 var sortStatus = this.directoryModel_.getFileList().sortStatus; 961 var sortStatus = this.directoryModel_.getFileList().sortStatus;
967 var prefs = { 962 var prefs = {
968 sortField: sortStatus.field, 963 sortField: sortStatus.field,
969 sortDirection: sortStatus.direction, 964 sortDirection: sortStatus.direction,
970 columns: [] 965 columns: []
971 }; 966 };
972 var cm = this.table_.columnModel; 967 var cm = this.table_.columnModel;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 */ 1016 */
1022 FileManager.prototype.getSelectedFilterIndex_ = function() { 1017 FileManager.prototype.getSelectedFilterIndex_ = function() {
1023 var index = Number(this.fileTypeSelector_.selectedIndex); 1018 var index = Number(this.fileTypeSelector_.selectedIndex);
1024 if (index < 0) // Nothing selected. 1019 if (index < 0) // Nothing selected.
1025 return 0; 1020 return 0;
1026 if (this.params_.includeAllFiles) // Already 1-based. 1021 if (this.params_.includeAllFiles) // Already 1-based.
1027 return index; 1022 return index;
1028 return index + 1; // Convert to 1-based; 1023 return index + 1; // Convert to 1-based;
1029 }; 1024 };
1030 1025
1031 FileManager.prototype.getRootEntry_ = function(index) {
1032 if (index == -1)
1033 return null;
1034
1035 return this.rootsList_.dataModel.item(index);
1036 };
1037
1038 FileManager.prototype.setListType = function(type) { 1026 FileManager.prototype.setListType = function(type) {
1039 if (type && type == this.listType_) 1027 if (type && type == this.listType_)
1040 return; 1028 return;
1041 1029
1042 this.table_.list.startBatchUpdates(); 1030 this.table_.list.startBatchUpdates();
1043 this.grid_.startBatchUpdates(); 1031 this.grid_.startBatchUpdates();
1044 1032
1045 // TODO(dzvorygin): style.display and dataModel setting order shouldn't 1033 // TODO(dzvorygin): style.display and dataModel setting order shouldn't
1046 // cause any UI bugs. Currently, the only right way is first to set display 1034 // cause any UI bugs. Currently, the only right way is first to set display
1047 // style and only then set dataModel. 1035 // style and only then set dataModel.
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1235 g.startBatchUpdates(); 1223 g.startBatchUpdates();
1236 setTimeout(function() { 1224 setTimeout(function() {
1237 g.columns = 0; 1225 g.columns = 0;
1238 g.redraw(); 1226 g.redraw();
1239 g.endBatchUpdates(); 1227 g.endBatchUpdates();
1240 }, 0); 1228 }, 0);
1241 } else { 1229 } else {
1242 this.table_.redraw(); 1230 this.table_.redraw();
1243 } 1231 }
1244 1232
1245 this.rootsList_.redraw();
1246 this.breadcrumbs_.truncate(); 1233 this.breadcrumbs_.truncate();
1247 this.searchBreadcrumbs_.truncate(); 1234 this.searchBreadcrumbs_.truncate();
1248 1235
1249 this.updateWindowState_(); 1236 this.updateWindowState_();
1250 }; 1237 };
1251 1238
1252 FileManager.prototype.updateWindowState_ = function() { 1239 FileManager.prototype.updateWindowState_ = function() {
1253 util.platform.getWindowStatus(function(wnd) { 1240 util.platform.getWindowStatus(function(wnd) {
1254 if (wnd.state == 'maximized') { 1241 if (wnd.state == 'maximized') {
1255 this.dialogDom_.setAttribute('maximized', 'maximized'); 1242 this.dialogDom_.setAttribute('maximized', 'maximized');
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1452 } 1439 }
1453 1440
1454 this.okButton_.textContent = okLabel; 1441 this.okButton_.textContent = okLabel;
1455 1442
1456 var dialogTitle = this.params_.title || defaultTitle; 1443 var dialogTitle = this.params_.title || defaultTitle;
1457 this.dialogDom_.querySelector('.dialog-title').textContent = dialogTitle; 1444 this.dialogDom_.querySelector('.dialog-title').textContent = dialogTitle;
1458 1445
1459 this.dialogDom_.setAttribute('type', this.dialogType); 1446 this.dialogDom_.setAttribute('type', this.dialogType);
1460 }; 1447 };
1461 1448
1462 FileManager.prototype.renderRoot_ = function(path) {
1463 var li = this.document_.createElement('li');
1464 li.className = 'root-item';
1465 li.setAttribute('role', 'option');
1466 var dm = this.directoryModel_;
1467 var handleClick = function() {
1468 if (li.selected && path !== dm.getCurrentDirPath()) {
1469 dm.changeDirectory(path);
1470 }
1471 };
1472 li.addEventListener('mousedown', handleClick);
1473 li.addEventListener(cr.ui.TouchHandler.EventType.TOUCH_START, handleClick);
1474
1475 var rootType = PathUtil.getRootType(path);
1476
1477 var iconDiv = this.document_.createElement('div');
1478 iconDiv.className = 'volume-icon';
1479 iconDiv.setAttribute('volume-type-icon', rootType);
1480 if (rootType === RootType.REMOVABLE) {
1481 iconDiv.setAttribute('volume-subtype',
1482 this.volumeManager_.getDeviceType(path));
1483 }
1484 li.appendChild(iconDiv);
1485
1486 var div = this.document_.createElement('div');
1487 div.className = 'root-label';
1488
1489 div.textContent = PathUtil.getRootLabel(path);
1490 li.appendChild(div);
1491
1492 if (rootType === RootType.ARCHIVE || rootType === RootType.REMOVABLE) {
1493 var eject = this.document_.createElement('div');
1494 eject.className = 'root-eject';
1495 eject.addEventListener('click', function(event) {
1496 event.stopPropagation();
1497 var unmountCommand = this.dialogDom_.querySelector('command#unmount');
1498 // Let's make sure 'canExecute' state of the command is properly set for
1499 // the root before executing it.
1500 unmountCommand.canExecuteChange(li);
1501 unmountCommand.execute(li);
1502 }.bind(this));
1503 // Block other mouse handlers.
1504 eject.addEventListener('mouseup', function(e) { e.stopPropagation() });
1505 eject.addEventListener('mousedown', function(e) { e.stopPropagation() });
1506 li.appendChild(eject);
1507 }
1508
1509 if (rootType != RootType.DRIVE && rootType != RootType.DOWNLOADS)
1510 cr.ui.contextMenuHandler.setContextMenu(li, this.rootsContextMenu_);
1511
1512 cr.defineProperty(li, 'lead', cr.PropertyKind.BOOL_ATTR);
1513 cr.defineProperty(li, 'selected', cr.PropertyKind.BOOL_ATTR);
1514
1515 return li;
1516 };
1517
1518 /** 1449 /**
1519 * Unmounts device. 1450 * Unmounts device.
1520 * @param {string} path Path to a volume to unmount. 1451 * @param {string} path Path to a volume to unmount.
1521 */ 1452 */
1522 FileManager.prototype.unmountVolume = function(path) { 1453 FileManager.prototype.unmountVolume = function(path) {
1523 var listItem = this.rootsList_.getListItemByIndex(
1524 this.directoryModel_.findRootsListIndex(path));
1525 if (listItem)
1526 listItem.setAttribute('disabled', '');
1527 var onError = function(error) { 1454 var onError = function(error) {
1528 if (listItem)
1529 listItem.removeAttribute('disabled');
1530 this.alert.showHtml('', str('UNMOUNT_FAILED')); 1455 this.alert.showHtml('', str('UNMOUNT_FAILED'));
1531 }; 1456 };
1532 this.volumeManager_.unmount(path, function() {}, onError.bind(this)); 1457 this.volumeManager_.unmount(path, function() {}, onError.bind(this));
1533 }; 1458 };
1534 1459
1535 FileManager.prototype.refreshCurrentDirectoryMetadata_ = function() { 1460 FileManager.prototype.refreshCurrentDirectoryMetadata_ = function() {
1536 var entries = this.directoryModel_.getFileList().slice(); 1461 var entries = this.directoryModel_.getFileList().slice();
1537 var directoryEntry = this.directoryModel_.getCurrentDirEntry(); 1462 var directoryEntry = this.directoryModel_.getCurrentDirEntry();
1538 // We don't pass callback here. When new metadata arrives, we have an 1463 // We don't pass callback here. When new metadata arrives, we have an
1539 // observer registered to update the UI. 1464 // observer registered to update the UI.
(...skipping 1618 matching lines...) Expand 10 before | Expand all | Expand 10 after
3158 callback(this.preferences_); 3083 callback(this.preferences_);
3159 return; 3084 return;
3160 } 3085 }
3161 3086
3162 chrome.fileBrowserPrivate.getPreferences(function(prefs) { 3087 chrome.fileBrowserPrivate.getPreferences(function(prefs) {
3163 this.preferences_ = prefs; 3088 this.preferences_ = prefs;
3164 callback(prefs); 3089 callback(prefs);
3165 }.bind(this)); 3090 }.bind(this));
3166 }; 3091 };
3167 })(); 3092 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698