Index: chrome/browser/resources/history/history.js |
diff --git a/chrome/browser/resources/history/history.js b/chrome/browser/resources/history/history.js |
index a71592de4ee5d70587681b99c7b513c00db04f3a..946d90224514e7bbd087e401a03c38138dcd4bfe 100644 |
--- a/chrome/browser/resources/history/history.js |
+++ b/chrome/browser/resources/history/history.js |
@@ -250,6 +250,10 @@ Visit.prototype.getResultDOM = function(propertyBag) { |
e.preventDefault(); |
}.bind(this)); |
} |
+ |
+ if (focusless) |
+ bookmarkSection.tabIndex = -1; |
+ |
entryBox.appendChild(bookmarkSection); |
var visitEntryWrapper = /** @type {HTMLElement} */( |
@@ -884,69 +888,95 @@ HistoryModel.prototype.getGroupByDomain = function() { |
}; |
/////////////////////////////////////////////////////////////////////////////// |
-// HistoryFocusObserver: |
+// HistoryFocusRow: |
/** |
+ * Provides an implementation for a single column grid. |
* @constructor |
- * @implements {cr.ui.FocusRow.Observer} |
+ * @extends {cr.ui.FocusRow} |
+ */ |
+HistoryFocusRow = function() {}; |
Dan Beam
2015/01/27 22:32:23
why did you change from function Declaration() {}
hcarmona
2015/01/29 00:00:37
Must have happened when I moved the code around. C
|
+ |
+/** |
+ * Decorates |rowElement| so that it can be treated as a HistoryFocusRow item. |
+ * @param {Element} rowElement The element representing this row. |
+ * @param {Node} boundary Focus events are ignored outside of this node. |
*/ |
-function HistoryFocusObserver() {} |
+HistoryFocusRow.decorate = function(rowElement, boundary) { |
+ rowElement.__proto__ = HistoryFocusRow.prototype; |
+ rowElement.decorate(boundary); |
+ |
+ /** |
+ * Both of these elements are checkboxes and a history focusRow will only |
+ * have 1 of the two. By giving them both the same type we can ensure |
+ * that a checkbox remains focused when focus changes. |
+ */ |
+ rowElement.addFocusRow_('.entry-box input', 'checkbox'); |
+ rowElement.addFocusRow_('.domain-checkbox', 'checkbox'); |
+ |
+ // Add the remaining elements. |
+ rowElement.addFocusRow_('.bookmark-section.starred', 'star'); |
+ rowElement.addFocusRow_('[is="action-link"]', 'domain'); |
+ rowElement.addFocusRow_('.title a', 'title'); |
+ rowElement.addFocusRow_('.drop-down', 'menu'); |
+}; |
+ |
+HistoryFocusRow.prototype = { |
+ __proto__: cr.ui.FocusRow.prototype, |
-HistoryFocusObserver.prototype = { |
/** @override */ |
- onActivate: function(row) { |
- this.getActiveRowElement_(row).classList.add('active'); |
+ onActiveStateChanged: function(state) { |
+ this.classList.toggle('active', state); |
}, |
/** @override */ |
- onDeactivate: function(row) { |
- this.getActiveRowElement_(row).classList.remove('active'); |
+ getEquivalentElement: function(element) { |
+ if (this.contains(element)) |
+ return element; |
+ |
+ // All elements default to another element with the same type. |
+ var ret = this.getColumn_(element.getAttribute('column-type')); |
+ |
+ if (!ret) { |
+ switch (element.getAttribute('column-type')) { |
+ case 'star': |
+ ret = this.getColumn_('title') || this.getColumn_('domain'); |
+ break; |
+ case 'domain': |
+ ret = this.getColumn_('title'); |
+ break; |
+ case 'title': |
+ ret = this.getColumn_('domain'); |
+ break; |
+ case 'menu': |
+ ret = this.focusableElements[this.focusableElements.length - 1]; |
+ } |
+ } |
+ |
+ return ret || this.focusableElements[0]; |
}, |
/** |
- * @param {cr.ui.FocusRow} row The row to find an element for. |
- * @return {Element} |row|'s "active" element. |
+ * @param {string} type The type of column to return. |
+ * @return {Element?} The column matching the type. |
Dan Beam
2015/01/27 22:32:23
nit: ?Element
hcarmona
2015/01/29 00:00:37
Done.
|
* @private |
*/ |
- getActiveRowElement_: function(row) { |
- return findAncestorByClass(row.items[0], 'entry') || |
- findAncestorByClass(row.items[0], 'site-domain-wrapper'); |
+ getColumn_: function(type) { |
+ return this.querySelector('[column-type=' + type + ']'); |
}, |
-}; |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// HistoryFocusGrid: |
- |
-/** |
- * @param {Node=} opt_boundary |
- * @param {cr.ui.FocusRow.Observer=} opt_observer |
- * @constructor |
- * @extends {cr.ui.FocusGrid} |
- */ |
-function HistoryFocusGrid(opt_boundary, opt_observer) { |
- cr.ui.FocusGrid.apply(this, arguments); |
-} |
-HistoryFocusGrid.prototype = { |
- __proto__: cr.ui.FocusGrid.prototype, |
- |
- /** @override */ |
- onMousedown: function(row, e) { |
- // TODO(dbeam): Can cr.ui.FocusGrid know about cr.ui.MenuButton? If so, bake |
- // this logic into the base class directly. |
- var menuButton = findAncestorByClass(e.target, 'menu-button'); |
- if (menuButton) { |
- // Deactivate any other active row. |
- this.rows.some(function(r) { |
- if (r.activeIndex >= 0 && r != row) { |
- r.activeIndex = -1; |
- return true; |
- } |
- }); |
- // Activate only the row with a pressed menu button. |
- row.activeIndex = row.items.indexOf(menuButton); |
+ /** |
+ * Add a focusable element if it exists in this FocusRow. |
+ * @param {string} query A query to select the appropriate element. |
+ * @param {string} type The type to use for the element. |
+ * @private |
+ */ |
+ addFocusRow_: function(query, type) { |
+ var element = this.querySelector(query); |
+ if (element) { |
+ this.addFocusableElement(element); |
+ element.setAttribute('column-type', type); |
} |
- return !!menuButton; |
}, |
}; |
@@ -964,8 +994,7 @@ function HistoryView(model) { |
this.editButtonTd_ = $('edit-button'); |
this.editingControlsDiv_ = $('editing-controls'); |
this.resultDiv_ = $('results-display'); |
- this.focusGrid_ = new HistoryFocusGrid(this.resultDiv_, |
- new HistoryFocusObserver); |
+ this.focusGrid_ = new cr.ui.FocusGrid(); |
this.pageDiv_ = $('results-pagination'); |
this.model_ = model; |
this.pageIndex_ = 0; |
@@ -1197,14 +1226,14 @@ HistoryView.prototype.showNotification = function(innerHTML, isWarning) { |
HistoryView.prototype.onBeforeRemove = function(visit) { |
assert(this.currentVisits_.indexOf(visit) >= 0); |
- var pos = this.focusGrid_.getPositionForTarget(document.activeElement); |
- if (!pos) |
+ var rowIndex = this.focusGrid_.getRowIndexForTarget(document.activeElement); |
+ if (rowIndex == -1) |
return; |
- var row = this.focusGrid_.rows[pos.row + 1] || |
- this.focusGrid_.rows[pos.row - 1]; |
- if (row) |
- row.focusIndex(Math.min(pos.col, row.items.length - 1)); |
+ var rowToFocus = this.focusGrid_.rows[rowIndex + 1] || |
+ this.focusGrid_.rows[rowIndex - 1]; |
+ if (rowToFocus) |
+ rowToFocus.getEquivalentElement(document.activeElement).focus(); |
}; |
/** @param {Visit} visit The visit about to be unstarred. */ |
@@ -1212,9 +1241,14 @@ HistoryView.prototype.onBeforeUnstarred = function(visit) { |
assert(this.currentVisits_.indexOf(visit) >= 0); |
assert(visit.bookmarkStar == document.activeElement); |
- var pos = this.focusGrid_.getPositionForTarget(document.activeElement); |
- var row = this.focusGrid_.rows[pos.row]; |
- row.focusIndex(Math.min(pos.col + 1, row.items.length - 1)); |
+ var rowIndex = this.focusGrid_.getRowIndexForTarget(document.activeElement); |
+ var row = this.focusGrid_.rows[rowIndex]; |
+ |
+ // Focus the title or domain when the bookmarked star is removed because the |
+ // star will no longer be focusable. |
+ var newFocus = row.querySelector('[column-type="title"]') || |
+ row.querySelector('[column-type="domain"]'); |
Dan Beam
2015/01/27 22:32:23
nit: arguably combine querySelector() calls into 1
hcarmona
2015/01/29 00:00:37
Done.
|
+ newFocus.focus(); |
}; |
/** @param {Visit} visit The visit that was just unstarred. */ |
@@ -1312,7 +1346,7 @@ HistoryView.prototype.positionNotificationBar = function() { |
* @return {boolean} Whether |el| is in |this.focusGrid_|. |
*/ |
HistoryView.prototype.isInFocusGrid = function(el) { |
- return !!this.focusGrid_.getPositionForTarget(el); |
+ return this.focusGrid_.getRowIndexForTarget(el) != -1; |
}; |
// HistoryView, private: ------------------------------------------------------ |
@@ -1674,26 +1708,16 @@ var focusGridRowSelector = [ |
'.site-domain-wrapper' |
].join(', '); |
-var focusGridColumnSelector = [ |
- '.entry-box input', |
- '.bookmark-section.starred', |
- '.title a', |
- '.drop-down', |
- '.domain-checkbox', |
- '[is="action-link"]', |
-].join(', '); |
- |
/** @private */ |
HistoryView.prototype.updateFocusGrid_ = function() { |
var rows = this.resultDiv_.querySelectorAll(focusGridRowSelector); |
- var grid = []; |
+ this.focusGrid_.destroy(); |
for (var i = 0; i < rows.length; ++i) { |
assert(rows[i].parentNode); |
- grid.push(rows[i].querySelectorAll(focusGridColumnSelector)); |
+ HistoryFocusRow.decorate(rows[i], this.resultDiv_); |
+ this.focusGrid_.addRow(rows[i]); |
} |
- |
- this.focusGrid_.setGrid(grid); |
}; |
/** |