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

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) 2013 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 */
11 window.onerror = function() { JSErrorCount++ }; 11 window.onerror = function() { JSErrorCount++ };
(...skipping 498 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_, true);
mtomasz 2013/03/14 10:15:39 nit: Please add comment what is that 'true' argume
yoshiki 2013/03/14 13:43:42 Done.
521 controller.attachBreadcrumbsDropTarget(this.breadcrumbs_); 521 controller.attachBreadcrumbsDropTarget(this.breadcrumbs_);
522 controller.attachCopyPasteHandlers(); 522 controller.attachCopyPasteHandlers();
523 controller.addEventListener('selection-copied', 523 controller.addEventListener('selection-copied',
524 this.blinkSelection.bind(this)); 524 this.blinkSelection.bind(this));
525 controller.addEventListener('selection-cut', 525 controller.addEventListener('selection-cut',
526 this.blinkSelection.bind(this)); 526 this.blinkSelection.bind(this));
527 }; 527 };
528 528
529 /** 529 /**
530 * One-time initialization of context menus. 530 * One-time initialization of context menus.
531 */ 531 */
532 FileManager.prototype.initContextMenus_ = function() { 532 FileManager.prototype.initContextMenus_ = function() {
533 this.fileContextMenu_ = this.dialogDom_.querySelector('#file-context-menu'); 533 this.fileContextMenu_ = this.dialogDom_.querySelector('#file-context-menu');
534 cr.ui.Menu.decorate(this.fileContextMenu_); 534 cr.ui.Menu.decorate(this.fileContextMenu_);
535 535
536 cr.ui.contextMenuHandler.setContextMenu(this.grid_, this.fileContextMenu_); 536 cr.ui.contextMenuHandler.setContextMenu(this.grid_, this.fileContextMenu_);
537 cr.ui.contextMenuHandler.setContextMenu(this.table_.querySelector('.list'), 537 cr.ui.contextMenuHandler.setContextMenu(this.table_.querySelector('.list'),
538 this.fileContextMenu_); 538 this.fileContextMenu_);
539 cr.ui.contextMenuHandler.setContextMenu( 539 cr.ui.contextMenuHandler.setContextMenu(
540 this.document_.querySelector('.drive-welcome.page'), 540 this.document_.querySelector('.drive-welcome.page'),
541 this.fileContextMenu_); 541 this.fileContextMenu_);
542 542
543 this.rootsContextMenu_ = 543 this.rootsContextMenu_ =
544 this.dialogDom_.querySelector('#roots-context-menu'); 544 this.dialogDom_.querySelector('#roots-context-menu');
545 cr.ui.Menu.decorate(this.rootsContextMenu_); 545 cr.ui.Menu.decorate(this.rootsContextMenu_);
546 546
547 this.directoryTree_.setContextMenu(this.rootsContextMenu_);
548
547 this.textContextMenu_ = 549 this.textContextMenu_ =
548 this.dialogDom_.querySelector('#text-context-menu'); 550 this.dialogDom_.querySelector('#text-context-menu');
549 cr.ui.Menu.decorate(this.textContextMenu_); 551 cr.ui.Menu.decorate(this.textContextMenu_);
550 552
551 this.gearButton_ = this.dialogDom_.querySelector('#gear-button'); 553 this.gearButton_ = this.dialogDom_.querySelector('#gear-button');
552 this.gearButton_.addEventListener('menushow', 554 this.gearButton_.addEventListener('menushow',
553 this.refreshRemainingSpace_.bind(this, 555 this.refreshRemainingSpace_.bind(this,
554 false /* Without loading caption. */)); 556 false /* Without loading caption. */));
555 cr.ui.decorate(this.gearButton_, cr.ui.MenuButton); 557 cr.ui.decorate(this.gearButton_, cr.ui.MenuButton);
556 558
(...skipping 20 matching lines...) Expand all
577 cr.ui.Command.decorate(commands[i]); 579 cr.ui.Command.decorate(commands[i]);
578 580
579 var doc = this.document_; 581 var doc = this.document_;
580 582
581 CommandUtil.registerCommand(doc, 'newfolder', 583 CommandUtil.registerCommand(doc, 'newfolder',
582 Commands.newFolderCommand, this, this.directoryModel_); 584 Commands.newFolderCommand, this, this.directoryModel_);
583 585
584 CommandUtil.registerCommand(doc, 'newwindow', 586 CommandUtil.registerCommand(doc, 'newwindow',
585 Commands.newWindowCommand, this); 587 Commands.newWindowCommand, this);
586 588
587 CommandUtil.registerCommand(this.rootsList_, 'unmount', 589 CommandUtil.registerCommand(this.directoryTree_, 'unmount',
588 Commands.unmountCommand, this.rootsList_, this); 590 Commands.unmountCommand, this.directoryTree_, this);
589 591
590 CommandUtil.registerCommand(doc, 'format', 592 CommandUtil.registerCommand(doc, 'format',
591 Commands.formatCommand, this.rootsList_, this, this.directoryModel_); 593 Commands.formatCommand, this.directoryTree_, this,
594 this.directoryModel_);
592 595
593 CommandUtil.registerCommand(this.rootsList_, 'import-photos', 596 CommandUtil.registerCommand(this.directoryTree_, 'import-photos',
594 Commands.importCommand, this.rootsList_); 597 Commands.importCommand, this.directoryTree_);
595 598
596 CommandUtil.registerCommand(doc, 'delete', 599 CommandUtil.registerCommand(doc, 'delete',
597 Commands.deleteFileCommand, this); 600 Commands.deleteFileCommand, this);
598 601
599 CommandUtil.registerCommand(doc, 'rename', 602 CommandUtil.registerCommand(doc, 'rename',
600 Commands.renameFileCommand, this); 603 Commands.renameFileCommand, this);
601 604
602 CommandUtil.registerCommand(doc, 'volume-help', 605 CommandUtil.registerCommand(doc, 'volume-help',
603 Commands.volumeHelpCommand, this); 606 Commands.volumeHelpCommand, this);
604 607
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
902 905
903 var fileListFocusBound = this.onFileListFocus_.bind(this); 906 var fileListFocusBound = this.onFileListFocus_.bind(this);
904 var fileListBlurBound = this.onFileListBlur_.bind(this); 907 var fileListBlurBound = this.onFileListBlur_.bind(this);
905 908
906 this.table_.list.addEventListener('focus', fileListFocusBound); 909 this.table_.list.addEventListener('focus', fileListFocusBound);
907 this.grid_.addEventListener('focus', fileListFocusBound); 910 this.grid_.addEventListener('focus', fileListFocusBound);
908 911
909 this.table_.list.addEventListener('blur', fileListBlurBound); 912 this.table_.list.addEventListener('blur', fileListBlurBound);
910 this.grid_.addEventListener('blur', fileListBlurBound); 913 this.grid_.addEventListener('blur', fileListBlurBound);
911 914
912 this.initRootsList_(); 915 this.initSidebar_();
913 916
914 this.table_.addEventListener('column-resize-end', 917 this.table_.addEventListener('column-resize-end',
915 this.updateStartupPrefs_.bind(this)); 918 this.updateStartupPrefs_.bind(this));
916 919
917 this.setListType(prefs.listType || FileManager.ListType.DETAIL); 920 this.setListType(prefs.listType || FileManager.ListType.DETAIL);
918 921
919 if (prefs.columns) { 922 if (prefs.columns) {
920 var cm = this.table_.columnModel; 923 var cm = this.table_.columnModel;
921 for (var i = 0; i < cm.totalSize; i++) { 924 for (var i = 0; i < cm.totalSize; i++) {
922 if (prefs.columns[i] > 0) 925 if (prefs.columns[i] > 0)
(...skipping 12 matching lines...) Expand all
935 // Update metadata to change 'Today' and 'Yesterday' dates. 938 // Update metadata to change 'Today' and 'Yesterday' dates.
936 var today = new Date(); 939 var today = new Date();
937 today.setHours(0); 940 today.setHours(0);
938 today.setMinutes(0); 941 today.setMinutes(0);
939 today.setSeconds(0); 942 today.setSeconds(0);
940 today.setMilliseconds(0); 943 today.setMilliseconds(0);
941 setTimeout(this.dailyUpdateModificationTime_.bind(this), 944 setTimeout(this.dailyUpdateModificationTime_.bind(this),
942 today.getTime() + MILLISECONDS_IN_DAY - Date.now() + 1000); 945 today.getTime() + MILLISECONDS_IN_DAY - Date.now() + 1000);
943 }; 946 };
944 947
945 FileManager.prototype.initRootsList_ = function() { 948 FileManager.prototype.initSidebar_ = function() {
946 this.rootsList_ = this.dialogDom_.querySelector('#roots-list'); 949 this.directoryTree_ = this.dialogDom_.querySelector('#directory-tree');
947 cr.ui.List.decorate(this.rootsList_); 950 DirectoryTree.decorate(this.directoryTree_, this.directoryModel_);
948 951
949 // Overriding default role 'list' set by cr.ui.List.decorate() to 'listbox' 952 this.directoryTree_.addEventListener('change', function() {
950 // role for better accessibility on ChromeOS. 953 var currentPath = this.directoryTree_.getCurrentPath() ||
mtomasz 2013/03/14 10:15:39 Indentation is off? I think we can align.
yoshiki 2013/03/14 13:43:42 Done.
951 this.rootsList_.setAttribute('role', 'listbox'); 954 this.directoryModel_.getDefaultDirectory();
952 955 this.directoryModel_.changeDirectory(currentPath);
953 var self = this; 956 }.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 }; 957 };
964 958
965 FileManager.prototype.updateStartupPrefs_ = function() { 959 FileManager.prototype.updateStartupPrefs_ = function() {
966 var sortStatus = this.directoryModel_.getFileList().sortStatus; 960 var sortStatus = this.directoryModel_.getFileList().sortStatus;
967 var prefs = { 961 var prefs = {
968 sortField: sortStatus.field, 962 sortField: sortStatus.field,
969 sortDirection: sortStatus.direction, 963 sortDirection: sortStatus.direction,
970 columns: [] 964 columns: []
971 }; 965 };
972 var cm = this.table_.columnModel; 966 var cm = this.table_.columnModel;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 */ 1015 */
1022 FileManager.prototype.getSelectedFilterIndex_ = function() { 1016 FileManager.prototype.getSelectedFilterIndex_ = function() {
1023 var index = Number(this.fileTypeSelector_.selectedIndex); 1017 var index = Number(this.fileTypeSelector_.selectedIndex);
1024 if (index < 0) // Nothing selected. 1018 if (index < 0) // Nothing selected.
1025 return 0; 1019 return 0;
1026 if (this.params_.includeAllFiles) // Already 1-based. 1020 if (this.params_.includeAllFiles) // Already 1-based.
1027 return index; 1021 return index;
1028 return index + 1; // Convert to 1-based; 1022 return index + 1; // Convert to 1-based;
1029 }; 1023 };
1030 1024
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) { 1025 FileManager.prototype.setListType = function(type) {
1039 if (type && type == this.listType_) 1026 if (type && type == this.listType_)
1040 return; 1027 return;
1041 1028
1042 this.table_.list.startBatchUpdates(); 1029 this.table_.list.startBatchUpdates();
1043 this.grid_.startBatchUpdates(); 1030 this.grid_.startBatchUpdates();
1044 1031
1045 // TODO(dzvorygin): style.display and dataModel setting order shouldn't 1032 // 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 1033 // cause any UI bugs. Currently, the only right way is first to set display
1047 // style and only then set dataModel. 1034 // style and only then set dataModel.
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1235 g.startBatchUpdates(); 1222 g.startBatchUpdates();
1236 setTimeout(function() { 1223 setTimeout(function() {
1237 g.columns = 0; 1224 g.columns = 0;
1238 g.redraw(); 1225 g.redraw();
1239 g.endBatchUpdates(); 1226 g.endBatchUpdates();
1240 }, 0); 1227 }, 0);
1241 } else { 1228 } else {
1242 this.table_.redraw(); 1229 this.table_.redraw();
1243 } 1230 }
1244 1231
1245 this.rootsList_.redraw();
1246 this.breadcrumbs_.truncate(); 1232 this.breadcrumbs_.truncate();
1247 this.searchBreadcrumbs_.truncate(); 1233 this.searchBreadcrumbs_.truncate();
1248 1234
1249 this.updateWindowState_(); 1235 this.updateWindowState_();
1250 }; 1236 };
1251 1237
1252 FileManager.prototype.updateWindowState_ = function() { 1238 FileManager.prototype.updateWindowState_ = function() {
1253 util.platform.getWindowStatus(function(wnd) { 1239 util.platform.getWindowStatus(function(wnd) {
1254 if (wnd.state == 'maximized') { 1240 if (wnd.state == 'maximized') {
1255 this.dialogDom_.setAttribute('maximized', 'maximized'); 1241 this.dialogDom_.setAttribute('maximized', 'maximized');
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1452 } 1438 }
1453 1439
1454 this.okButton_.textContent = okLabel; 1440 this.okButton_.textContent = okLabel;
1455 1441
1456 var dialogTitle = this.params_.title || defaultTitle; 1442 var dialogTitle = this.params_.title || defaultTitle;
1457 this.dialogDom_.querySelector('.dialog-title').textContent = dialogTitle; 1443 this.dialogDom_.querySelector('.dialog-title').textContent = dialogTitle;
1458 1444
1459 this.dialogDom_.setAttribute('type', this.dialogType); 1445 this.dialogDom_.setAttribute('type', this.dialogType);
1460 }; 1446 };
1461 1447
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 /** 1448 /**
1519 * Unmounts device. 1449 * Unmounts device.
1520 * @param {string} path Path to a volume to unmount. 1450 * @param {string} path Path to a volume to unmount.
1521 */ 1451 */
1522 FileManager.prototype.unmountVolume = function(path) { 1452 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) { 1453 var onError = function(error) {
1528 if (listItem)
1529 listItem.removeAttribute('disabled');
1530 this.alert.showHtml('', str('UNMOUNT_FAILED')); 1454 this.alert.showHtml('', str('UNMOUNT_FAILED'));
1531 }; 1455 };
1532 this.volumeManager_.unmount(path, function() {}, onError.bind(this)); 1456 this.volumeManager_.unmount(path, function() {}, onError.bind(this));
1533 }; 1457 };
1534 1458
1535 FileManager.prototype.refreshCurrentDirectoryMetadata_ = function() { 1459 FileManager.prototype.refreshCurrentDirectoryMetadata_ = function() {
1536 var entries = this.directoryModel_.getFileList().slice(); 1460 var entries = this.directoryModel_.getFileList().slice();
1537 var directoryEntry = this.directoryModel_.getCurrentDirEntry(); 1461 var directoryEntry = this.directoryModel_.getCurrentDirEntry();
1538 // We don't pass callback here. When new metadata arrives, we have an 1462 // We don't pass callback here. When new metadata arrives, we have an
1539 // observer registered to update the UI. 1463 // observer registered to update the UI.
(...skipping 1618 matching lines...) Expand 10 before | Expand all | Expand 10 after
3158 callback(this.preferences_); 3082 callback(this.preferences_);
3159 return; 3083 return;
3160 } 3084 }
3161 3085
3162 chrome.fileBrowserPrivate.getPreferences(function(prefs) { 3086 chrome.fileBrowserPrivate.getPreferences(function(prefs) {
3163 this.preferences_ = prefs; 3087 this.preferences_ = prefs;
3164 callback(prefs); 3088 callback(prefs);
3165 }.bind(this)); 3089 }.bind(this));
3166 }; 3090 };
3167 })(); 3091 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698