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

Side by Side Diff: chrome/browser/resources/settings/focus_row_behavior.js

Issue 2749513004: MD Settings: adjust iron-list focus row behaviors. (Closed)
Patch Set: add tests for new focusRowBehavior Created 3 years, 9 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
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6 * @param {{lastFocused: Object}} listItem
7 * @constructor
8 * @implements {cr.ui.FocusRow.Delegate}
9 */
10 function FocusRowDelegate(listItem) {
11 this.listItem = listItem;
12 }
13
14 FocusRowDelegate.prototype = {
15 /**
16 * @override
17 * @param {!cr.ui.FocusRow} row
18 * @param {!Event} e
19 */
20 onFocus: function(row, e) {
21 this.listItem.lastFocused = e.path[0];
22 },
23
24 /**
25 * @override
26 * @param {!cr.ui.FocusRow} row The row that detected a keydown.
27 * @param {!Event} e
28 * @return {boolean} Whether the event was handled.
29 */
30 onKeydown: function(row, e) {
31 // Prevent iron-list from changing the focus on enter.
32 if (e.key == 'Enter')
33 e.stopPropagation();
34
35 return false;
36 },
37 };
38
39 /**
40 * @param {!Element} root
41 * @param {?Element} boundary
42 * @param {cr.ui.FocusRow.Delegate} delegate
43 * @constructor
44 * @extends {cr.ui.FocusRow}
45 */
46 function VirtualFocusRow(root, boundary, delegate) {
hcarmona 2017/03/16 21:31:54 boundary is not used. Can we get rid of it and add
scottchen 2017/03/17 21:26:58 Good idea.
47 cr.ui.FocusRow.call(this, root, boundary, delegate);
48 }
49
50 VirtualFocusRow.prototype = {
51 __proto__: cr.ui.FocusRow.prototype
52 };
53
54
55 /**
56 * Any element that is being used as an iron-list row item can extend this
57 * behavior, which encapsulates focus controls of mouse and keyboards.
58 * To use this behavior:
59 * - The parent element should pass a "last-focused" attribute double-bound
60 * to the row items, to track the last-focused element across rows.
61 * - There must be a container in the extending element with the
62 * [focus-row-container] attribute that contains all focusable controls.
63 * - On each of the focusable controls, there must be a [focus-row-control]
64 * attribute, and a [type=] attribute unique for each type of control.
65 *
66 * @polymerBehavior
67 */
68 var FocusRowBehavior = {
69 properties: {
70 /** @private {VirtualFocusRow} */
71 row_: Object,
72
73 /** @private {boolean} */
74 mouseFocused_: Boolean,
75
76 /** @type {Element} */
77 lastFocused: {
78 type: Object,
79 notify: true,
80 },
81
82 /** @type {number} */
83 ironListTabIndex: {
hcarmona 2017/03/16 21:31:54 This seems a bit redundant, can we use |tabindex|
scottchen 2017/03/17 21:26:58 They're actually not always the same since the tem
hcarmona 2017/03/17 23:55:50 SG, can we add a quick comment to explain that her
scottchen 2017/03/18 01:05:47 Done.
84 type: Number,
85 observer: 'ironListTabIndexChanged_',
86 },
87 },
88
89 /** @override */
90 attached: function() {
91 this.classList.add('no-outline');
92
93 Polymer.RenderStatus.afterNextRender(this, function() {
94 var rowContainer = this.root.querySelector('[focus-row-container]');
95 assert(!!rowContainer);
96 this.row_ =
97 new VirtualFocusRow(rowContainer, null, new FocusRowDelegate(this));
98 this.row_.makeActive(this.ironListTabIndex == 0);
99 this.addItems_();
hcarmona 2017/03/16 21:31:54 Should addItems_ be called before makeActive?
scottchen 2017/03/17 21:26:58 Either way is fine, row_.makeActive() and row_.add
hcarmona 2017/03/17 23:55:50 Acknowledged.
100
101 // Adding listeners asynchronously to reduce blocking time, since this
102 // behavior will be used by items in potentially long lists.
103 this.listen(this, 'focus', 'onFocus_');
104 this.listen(this, 'dom-change', 'onDomChange_');
hcarmona 2017/03/16 21:31:54 Can this just call addItems_ directly?
scottchen 2017/03/17 21:26:58 Yep!
105 this.listen(this, 'mousedown', 'onMouseDown_');
106 this.listen(this, 'blur', 'onBlur_');
107 });
hcarmona 2017/03/16 21:31:54 I think you're missing a .bind(this) on your funct
scottchen 2017/03/17 21:26:58 "this" is provided as the first element of the aft
hcarmona 2017/03/17 23:55:50 Acknowledged.
108 },
109
110 /** @override */
111 detached: function() {
112 this.unlisten(this, 'focus', 'onFocus_');
113 this.unlisten(this, 'dom-change', 'onDomChange_');
114 this.unlisten(this, 'mousedown', 'onMouseDown_');
115 this.unlisten(this, 'blur', 'onBlur_');
116 if (this.row_)
117 this.row_.destroy();
118 },
119
120 /** @private */
121 addItems_: function() {
122 if (this.row_) {
123 this.row_.destroy();
124
125 var controls = this.root.querySelectorAll('[focus-row-control]');
126 for (var i = 0; i < controls.length; i++) {
127 this.row_.addItem(
128 controls[i].getAttribute('type'),
129 /** @type {HTMLElement} */ (controls[i]));
130 }
131 }
132 },
133
134 /** @private */
135 onFocus_: function() {
136 if (this.mouseFocused_) {
137 this.mouseFocused_ = false; // Consume and reset flag.
138 return;
139 }
140
141 if (this.lastFocused)
142 this.row_.getEquivalentElement(this.lastFocused).focus();
143 else
144 this.row_.getFirstFocusable().focus();
145
146 this.tabIndex = -1;
hcarmona 2017/03/16 21:31:54 Why are we setting the tabindex to -1 here? Do we
scottchen 2017/03/17 21:26:58 It's to make the row itself back to an "unselectab
hcarmona 2017/03/17 23:55:50 What happens if you tab away, can it be focused ag
scottchen 2017/03/18 01:05:46 Yeah, since now the child's tabindex would be 0.
147 },
148
149 /** @private */
150 ironListTabIndexChanged_: function() {
151 if (this.row_)
152 this.row_.makeActive(this.ironListTabIndex == 0);
153 },
154
155 /** @private */
156 onDomChange_: function() {
157 this.addItems_();
158 },
159
160 /** @private */
161 onMouseDown_: function() {
162 this.mouseFocused_ = true; // Set flag to not do any control-focusing.
163 },
164
165 /** @private */
166 onBlur_: function() {
167 this.mouseFocused_ = false; // Reset flag since it's not active anymore.
168 }
169 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698