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

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

Issue 807593005: Make downloads list keyboard shortcuts more consistent. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Apply feedback Created 5 years, 10 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
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 <include src="../uber/uber_utils.js"> 5 <include src="../uber/uber_utils.js">
6 <include src="history_focus_manager.js"> 6 <include src="history_focus_manager.js">
7 7
8 /////////////////////////////////////////////////////////////////////////////// 8 ///////////////////////////////////////////////////////////////////////////////
9 // Globals: 9 // Globals:
10 /** @const */ var RESULTS_PER_PAGE = 150; 10 /** @const */ var RESULTS_PER_PAGE = 150;
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 chrome.send('removeBookmark', [self.url_]); 243 chrome.send('removeBookmark', [self.url_]);
244 244
245 this.model_.getView().onBeforeUnstarred(this); 245 this.model_.getView().onBeforeUnstarred(this);
246 bookmarkSection.classList.remove('starred'); 246 bookmarkSection.classList.remove('starred');
247 this.model_.getView().onAfterUnstarred(this); 247 this.model_.getView().onAfterUnstarred(this);
248 248
249 bookmarkSection.removeEventListener('click', f); 249 bookmarkSection.removeEventListener('click', f);
250 e.preventDefault(); 250 e.preventDefault();
251 }.bind(this)); 251 }.bind(this));
252 } 252 }
253
254 if (focusless)
255 bookmarkSection.tabIndex = -1;
256
253 entryBox.appendChild(bookmarkSection); 257 entryBox.appendChild(bookmarkSection);
254 258
255 var visitEntryWrapper = /** @type {HTMLElement} */( 259 var visitEntryWrapper = /** @type {HTMLElement} */(
256 entryBox.appendChild(document.createElement('div'))); 260 entryBox.appendChild(document.createElement('div')));
257 if (addTitleFavicon || this.blockedVisit) 261 if (addTitleFavicon || this.blockedVisit)
258 visitEntryWrapper.classList.add('visit-entry'); 262 visitEntryWrapper.classList.add('visit-entry');
259 if (this.blockedVisit) { 263 if (this.blockedVisit) {
260 visitEntryWrapper.classList.add('blocked-indicator'); 264 visitEntryWrapper.classList.add('blocked-indicator');
261 visitEntryWrapper.appendChild(this.getVisitAttemptDOM_()); 265 visitEntryWrapper.appendChild(this.getVisitAttemptDOM_());
262 } else { 266 } else {
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 881
878 /** 882 /**
879 * Gets whether we are grouped by domain. 883 * Gets whether we are grouped by domain.
880 * @return {boolean} Whether the results are grouped by domain. 884 * @return {boolean} Whether the results are grouped by domain.
881 */ 885 */
882 HistoryModel.prototype.getGroupByDomain = function() { 886 HistoryModel.prototype.getGroupByDomain = function() {
883 return this.groupByDomain_; 887 return this.groupByDomain_;
884 }; 888 };
885 889
886 /////////////////////////////////////////////////////////////////////////////// 890 ///////////////////////////////////////////////////////////////////////////////
887 // HistoryFocusObserver: 891 // HistoryFocusRow:
888 892
889 /** 893 /**
894 * Provides an implementation for a single column grid.
890 * @constructor 895 * @constructor
891 * @implements {cr.ui.FocusRow.Observer} 896 * @extends {cr.ui.FocusRow}
892 */ 897 */
893 function HistoryFocusObserver() {} 898 function HistoryFocusRow() {}
894 899
895 HistoryFocusObserver.prototype = { 900 /**
901 * Decorates |rowElement| so that it can be treated as a HistoryFocusRow item.
902 * @param {Element} rowElement The element representing this row.
903 * @param {Node} boundary Focus events are ignored outside of this node.
904 */
905 HistoryFocusRow.decorate = function(rowElement, boundary) {
906 rowElement.__proto__ = HistoryFocusRow.prototype;
907 rowElement.decorate(boundary);
908
909 rowElement.addElementIfPresent_('.entry-box input', 'checkbox');
910 rowElement.addElementIfPresent_('.domain-checkbox', 'checkbox');
911 rowElement.addElementIfPresent_('.bookmark-section.starred', 'star');
912 rowElement.addElementIfPresent_('[is="action-link"]', 'domain');
913 rowElement.addElementIfPresent_('.title a', 'title');
914 rowElement.addElementIfPresent_('.drop-down', 'menu');
915 };
916
917 HistoryFocusRow.prototype = {
918 __proto__: cr.ui.FocusRow.prototype,
919
896 /** @override */ 920 /** @override */
897 onActivate: function(row) { 921 onActiveStateChanged: function(state) {
898 this.getActiveRowElement_(row).classList.add('active'); 922 this.classList.toggle('active', state);
899 }, 923 },
900 924
901 /** @override */ 925 /** @override */
902 onDeactivate: function(row) { 926 getEquivalentElement: function(element) {
903 this.getActiveRowElement_(row).classList.remove('active'); 927 if (this.contains(element))
928 return element;
929
930 // All elements default to another element with the same type.
931 var equivalent = this.getColumn_(element.getAttribute('column-type'));
932
933 if (!equivalent) {
934 switch (element.getAttribute('column-type')) {
935 case 'star':
936 equivalent = this.getColumn_('title') || this.getColumn_('domain');
937 break;
938 case 'domain':
939 equivalent = this.getColumn_('title');
940 break;
941 case 'title':
942 equivalent = this.getColumn_('domain');
943 break;
944 case 'menu':
945 return this.focusableElements[this.focusableElements.length - 1];
946 }
947 }
948
949 return equivalent || this.focusableElements[0];
904 }, 950 },
905 951
906 /** 952 /**
907 * @param {cr.ui.FocusRow} row The row to find an element for. 953 * @param {string} type The type of column to return.
908 * @return {Element} |row|'s "active" element. 954 * @return {?Element} The column matching the type.
909 * @private 955 * @private
910 */ 956 */
911 getActiveRowElement_: function(row) { 957 getColumn_: function(type) {
912 return findAncestorByClass(row.items[0], 'entry') || 958 return this.querySelector('[column-type=' + type + ']');
913 findAncestorByClass(row.items[0], 'site-domain-wrapper'); 959 },
960
961 /**
962 * @param {string} query A query to select the appropriate element.
963 * @param {string} type The type to use for the element.
964 * @private
965 */
966 addElementIfPresent_: function(query, type) {
967 var element = this.querySelector(query);
968 if (element) {
969 this.addFocusableElement(element);
970 element.setAttribute('column-type', type);
971 }
914 }, 972 },
915 }; 973 };
916 974
917 ///////////////////////////////////////////////////////////////////////////////
918 // HistoryFocusGrid:
919
920 /**
921 * @param {Node=} opt_boundary
922 * @param {cr.ui.FocusRow.Observer=} opt_observer
923 * @constructor
924 * @extends {cr.ui.FocusGrid}
925 */
926 function HistoryFocusGrid(opt_boundary, opt_observer) {
927 cr.ui.FocusGrid.apply(this, arguments);
928 }
929
930 HistoryFocusGrid.prototype = {
931 __proto__: cr.ui.FocusGrid.prototype,
932
933 /** @override */
934 onMousedown: function(row, e) {
935 // TODO(dbeam): Can cr.ui.FocusGrid know about cr.ui.MenuButton? If so, bake
936 // this logic into the base class directly.
937 var menuButton = findAncestorByClass(e.target, 'menu-button');
938 if (menuButton) {
939 // Deactivate any other active row.
940 this.rows.some(function(r) {
941 if (r.activeIndex >= 0 && r != row) {
942 r.activeIndex = -1;
943 return true;
944 }
945 });
946 // Activate only the row with a pressed menu button.
947 row.activeIndex = row.items.indexOf(menuButton);
948 }
949 return !!menuButton;
950 },
951 };
952
953 /////////////////////////////////////////////////////////////////////////////// 975 ///////////////////////////////////////////////////////////////////////////////
954 // HistoryView: 976 // HistoryView:
955 977
956 /** 978 /**
957 * Functions and state for populating the page with HTML. This should one-day 979 * Functions and state for populating the page with HTML. This should one-day
958 * contain the view and use event handlers, rather than pushing HTML out and 980 * contain the view and use event handlers, rather than pushing HTML out and
959 * getting called externally. 981 * getting called externally.
960 * @param {HistoryModel} model The model backing this view. 982 * @param {HistoryModel} model The model backing this view.
961 * @constructor 983 * @constructor
962 */ 984 */
963 function HistoryView(model) { 985 function HistoryView(model) {
964 this.editButtonTd_ = $('edit-button'); 986 this.editButtonTd_ = $('edit-button');
965 this.editingControlsDiv_ = $('editing-controls'); 987 this.editingControlsDiv_ = $('editing-controls');
966 this.resultDiv_ = $('results-display'); 988 this.resultDiv_ = $('results-display');
967 this.focusGrid_ = new HistoryFocusGrid(this.resultDiv_, 989 this.focusGrid_ = new cr.ui.FocusGrid();
968 new HistoryFocusObserver);
969 this.pageDiv_ = $('results-pagination'); 990 this.pageDiv_ = $('results-pagination');
970 this.model_ = model; 991 this.model_ = model;
971 this.pageIndex_ = 0; 992 this.pageIndex_ = 0;
972 this.lastDisplayed_ = []; 993 this.lastDisplayed_ = [];
973 994
974 this.model_.setView(this); 995 this.model_.setView(this);
975 996
976 this.currentVisits_ = []; 997 this.currentVisits_ = [];
977 998
978 // If there is no search button, use the search button label as placeholder 999 // If there is no search button, use the search button label as placeholder
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
1190 1211
1191 this.positionNotificationBar(); 1212 this.positionNotificationBar();
1192 }; 1213 };
1193 1214
1194 /** 1215 /**
1195 * @param {Visit} visit The visit about to be removed from this view. 1216 * @param {Visit} visit The visit about to be removed from this view.
1196 */ 1217 */
1197 HistoryView.prototype.onBeforeRemove = function(visit) { 1218 HistoryView.prototype.onBeforeRemove = function(visit) {
1198 assert(this.currentVisits_.indexOf(visit) >= 0); 1219 assert(this.currentVisits_.indexOf(visit) >= 0);
1199 1220
1200 var pos = this.focusGrid_.getPositionForTarget(document.activeElement); 1221 var rowIndex = this.focusGrid_.getRowIndexForTarget(document.activeElement);
1201 if (!pos) 1222 if (rowIndex == -1)
1202 return; 1223 return;
1203 1224
1204 var row = this.focusGrid_.rows[pos.row + 1] || 1225 var rowToFocus = this.focusGrid_.rows[rowIndex + 1] ||
1205 this.focusGrid_.rows[pos.row - 1]; 1226 this.focusGrid_.rows[rowIndex - 1];
1206 if (row) 1227 if (rowToFocus)
1207 row.focusIndex(Math.min(pos.col, row.items.length - 1)); 1228 rowToFocus.getEquivalentElement(document.activeElement).focus();
1208 }; 1229 };
1209 1230
1210 /** @param {Visit} visit The visit about to be unstarred. */ 1231 /** @param {Visit} visit The visit about to be unstarred. */
1211 HistoryView.prototype.onBeforeUnstarred = function(visit) { 1232 HistoryView.prototype.onBeforeUnstarred = function(visit) {
1212 assert(this.currentVisits_.indexOf(visit) >= 0); 1233 assert(this.currentVisits_.indexOf(visit) >= 0);
1213 assert(visit.bookmarkStar == document.activeElement); 1234 assert(visit.bookmarkStar == document.activeElement);
1214 1235
1215 var pos = this.focusGrid_.getPositionForTarget(document.activeElement); 1236 var rowIndex = this.focusGrid_.getRowIndexForTarget(document.activeElement);
1216 var row = this.focusGrid_.rows[pos.row]; 1237 var row = this.focusGrid_.rows[rowIndex];
1217 row.focusIndex(Math.min(pos.col + 1, row.items.length - 1)); 1238
1239 // Focus the title or domain when the bookmarked star is removed because the
1240 // star will no longer be focusable.
1241 row.querySelector('[column-type=title], [column-type=domain]').focus();
1218 }; 1242 };
1219 1243
1220 /** @param {Visit} visit The visit that was just unstarred. */ 1244 /** @param {Visit} visit The visit that was just unstarred. */
1221 HistoryView.prototype.onAfterUnstarred = function(visit) { 1245 HistoryView.prototype.onAfterUnstarred = function(visit) {
1222 this.updateFocusGrid_(); 1246 this.updateFocusGrid_();
1223 }; 1247 };
1224 1248
1225 /** 1249 /**
1226 * Removes a single entry from the view. Also removes gaps before and after 1250 * Removes a single entry from the view. Also removes gaps before and after
1227 * entry if necessary. 1251 * entry if necessary.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1305 } else { 1329 } else {
1306 bar.classList.remove('alone'); 1330 bar.classList.remove('alone');
1307 } 1331 }
1308 }; 1332 };
1309 1333
1310 /** 1334 /**
1311 * @param {Element} el An element to look for. 1335 * @param {Element} el An element to look for.
1312 * @return {boolean} Whether |el| is in |this.focusGrid_|. 1336 * @return {boolean} Whether |el| is in |this.focusGrid_|.
1313 */ 1337 */
1314 HistoryView.prototype.isInFocusGrid = function(el) { 1338 HistoryView.prototype.isInFocusGrid = function(el) {
1315 return !!this.focusGrid_.getPositionForTarget(el); 1339 return this.focusGrid_.getRowIndexForTarget(el) != -1;
1316 }; 1340 };
1317 1341
1318 // HistoryView, private: ------------------------------------------------------ 1342 // HistoryView, private: ------------------------------------------------------
1319 1343
1320 /** 1344 /**
1321 * Clear the results in the view. Since we add results piecemeal, we need 1345 * Clear the results in the view. Since we add results piecemeal, we need
1322 * to clear them out when we switch to a new page or reload. 1346 * to clear them out when we switch to a new page or reload.
1323 * @private 1347 * @private
1324 */ 1348 */
1325 HistoryView.prototype.clear_ = function() { 1349 HistoryView.prototype.clear_ = function() {
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 // time column. 1691 // time column.
1668 this.setTimeColumnWidth_(); 1692 this.setTimeColumnWidth_();
1669 }; 1693 };
1670 1694
1671 var focusGridRowSelector = [ 1695 var focusGridRowSelector = [
1672 ':-webkit-any(.day-results, .search-results) > .entry:not(.fade-out)', 1696 ':-webkit-any(.day-results, .search-results) > .entry:not(.fade-out)',
1673 '.expand .grouped .entry:not(.fade-out)', 1697 '.expand .grouped .entry:not(.fade-out)',
1674 '.site-domain-wrapper' 1698 '.site-domain-wrapper'
1675 ].join(', '); 1699 ].join(', ');
1676 1700
1677 var focusGridColumnSelector = [
1678 '.entry-box input',
1679 '.bookmark-section.starred',
1680 '.title a',
1681 '.drop-down',
1682 '.domain-checkbox',
1683 '[is="action-link"]',
1684 ].join(', ');
1685
1686 /** @private */ 1701 /** @private */
1687 HistoryView.prototype.updateFocusGrid_ = function() { 1702 HistoryView.prototype.updateFocusGrid_ = function() {
1688 var rows = this.resultDiv_.querySelectorAll(focusGridRowSelector); 1703 var rows = this.resultDiv_.querySelectorAll(focusGridRowSelector);
1689 var grid = []; 1704 this.focusGrid_.destroy();
1690 1705
1691 for (var i = 0; i < rows.length; ++i) { 1706 for (var i = 0; i < rows.length; ++i) {
1692 assert(rows[i].parentNode); 1707 assert(rows[i].parentNode);
1693 grid.push(rows[i].querySelectorAll(focusGridColumnSelector)); 1708 HistoryFocusRow.decorate(rows[i], this.resultDiv_);
1709 this.focusGrid_.addRow(rows[i]);
1694 } 1710 }
1695
1696 this.focusGrid_.setGrid(grid);
1697 }; 1711 };
1698 1712
1699 /** 1713 /**
1700 * Update the visibility of the page navigation buttons. 1714 * Update the visibility of the page navigation buttons.
1701 * @private 1715 * @private
1702 */ 1716 */
1703 HistoryView.prototype.updateNavBar_ = function() { 1717 HistoryView.prototype.updateNavBar_ = function() {
1704 this.updateRangeButtons_(); 1718 this.updateRangeButtons_();
1705 1719
1706 // If grouping by domain is enabled, there's a control bar on top, don't show 1720 // If grouping by domain is enabled, there's a control bar on top, don't show
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after
2381 historyView.reload(); 2395 historyView.reload();
2382 } 2396 }
2383 2397
2384 // Add handlers to HTML elements. 2398 // Add handlers to HTML elements.
2385 document.addEventListener('DOMContentLoaded', load); 2399 document.addEventListener('DOMContentLoaded', load);
2386 2400
2387 // This event lets us enable and disable menu items before the menu is shown. 2401 // This event lets us enable and disable menu items before the menu is shown.
2388 document.addEventListener('canExecute', function(e) { 2402 document.addEventListener('canExecute', function(e) {
2389 e.canExecute = true; 2403 e.canExecute = true;
2390 }); 2404 });
OLDNEW
« no previous file with comments | « chrome/browser/resources/downloads/downloads.js ('k') | chrome/browser/resources/history/other_devices.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698