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

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 after talk Created 5 years, 11 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 if (focusless)
254 bookmarkSection.tabIndex = -1;
253 entryBox.appendChild(bookmarkSection); 255 entryBox.appendChild(bookmarkSection);
254 256
255 var visitEntryWrapper = /** @type {HTMLElement} */( 257 var visitEntryWrapper = /** @type {HTMLElement} */(
256 entryBox.appendChild(document.createElement('div'))); 258 entryBox.appendChild(document.createElement('div')));
257 if (addTitleFavicon || this.blockedVisit) 259 if (addTitleFavicon || this.blockedVisit)
258 visitEntryWrapper.classList.add('visit-entry'); 260 visitEntryWrapper.classList.add('visit-entry');
259 if (this.blockedVisit) { 261 if (this.blockedVisit) {
260 visitEntryWrapper.classList.add('blocked-indicator'); 262 visitEntryWrapper.classList.add('blocked-indicator');
261 visitEntryWrapper.appendChild(this.getVisitAttemptDOM_()); 263 visitEntryWrapper.appendChild(this.getVisitAttemptDOM_());
262 } else { 264 } else {
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 879
878 /** 880 /**
879 * Gets whether we are grouped by domain. 881 * Gets whether we are grouped by domain.
880 * @return {boolean} Whether the results are grouped by domain. 882 * @return {boolean} Whether the results are grouped by domain.
881 */ 883 */
882 HistoryModel.prototype.getGroupByDomain = function() { 884 HistoryModel.prototype.getGroupByDomain = function() {
883 return this.groupByDomain_; 885 return this.groupByDomain_;
884 }; 886 };
885 887
886 /////////////////////////////////////////////////////////////////////////////// 888 ///////////////////////////////////////////////////////////////////////////////
887 // HistoryFocusObserver: 889 // HistoryFocusRow:
888 890
889 /** 891 /**
890 * @constructor 892 * Provides an implementation for a single column grid.
891 * @implements {cr.ui.FocusRow.Observer} 893 * @param {Node} boundary Focus events are ignored outside of this node.
894 * @param {Element} rowElement The element representing this row.
895 * @extends {cr.ui.FocusRow}
892 */ 896 */
893 function HistoryFocusObserver() {} 897 HistoryFocusRow = function(boundary, rowElement) {
898 cr.ui.FocusRow.apply(this, arguments);
894 899
895 HistoryFocusObserver.prototype = { 900 /**
901 * Both of these elements are checkboxes and a history focusRow will only
902 * have 1 of the two. By giving them both the same type we can ensure
903 * that a checkbox remains focused when focus changes.
904 */
905 this.addFocusRow_('.entry-box input', 'checkbox');
906 this.addFocusRow_('.domain-checkbox', 'checkbox');
907
908 // Add the remaining elements.
909 this.addFocusRow_('.bookmark-section.starred', 'star');
910 this.addFocusRow_('[is="action-link"]', 'domain');
911 this.addFocusRow_('.title a', 'title');
912 this.addFocusRow_('.drop-down', 'menu');
913 };
914
915 HistoryFocusRow.prototype = {
916 __proto__: cr.ui.FocusRow.prototype,
917
896 /** @override */ 918 /** @override */
897 onActivate: function(row) { 919 onActivate: function() {
898 this.getActiveRowElement_(row).classList.add('active'); 920 this.rowElement_.classList.add('active');
899 }, 921 },
900 922
901 /** @override */ 923 /** @override */
902 onDeactivate: function(row) { 924 onDeactivate: function(row) {
903 this.getActiveRowElement_(row).classList.remove('active'); 925 this.rowElement_.classList.remove('active');
926 },
927
928 /** @override */
929 getEquivalentElement: function(element) {
930 if (this.contains(element))
931 return element;
932
933 var ret = null;
934
935 switch (element.getAttribute('column-type')) {
936 case ('checkbox'):
937 ret = this.getMatch('[column-type="checkbox"]');
Evan Stade 2015/01/22 16:55:10 what is getMatch? seems a lot like querySelector
hcarmona 2015/01/24 01:24:19 Done. Replaced getMatch with querySelector.
938 break;
939 case ('star'):
940 ret = this.getMatch('[column-type="star"]') ||
941 this.getMatch('[column-type="title"]') ||
942 this.getMatch('[column-type="domain"]');
943 break;
944 case ('domain'):
945 ret = this.getMatch('[column-type="domain"]') ||
946 this.getMatch('[column-type="title"]');
947 break;
948 case ('title'):
949 ret = this.getMatch('[column-type="title"]') ||
950 this.getMatch('[column-type="domain"]');
951 break;
952 case ('menu'):
953 ret = this.rowElements[this.rowElements.length - 1];
954 }
955
956 return ret || this.rowElements[0];
904 }, 957 },
905 958
906 /** 959 /**
907 * @param {cr.ui.FocusRow} row The row to find an element for. 960 * Add a focusable element if it exists in this FocusRow.
908 * @return {Element} |row|'s "active" element. 961 * @param {string} query A query to select the appropriate element.
962 * @param {string} type The type to use for the element.
909 * @private 963 * @private
910 */ 964 */
911 getActiveRowElement_: function(row) { 965 addFocusRow_: function(query, type) {
912 return findAncestorByClass(row.items[0], 'entry') || 966 var element = this.getMatch(query);
913 findAncestorByClass(row.items[0], 'site-domain-wrapper'); 967 if (element) {
968 this.setFocusableElement(element);
969 element.setAttribute('column-type', type);
970 }
914 }, 971 },
915 }; 972 };
916 973
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 /////////////////////////////////////////////////////////////////////////////// 974 ///////////////////////////////////////////////////////////////////////////////
954 // HistoryView: 975 // HistoryView:
955 976
956 /** 977 /**
957 * Functions and state for populating the page with HTML. This should one-day 978 * 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 979 * contain the view and use event handlers, rather than pushing HTML out and
959 * getting called externally. 980 * getting called externally.
960 * @param {HistoryModel} model The model backing this view. 981 * @param {HistoryModel} model The model backing this view.
961 * @constructor 982 * @constructor
962 */ 983 */
963 function HistoryView(model) { 984 function HistoryView(model) {
964 this.editButtonTd_ = $('edit-button'); 985 this.editButtonTd_ = $('edit-button');
965 this.editingControlsDiv_ = $('editing-controls'); 986 this.editingControlsDiv_ = $('editing-controls');
966 this.resultDiv_ = $('results-display'); 987 this.resultDiv_ = $('results-display');
967 this.focusGrid_ = new HistoryFocusGrid(this.resultDiv_, 988 this.focusGrid_ = new cr.ui.FocusGrid();
968 new HistoryFocusObserver);
969 this.pageDiv_ = $('results-pagination'); 989 this.pageDiv_ = $('results-pagination');
970 this.model_ = model; 990 this.model_ = model;
971 this.pageIndex_ = 0; 991 this.pageIndex_ = 0;
972 this.lastDisplayed_ = []; 992 this.lastDisplayed_ = [];
973 993
974 this.model_.setView(this); 994 this.model_.setView(this);
975 995
976 this.currentVisits_ = []; 996 this.currentVisits_ = [];
977 997
978 // If there is no search button, use the search button label as placeholder 998 // If there is no search button, use the search button label as placeholder
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 HistoryView.prototype.onBeforeRemove = function(visit) { 1217 HistoryView.prototype.onBeforeRemove = function(visit) {
1198 assert(this.currentVisits_.indexOf(visit) >= 0); 1218 assert(this.currentVisits_.indexOf(visit) >= 0);
1199 1219
1200 var pos = this.focusGrid_.getPositionForTarget(document.activeElement); 1220 var pos = this.focusGrid_.getPositionForTarget(document.activeElement);
1201 if (!pos) 1221 if (!pos)
1202 return; 1222 return;
1203 1223
1204 var row = this.focusGrid_.rows[pos.row + 1] || 1224 var row = this.focusGrid_.rows[pos.row + 1] ||
1205 this.focusGrid_.rows[pos.row - 1]; 1225 this.focusGrid_.rows[pos.row - 1];
1206 if (row) 1226 if (row)
1207 row.focusIndex(Math.min(pos.col, row.items.length - 1)); 1227 row.focusEquivalentElement(pos.element);
1208 }; 1228 };
1209 1229
1210 /** @param {Visit} visit The visit about to be unstarred. */ 1230 /** @param {Visit} visit The visit about to be unstarred. */
1211 HistoryView.prototype.onBeforeUnstarred = function(visit) { 1231 HistoryView.prototype.onBeforeUnstarred = function(visit) {
1212 assert(this.currentVisits_.indexOf(visit) >= 0); 1232 assert(this.currentVisits_.indexOf(visit) >= 0);
1213 assert(visit.bookmarkStar == document.activeElement); 1233 assert(visit.bookmarkStar == document.activeElement);
1214 1234
1215 var pos = this.focusGrid_.getPositionForTarget(document.activeElement); 1235 var pos = this.focusGrid_.getPositionForTarget(document.activeElement);
1216 var row = this.focusGrid_.rows[pos.row]; 1236 var row = this.focusGrid_.rows[pos.row];
1217 row.focusIndex(Math.min(pos.col + 1, row.items.length - 1)); 1237 row.focusEquivalentElement(pos.element);
1218 }; 1238 };
1219 1239
1220 /** @param {Visit} visit The visit that was just unstarred. */ 1240 /** @param {Visit} visit The visit that was just unstarred. */
1221 HistoryView.prototype.onAfterUnstarred = function(visit) { 1241 HistoryView.prototype.onAfterUnstarred = function(visit) {
1222 this.updateFocusGrid_(); 1242 this.updateFocusGrid_();
1223 }; 1243 };
1224 1244
1225 /** 1245 /**
1226 * Removes a single entry from the view. Also removes gaps before and after 1246 * Removes a single entry from the view. Also removes gaps before and after
1227 * entry if necessary. 1247 * entry if necessary.
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 // time column. 1687 // time column.
1668 this.setTimeColumnWidth_(); 1688 this.setTimeColumnWidth_();
1669 }; 1689 };
1670 1690
1671 var focusGridRowSelector = [ 1691 var focusGridRowSelector = [
1672 ':-webkit-any(.day-results, .search-results) > .entry:not(.fade-out)', 1692 ':-webkit-any(.day-results, .search-results) > .entry:not(.fade-out)',
1673 '.expand .grouped .entry:not(.fade-out)', 1693 '.expand .grouped .entry:not(.fade-out)',
1674 '.site-domain-wrapper' 1694 '.site-domain-wrapper'
1675 ].join(', '); 1695 ].join(', ');
1676 1696
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 */ 1697 /** @private */
1687 HistoryView.prototype.updateFocusGrid_ = function() { 1698 HistoryView.prototype.updateFocusGrid_ = function() {
1688 var rows = this.resultDiv_.querySelectorAll(focusGridRowSelector); 1699 var rows = this.resultDiv_.querySelectorAll(focusGridRowSelector);
1689 var grid = []; 1700 this.focusGrid_.destroy();
1690 1701
1691 for (var i = 0; i < rows.length; ++i) { 1702 for (var i = 0; i < rows.length; ++i) {
1692 assert(rows[i].parentNode); 1703 assert(rows[i].parentNode);
1693 grid.push(rows[i].querySelectorAll(focusGridColumnSelector)); 1704 this.focusGrid_.addRow(new HistoryFocusRow(this.resultDiv_, rows[i]));
1694 } 1705 }
1695
1696 this.focusGrid_.setGrid(grid);
1697 }; 1706 };
1698 1707
1699 /** 1708 /**
1700 * Update the visibility of the page navigation buttons. 1709 * Update the visibility of the page navigation buttons.
1701 * @private 1710 * @private
1702 */ 1711 */
1703 HistoryView.prototype.updateNavBar_ = function() { 1712 HistoryView.prototype.updateNavBar_ = function() {
1704 this.updateRangeButtons_(); 1713 this.updateRangeButtons_();
1705 1714
1706 // If grouping by domain is enabled, there's a control bar on top, don't show 1715 // 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(); 2390 historyView.reload();
2382 } 2391 }
2383 2392
2384 // Add handlers to HTML elements. 2393 // Add handlers to HTML elements.
2385 document.addEventListener('DOMContentLoaded', load); 2394 document.addEventListener('DOMContentLoaded', load);
2386 2395
2387 // This event lets us enable and disable menu items before the menu is shown. 2396 // This event lets us enable and disable menu items before the menu is shown.
2388 document.addEventListener('canExecute', function(e) { 2397 document.addEventListener('canExecute', function(e) {
2389 e.canExecute = true; 2398 e.canExecute = true;
2390 }); 2399 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698