| 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 } | 28 }, |
| 29 |
| 30 disabled: { |
| 31 type: Boolean, |
| 32 value: false, |
| 33 observer: '_disabledChanged', |
| 34 }, |
| 29 }, | 35 }, |
| 30 | 36 |
| 37 _SEARCH_RESET_TIMEOUT_MS: 1000, |
| 38 |
| 39 _previousTabIndex: 0, |
| 40 |
| 31 hostAttributes: { | 41 hostAttributes: { |
| 32 'role': 'menu', | 42 'role': 'menu', |
| 33 'tabindex': '0' | |
| 34 }, | 43 }, |
| 35 | 44 |
| 36 observers: [ | 45 observers: [ |
| 37 '_updateMultiselectable(multi)' | 46 '_updateMultiselectable(multi)' |
| 38 ], | 47 ], |
| 39 | 48 |
| 40 listeners: { | 49 listeners: { |
| 41 'focus': '_onFocus', | 50 'focus': '_onFocus', |
| 42 'keydown': '_onKeydown', | 51 'keydown': '_onKeydown', |
| 43 'iron-items-changed': '_onIronItemsChanged' | 52 'iron-items-changed': '_onIronItemsChanged' |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 } | 110 } |
| 102 }, | 111 }, |
| 103 | 112 |
| 104 /** | 113 /** |
| 105 * Given a KeyboardEvent, this method will focus the appropriate item in the | 114 * Given a KeyboardEvent, this method will focus the appropriate item in the |
| 106 * menu (if there is a relevant item, and it is possible to focus it). | 115 * menu (if there is a relevant item, and it is possible to focus it). |
| 107 * | 116 * |
| 108 * @param {KeyboardEvent} event A KeyboardEvent. | 117 * @param {KeyboardEvent} event A KeyboardEvent. |
| 109 */ | 118 */ |
| 110 _focusWithKeyboardEvent: function(event) { | 119 _focusWithKeyboardEvent: function(event) { |
| 120 this.cancelDebouncer('_clearSearchText'); |
| 121 |
| 122 var searchText = this._searchText || ''; |
| 123 var key = event.key && event.key.length == 1 ? event.key : |
| 124 String.fromCharCode(event.keyCode); |
| 125 searchText += key.toLocaleLowerCase(); |
| 126 |
| 127 var searchLength = searchText.length; |
| 128 |
| 111 for (var i = 0, item; item = this.items[i]; i++) { | 129 for (var i = 0, item; item = this.items[i]; i++) { |
| 130 if (item.hasAttribute('disabled')) { |
| 131 continue; |
| 132 } |
| 133 |
| 112 var attr = this.attrForItemTitle || 'textContent'; | 134 var attr = this.attrForItemTitle || 'textContent'; |
| 113 var title = item[attr] || item.getAttribute(attr); | 135 var title = (item[attr] || item.getAttribute(attr) || '').trim(); |
| 114 | 136 |
| 115 if (!item.hasAttribute('disabled') && title && | 137 if (title.length < searchLength) { |
| 116 title.trim().charAt(0).toLowerCase() === String.fromCharCode(event.k
eyCode).toLowerCase()) { | 138 continue; |
| 139 } |
| 140 |
| 141 if (title.slice(0, searchLength).toLocaleLowerCase() == searchText) { |
| 117 this._setFocusedItem(item); | 142 this._setFocusedItem(item); |
| 118 break; | 143 break; |
| 119 } | 144 } |
| 120 } | 145 } |
| 146 |
| 147 this._searchText = searchText; |
| 148 this.debounce('_clearSearchText', this._clearSearchText, |
| 149 this._SEARCH_RESET_TIMEOUT_MS); |
| 150 }, |
| 151 |
| 152 _clearSearchText: function() { |
| 153 this._searchText = ''; |
| 121 }, | 154 }, |
| 122 | 155 |
| 123 /** | 156 /** |
| 124 * Focuses the previous item (relative to the currently focused item) in the | 157 * Focuses the previous item (relative to the currently focused item) in the |
| 125 * menu, disabled items will be skipped. | 158 * menu, disabled items will be skipped. |
| 126 * Loop until length + 1 to handle case of single item in menu. | 159 * Loop until length + 1 to handle case of single item in menu. |
| 127 */ | 160 */ |
| 128 _focusPrevious: function() { | 161 _focusPrevious: function() { |
| 129 var length = this.items.length; | 162 var length = this.items.length; |
| 130 var curFocusIndex = Number(this.indexOf(this.focusedItem)); | 163 var curFocusIndex = Number(this.indexOf(this.focusedItem)); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 /** | 221 /** |
| 189 * Discretely updates tabindex values among menu items as the focused item | 222 * Discretely updates tabindex values among menu items as the focused item |
| 190 * changes. | 223 * changes. |
| 191 * | 224 * |
| 192 * @param {Element} focusedItem The element that is currently focused. | 225 * @param {Element} focusedItem The element that is currently focused. |
| 193 * @param {?Element} old The last element that was considered focused, if | 226 * @param {?Element} old The last element that was considered focused, if |
| 194 * applicable. | 227 * applicable. |
| 195 */ | 228 */ |
| 196 _focusedItemChanged: function(focusedItem, old) { | 229 _focusedItemChanged: function(focusedItem, old) { |
| 197 old && old.setAttribute('tabindex', '-1'); | 230 old && old.setAttribute('tabindex', '-1'); |
| 198 if (focusedItem) { | 231 if (focusedItem && !focusedItem.hasAttribute('disabled') && !this.disabled
) { |
| 199 focusedItem.setAttribute('tabindex', '0'); | 232 focusedItem.setAttribute('tabindex', '0'); |
| 200 focusedItem.focus(); | 233 focusedItem.focus(); |
| 201 } | 234 } |
| 202 }, | 235 }, |
| 203 | 236 |
| 204 /** | 237 /** |
| 205 * A handler that responds to mutation changes related to the list of items | 238 * A handler that responds to mutation changes related to the list of items |
| 206 * in the menu. | 239 * in the menu. |
| 207 * | 240 * |
| 208 * @param {CustomEvent} event An event containing mutation records as its | 241 * @param {CustomEvent} event An event containing mutation records as its |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 // all other keys focus the menu item starting with that character | 345 // all other keys focus the menu item starting with that character |
| 313 this._focusWithKeyboardEvent(event); | 346 this._focusWithKeyboardEvent(event); |
| 314 } | 347 } |
| 315 event.stopPropagation(); | 348 event.stopPropagation(); |
| 316 }, | 349 }, |
| 317 | 350 |
| 318 // override _activateHandler | 351 // override _activateHandler |
| 319 _activateHandler: function(event) { | 352 _activateHandler: function(event) { |
| 320 Polymer.IronSelectableBehavior._activateHandler.call(this, event); | 353 Polymer.IronSelectableBehavior._activateHandler.call(this, event); |
| 321 event.stopPropagation(); | 354 event.stopPropagation(); |
| 355 }, |
| 356 |
| 357 /** |
| 358 * Updates this element's tab index when it's enabled/disabled. |
| 359 * @param {boolean} disabled |
| 360 */ |
| 361 _disabledChanged: function(disabled) { |
| 362 if (disabled) { |
| 363 this._previousTabIndex = this.hasAttribute('tabindex') ? this.tabIndex :
0; |
| 364 this.removeAttribute('tabindex'); // No tabindex means not tab-able or
select-able. |
| 365 } else if (!this.hasAttribute('tabindex')) { |
| 366 this.setAttribute('tabindex', this._previousTabIndex); |
| 367 } |
| 322 } | 368 } |
| 323 }; | 369 }; |
| 324 | 370 |
| 325 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; | 371 Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; |
| 326 | 372 |
| 327 /** @polymerBehavior Polymer.IronMenuBehavior */ | 373 /** @polymerBehavior Polymer.IronMenuBehavior */ |
| 328 Polymer.IronMenuBehavior = [ | 374 Polymer.IronMenuBehavior = [ |
| 329 Polymer.IronMultiSelectableBehavior, | 375 Polymer.IronMultiSelectableBehavior, |
| 330 Polymer.IronA11yKeysBehavior, | 376 Polymer.IronA11yKeysBehavior, |
| 331 Polymer.IronMenuBehaviorImpl | 377 Polymer.IronMenuBehaviorImpl |
| 332 ]; | 378 ]; |
| OLD | NEW |