Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /** | 1 /** |
| 2 * `Polymer.IronMenuBehavior` implements accessible menu behavior. | 2 * `Polymer.IronMenuBehavior` implements accessible menu behavior. |
| 3 * | 3 * |
| 4 * @demo demo/index.html | 4 * @demo demo/index.html |
| 5 * @polymerBehavior Polymer.IronMenuBehavior | 5 * @polymerBehavior Polymer.IronMenuBehavior |
| 6 */ | 6 */ |
| 7 Polymer.IronMenuBehaviorImpl = { | 7 Polymer.IronMenuBehaviorImpl = { |
| 8 | 8 |
| 9 properties: { | 9 properties: { |
| 10 | 10 |
| 11 /** | 11 /** |
| 12 * Returns the currently focused item. | 12 * Returns the currently focused item. |
| 13 * @type {?Object} | 13 * @type {?Object} |
| 14 */ | 14 */ |
| 15 focusedItem: { | 15 focusedItem: { |
| 16 observer: '_focusedItemChanged', | 16 observer: '_focusedItemChanged', |
| 17 readOnly: true, | 17 readOnly: true, |
| 18 type: Object | 18 type: Object |
| 19 }, | 19 }, |
| 20 | 20 |
| 21 /** | 21 /** |
| 22 * The attribute to use on menu items to look up the item title. Typing th e first | 22 * The attribute to use on menu items to look up the item title. Typing th e first |
| 23 * letter of an item when the menu is open focuses that item. If unset, `t extContent` | 23 * letter of an item when the menu is open focuses that item. If unset, `t extContent` |
| 24 * will be used. | 24 * will be used. |
| 25 */ | 25 */ |
| 26 attrForItemTitle: { | 26 attrForItemTitle: { |
| 27 type: String | 27 type: String |
| 28 }, | |
| 29 | |
| 30 disabled: { | |
| 31 type: Boolean, | |
| 32 value: false, | |
| 33 reflectToAttribute: true, | |
| 34 observer: '_disableTabindex', | |
| 28 } | 35 } |
| 29 }, | 36 }, |
| 30 | 37 |
| 31 hostAttributes: { | 38 hostAttributes: { |
| 32 'role': 'menu', | 39 'role': 'menu', |
| 33 'tabindex': '0' | |
| 34 }, | 40 }, |
| 35 | 41 |
| 36 observers: [ | 42 observers: [ |
| 37 '_updateMultiselectable(multi)' | 43 '_updateMultiselectable(multi)' |
| 38 ], | 44 ], |
| 39 | 45 |
| 40 listeners: { | 46 listeners: { |
| 41 'focus': '_onFocus', | 47 'focus': '_onFocus', |
| 42 'keydown': '_onKeydown', | 48 'keydown': '_onKeydown', |
| 43 'iron-items-changed': '_onIronItemsChanged' | 49 'iron-items-changed': '_onIronItemsChanged' |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 /** | 82 /** |
| 77 * Resets all tabindex attributes to the appropriate value based on the | 83 * Resets all tabindex attributes to the appropriate value based on the |
| 78 * current selection state. The appropriate value is `0` (focusable) for | 84 * current selection state. The appropriate value is `0` (focusable) for |
| 79 * the default selected item, and `-1` (not keyboard focusable) for all | 85 * the default selected item, and `-1` (not keyboard focusable) for all |
| 80 * other items. | 86 * other items. |
| 81 */ | 87 */ |
| 82 _resetTabindices: function() { | 88 _resetTabindices: function() { |
| 83 var selectedItem = this.multi ? (this.selectedItems && this.selectedItems[ 0]) : this.selectedItem; | 89 var selectedItem = this.multi ? (this.selectedItems && this.selectedItems[ 0]) : this.selectedItem; |
| 84 | 90 |
| 85 this.items.forEach(function(item) { | 91 this.items.forEach(function(item) { |
| 86 item.setAttribute('tabindex', item === selectedItem ? '0' : '-1'); | 92 // Don't enable tab index if an item is disabled, even if it's selected. |
| 93 if (item === selectedItem && !selectedItem.hasAttribute('disabled') && ! this.disabled) | |
| 94 item.setAttribute('tabindex', 0); | |
| 95 else | |
| 96 item.removeAttribute('tabindex'); | |
| 87 }, this); | 97 }, this); |
| 88 }, | 98 }, |
| 89 | 99 |
| 90 /** | 100 /** |
| 91 * Sets appropriate ARIA based on whether or not the menu is meant to be | 101 * Sets appropriate ARIA based on whether or not the menu is meant to be |
| 92 * multi-selectable. | 102 * multi-selectable. |
| 93 * | 103 * |
| 94 * @param {boolean} multi True if the menu should be multi-selectable. | 104 * @param {boolean} multi True if the menu should be multi-selectable. |
| 95 */ | 105 */ |
| 96 _updateMultiselectable: function(multi) { | 106 _updateMultiselectable: function(multi) { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 | 197 |
| 188 /** | 198 /** |
| 189 * Discretely updates tabindex values among menu items as the focused item | 199 * Discretely updates tabindex values among menu items as the focused item |
| 190 * changes. | 200 * changes. |
| 191 * | 201 * |
| 192 * @param {Element} focusedItem The element that is currently focused. | 202 * @param {Element} focusedItem The element that is currently focused. |
| 193 * @param {?Element} old The last element that was considered focused, if | 203 * @param {?Element} old The last element that was considered focused, if |
| 194 * applicable. | 204 * applicable. |
| 195 */ | 205 */ |
| 196 _focusedItemChanged: function(focusedItem, old) { | 206 _focusedItemChanged: function(focusedItem, old) { |
| 197 old && old.setAttribute('tabindex', '-1'); | 207 old && old.removeAttribute('tabindex'); |
| 198 if (focusedItem) { | 208 if (focusedItem && !focusedItem.hasAttribute('disabled') && !this.disabled ) { |
| 199 focusedItem.setAttribute('tabindex', '0'); | 209 focusedItem.setAttribute('tabindex', '0'); |
| 200 focusedItem.focus(); | 210 focusedItem.focus(); |
| 201 } | 211 } |
| 202 }, | 212 }, |
| 203 | 213 |
| 204 /** | 214 /** |
| 205 * A handler that responds to mutation changes related to the list of items | 215 * A handler that responds to mutation changes related to the list of items |
| 206 * in the menu. | 216 * in the menu. |
| 207 * | 217 * |
| 208 * @param {CustomEvent} event An event containing mutation records as its | 218 * @param {CustomEvent} event An event containing mutation records as its |
| 209 * detail. | 219 * detail. |
| 210 */ | 220 */ |
| 211 _onIronItemsChanged: function(event) { | 221 _onIronItemsChanged: function(event) { |
| 212 if (event.detail.addedNodes.length) { | 222 if (event.detail.addedNodes.length) { |
| 213 this._resetTabindices(); | 223 this._resetTabindices(); |
| 214 } | 224 } |
| 215 }, | 225 }, |
| 216 | 226 |
| 217 /** | 227 /** |
| 218 * Handler that is called when a shift+tab keypress is detected by the menu. | 228 * Handler that is called when a shift+tab keypress is detected by the menu. |
| 219 * | 229 * |
| 220 * @param {CustomEvent} event A key combination event. | 230 * @param {CustomEvent} event A key combination event. |
| 221 */ | 231 */ |
| 222 _onShiftTabDown: function(event) { | 232 _onShiftTabDown: function(event) { |
| 223 var oldTabIndex = this.getAttribute('tabindex'); | 233 var couldTab = this.getAttribute('tabindex') == 0; |
| 224 | 234 |
| 225 Polymer.IronMenuBehaviorImpl._shiftTabPressed = true; | 235 Polymer.IronMenuBehaviorImpl._shiftTabPressed = true; |
| 226 | 236 |
| 227 this._setFocusedItem(null); | 237 this._setFocusedItem(null); |
| 228 | 238 |
| 229 this.setAttribute('tabindex', '-1'); | 239 this._disableTabindex(true); |
| 230 | 240 |
| 231 this.async(function() { | 241 this.async(function() { |
| 232 this.setAttribute('tabindex', oldTabIndex); | 242 this._disableTabindex(!couldTab); |
|
Dan Beam
2017/03/17 23:58:53
indent off
hcarmona
2017/03/18 01:05:07
Done.
| |
| 233 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; | 243 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; |
| 234 // NOTE(cdata): polymer/polymer#1305 | 244 // NOTE(cdata): polymer/polymer#1305 |
| 235 }, 1); | 245 }, 1); |
| 236 }, | 246 }, |
| 237 | 247 |
| 238 /** | 248 /** |
| 239 * Handler that is called when the menu receives focus. | 249 * Handler that is called when the menu receives focus. |
| 240 * | 250 * |
| 241 * @param {FocusEvent} event A focus event. | 251 * @param {FocusEvent} event A focus event. |
| 242 */ | 252 */ |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 // all other keys focus the menu item starting with that character | 322 // all other keys focus the menu item starting with that character |
| 313 this._focusWithKeyboardEvent(event); | 323 this._focusWithKeyboardEvent(event); |
| 314 } | 324 } |
| 315 event.stopPropagation(); | 325 event.stopPropagation(); |
| 316 }, | 326 }, |
| 317 | 327 |
| 318 // override _activateHandler | 328 // override _activateHandler |
| 319 _activateHandler: function(event) { | 329 _activateHandler: function(event) { |
| 320 Polymer.IronSelectableBehavior._activateHandler.call(this, event); | 330 Polymer.IronSelectableBehavior._activateHandler.call(this, event); |
| 321 event.stopPropagation(); | 331 event.stopPropagation(); |
| 332 }, | |
| 333 | |
| 334 /** | |
| 335 * Updates this element's tab index when it's enabled/disabled. | |
| 336 * @param {boolean} disabled | |
| 337 */ | |
| 338 _disableTabindex: function(disabled) { | |
| 339 if (disabled) | |
| 340 this.removeAttribute('tabindex'); // No tabindex means not tab-able or select-able. | |
| 341 else | |
| 342 this.setAttribute('tabindex', 0); // tabindex of 0 means tab-able. | |
| 322 } | 343 } |
| 323 }; | 344 }; |
| 324 | 345 |
| 325 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; | 346 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; |
| 326 | 347 |
| 327 /** @polymerBehavior Polymer.IronMenuBehavior */ | 348 /** @polymerBehavior Polymer.IronMenuBehavior */ |
| 328 Polymer.IronMenuBehavior = [ | 349 Polymer.IronMenuBehavior = [ |
| 329 Polymer.IronMultiSelectableBehavior, | 350 Polymer.IronMultiSelectableBehavior, |
| 330 Polymer.IronA11yKeysBehavior, | 351 Polymer.IronA11yKeysBehavior, |
| 331 Polymer.IronMenuBehaviorImpl | 352 Polymer.IronMenuBehaviorImpl |
| 332 ]; | 353 ]; |
| OLD | NEW |