| Index: ui/webui/resources/js/cr/ui/focus_grid.js
|
| diff --git a/ui/webui/resources/js/cr/ui/focus_grid.js b/ui/webui/resources/js/cr/ui/focus_grid.js
|
| index 2e76ca10c03009f2d5d72e5a781989e1754a00f4..7752ddf9b58186c4fe2e81b7820d62fbd0498c44 100644
|
| --- a/ui/webui/resources/js/cr/ui/focus_grid.js
|
| +++ b/ui/webui/resources/js/cr/ui/focus_grid.js
|
| @@ -18,7 +18,7 @@ cr.define('cr.ui', function() {
|
| * focusable [focused] focusable (row: 1, col: 1)
|
| * focusable focusable focusable
|
| *
|
| - * And pressing right at this point would move the focus to:
|
| + * And pressing right or tab at this point would move the focus to:
|
| *
|
| * focusable focusable focusable
|
| * focusable focusable [focused] (row: 1, col: 2)
|
| @@ -26,7 +26,6 @@ cr.define('cr.ui', function() {
|
| *
|
| * @param {Node=} opt_boundary Ignore focus events outside this node.
|
| * @param {cr.ui.FocusRow.Observer=} opt_observer An observer of rows.
|
| - * @implements {cr.ui.FocusRow.Delegate}
|
| * @constructor
|
| */
|
| function FocusGrid(opt_boundary, opt_observer) {
|
| @@ -38,8 +37,45 @@ cr.define('cr.ui', function() {
|
|
|
| /** @type {!Array.<!cr.ui.FocusRow>} */
|
| this.rows = [];
|
| +
|
| + /** @private {!EventTracker} */
|
| + this.eventTracker_ = new EventTracker;
|
| + this.eventTracker_.add(cr.doc, 'keydown', this.onKeydown_.bind(this));
|
| +
|
| + /** @private {cr.ui.FocusRow.Delegate} */
|
| + this.delegate_ = new FocusGrid.RowDelegate(this);
|
| }
|
|
|
| + /**
|
| + * Row delegate to overwrite the behavior of a mouse click to deselect any row
|
| + * that wasn't clicked.
|
| + * @param {cr.ui.FocusGrid} focusGrid
|
| + * @implements {cr.ui.FocusRow.Delegate}
|
| + */
|
| + FocusGrid.RowDelegate = function(focusGrid) {
|
| + /** @private {cr.ui.FocusGrid} */
|
| + this.focusGrid_ = focusGrid;
|
| + };
|
| + FocusGrid.RowDelegate.prototype = {
|
| + /** @override */
|
| + onKeydown: function(row, e) { return false; },
|
| +
|
| + /** @override */
|
| + onMousedown: function(row, e) {
|
| + // Only care about left mouse click.
|
| + if (e.button)
|
| + return false;
|
| +
|
| + // Focus the clicked row, unfocus all others.
|
| + var rows = this.focusGrid_.rows;
|
| + for (var i = 0; i < rows.length; ++i)
|
| + rows[i].onFocusIdChange(rows[i].getElementId(e.target));
|
| +
|
| + e.preventDefault();
|
| + return true;
|
| + },
|
| + };
|
| +
|
| FocusGrid.prototype = {
|
| /**
|
| * Unregisters event handlers and removes all |this.rows|.
|
| @@ -51,63 +87,85 @@ cr.define('cr.ui', function() {
|
|
|
| /**
|
| * @param {EventTarget} target A target item to find in this grid.
|
| - * @return {?{row: number, col: number}} A position or null if not found.
|
| + * @return {?{row: number, elementId: string}} A position or null if not
|
| + * found.
|
| */
|
| getPositionForTarget: function(target) {
|
| for (var i = 0; i < this.rows.length; ++i) {
|
| - for (var j = 0; j < this.rows[i].items.length; ++j) {
|
| - if (target == this.rows[i].items[j])
|
| - return {row: i, col: j};
|
| - }
|
| + var elementId = this.rows[i].getElementId(target);
|
| + if (elementId)
|
| + return { row: i, elementId: elementId };
|
| }
|
| return null;
|
| },
|
|
|
| - /** @override */
|
| - onKeydown: function(keyRow, e) {
|
| - var rowIndex = this.rows.indexOf(keyRow);
|
| - assert(rowIndex >= 0);
|
| + /**
|
| + * Handles keyboard shortcuts to move up/down in the grid.
|
| + * @param {Event} e The key event.
|
| + */
|
| + onKeydown_: function(e) {
|
| + var pos = this.getPositionForTarget(e.target);
|
| + if (!pos)
|
| + return;
|
|
|
| var row = -1;
|
|
|
| if (e.keyIdentifier == 'Up')
|
| - row = rowIndex - 1;
|
| + row = pos.row - 1;
|
| else if (e.keyIdentifier == 'Down')
|
| - row = rowIndex + 1;
|
| + row = pos.row + 1;
|
| else if (e.keyIdentifier == 'PageUp')
|
| row = 0;
|
| else if (e.keyIdentifier == 'PageDown')
|
| row = this.rows.length - 1;
|
|
|
| if (!this.rows[row])
|
| - return false;
|
| + return;
|
|
|
| - var colIndex = keyRow.items.indexOf(e.target);
|
| - var col = Math.min(colIndex, this.rows[row].items.length - 1);
|
| -
|
| - this.rows[row].focusIndex(col);
|
| + // Allow a grid to remember the elementId if a column is missing from a
|
| + // row. The elementId is reset if the column focus changed while the row
|
| + // was focused.
|
| + if (!this.rememberedId || this.rows[pos.row].focusChanged())
|
| + this.rememberedId = pos.elementId;
|
|
|
| + this.rows[row].setFocusId(this.rememberedId);
|
| + this.rows[row].trackFocus();
|
| e.preventDefault();
|
| - return true;
|
| },
|
|
|
| - /** @override */
|
| - onMousedown: function(row, e) {
|
| - return false;
|
| + /**
|
| + * Create a new FocusRow for this grid and return it.
|
| + * This row will need to be added to the grid using addRow.
|
| + * @return {cr.ui.FocusRow} The row that was added to the grid.
|
| + */
|
| + createRow: function() {
|
| + return new cr.ui.FocusRow(this.boundary_, this.delegate_, this.observer_);
|
| },
|
|
|
| /**
|
| - * @param {!Array.<!NodeList|!Array.<!Element>>} grid A 2D array of nodes.
|
| + * Add a FocusRow to this grid. This needs to be called AFTER adding columns
|
| + * to the row. This is so that TAB focus can be properly enabled in the
|
| + * columns.
|
| + * @param {cr.ui.FocusRow} row The row that needs to be added to this grid.
|
| */
|
| - setGrid: function(grid) {
|
| - this.destroy();
|
| -
|
| - this.rows = grid.map(function(row) {
|
| - return new cr.ui.FocusRow(row, this.boundary_, this, this.observer_);
|
| - }, this);
|
| + addRow: function(row) {
|
| + if (this.rows.length == 0) {
|
| + // Focus the first row.
|
| + row.setInitialFocus(true);
|
| + }
|
| + else {
|
| + if (row.getElementId(document.activeElement)) {
|
| + // Update focus if the current row is active.
|
| + this.rows[0].setInitialFocus(false);
|
| + row.setInitialFocus(true);
|
| + } else {
|
| + // Make sure initial focus is false if the row isn't active.
|
| + row.setInitialFocus(false);
|
| + }
|
| + }
|
|
|
| - if (!this.getPositionForTarget(document.activeElement) && this.rows[0])
|
| - this.rows[0].activeIndex = 0;
|
| + // Add the row after its initial focus is set.
|
| + this.rows.push(row);
|
| },
|
| };
|
|
|
|
|