Index: chrome/browser/resources/md_history/history_item.js |
diff --git a/chrome/browser/resources/md_history/history_item.js b/chrome/browser/resources/md_history/history_item.js |
index 3a88c4488ff2e82ea7b04babc7367b64de8cb18e..6854bf6b6f2f0487f8335490b7ab57328b5451ae 100644 |
--- a/chrome/browser/resources/md_history/history_item.js |
+++ b/chrome/browser/resources/md_history/history_item.js |
@@ -2,7 +2,79 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+/** |
+ * @param {!Element} root |
+ * @param {?Element} boundary |
+ * @param {cr.ui.FocusRow.Delegate} delegate |
+ * @constructor |
+ * @extends {cr.ui.FocusRow} |
+ */ |
+function HistoryFocusRow(root, boundary, delegate) { |
+ cr.ui.FocusRow.call(this, root, boundary, delegate); |
+ this.addItems(); |
+} |
+ |
+HistoryFocusRow.prototype = { |
+ __proto__: cr.ui.FocusRow.prototype, |
+ |
+ /** @override */ |
+ getCustomEquivalent: function(sampleElement) { |
+ var equivalent; |
+ |
+ if (this.getTypeForElement(sampleElement) == 'star') |
+ equivalent = this.getFirstFocusable('title'); |
+ |
+ return equivalent || |
+ cr.ui.FocusRow.prototype.getCustomEquivalent.call( |
+ this, sampleElement); |
+ }, |
+ |
+ addItems: function() { |
+ this.destroy(); |
+ |
+ assert(this.addItem('checkbox', '#checkbox')); |
+ assert(this.addItem('title', '#title')); |
+ assert(this.addItem('menu-button', '#menu-button')); |
+ |
+ this.addItem('star', '#bookmark-star'); |
+ }, |
+}; |
+ |
cr.define('md_history', function() { |
+ /** |
+ * @param {{lastFocused: Object}} historyItemElement |
Dan Beam
2016/09/15 16:51:10
why this type? avoid circular dependencies?
can w
|
+ * @constructor |
+ * @implements {cr.ui.FocusRow.Delegate} |
+ */ |
+ function FocusRowDelegate(historyItemElement) { |
+ this.historyItemElement = historyItemElement; |
+ } |
+ |
+ FocusRowDelegate.prototype = { |
+ /** |
+ * @override |
+ * @param {!cr.ui.FocusRow} row |
+ * @param {!Event} e |
+ */ |
+ onFocus: function(row, e) { |
+ this.historyItemElement.lastFocused = e.path[0]; |
+ }, |
+ |
+ /** |
+ * @override |
+ * @param {!cr.ui.FocusRow} row The row that detected a keydown. |
+ * @param {!Event} e |
+ * @return {boolean} Whether the event was handled. |
+ */ |
+ onKeydown: function(row, e) { |
+ // Prevent iron-list from changing the focus on enter. |
+ if (e.key == 'Enter') |
+ e.stopPropagation(); |
+ |
+ return false; |
+ }, |
+ }; |
+ |
var HistoryItem = Polymer({ |
is: 'history-item', |
@@ -34,6 +106,64 @@ cr.define('md_history', function() { |
path: String, |
index: Number, |
+ |
+ /** @type {Element} */ |
+ lastFocused: { |
+ type: Object, |
+ notify: true, |
+ }, |
+ |
+ tabIndex: { |
+ type: Number, |
+ observer: 'tabIndexChanged_', |
+ }, |
+ }, |
+ |
+ /** @private {?HistoryFocusRow} */ |
+ row_: null, |
+ |
+ /** @override */ |
+ attached: function() { |
+ Polymer.RenderStatus.afterNextRender(this, function() { |
+ this.row_ = new HistoryFocusRow( |
+ this.$['sizing-container'], null, new FocusRowDelegate(this)); |
+ this.row_.makeActive(this.tabIndex == 0); |
+ this.listen(this, 'focus', 'onFocus_'); |
+ this.listen(this, 'dom-change', 'onDomChange_'); |
+ }); |
+ }, |
+ |
+ /** @override */ |
+ detached: function() { |
+ this.unlisten(this, 'focus', 'onFocus_'); |
+ this.unlisten(this, 'dom-change', 'onDomChange_'); |
+ this.row_.destroy(); |
+ }, |
+ |
+ /** |
+ * @private |
+ */ |
+ onFocus_: function() { |
+ if (this.lastFocused) |
+ this.row_.getEquivalentElement(this.lastFocused).focus(); |
+ else |
+ this.row_.getFirstFocusable().focus(); |
+ }, |
+ |
+ /** |
+ * @private |
+ */ |
+ tabIndexChanged_: function() { |
+ if (this.row_) |
+ this.row_.makeActive(this.tabIndex == 0); |
+ }, |
+ |
+ /** |
+ * @private |
+ */ |
+ onDomChange_: function() { |
+ if (this.row_) |
+ this.row_.addItems(); |
}, |
/** |
@@ -118,7 +248,7 @@ cr.define('md_history', function() { |
/** |
* Record metrics when a result is clicked. This is deliberately tied to |
- * on-click rather than on-tap, as on-click triggers from middle clicks. |
+ * on-click rather than on-tap, as on-click triggers from middle clicks. |
*/ |
onLinkClick_: function() { |
var browserService = md_history.BrowserService.getInstance(); |