| OLD | NEW | 
 | (Empty) | 
|    1 <!-- |  | 
|    2 @license |  | 
|    3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. |  | 
|    4 This code may only be used under the BSD style license found at http://polymer.g
     ithub.io/LICENSE.txt |  | 
|    5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |  | 
|    6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
     BUTORS.txt |  | 
|    7 Code distributed by Google as part of the polymer project is also |  | 
|    8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
     TS.txt |  | 
|    9 --> |  | 
|   10  |  | 
|   11 <link rel="import" href="../polymer/polymer.html"> |  | 
|   12 <link rel="import" href="../iron-selector/iron-multi-selectable.html"> |  | 
|   13 <link rel="import" href="../iron-a11y-keys-behavior/iron-a11y-keys-behavior.html
     "> |  | 
|   14  |  | 
|   15 <script> |  | 
|   16  |  | 
|   17   /** |  | 
|   18    * `Polymer.IronMenuBehavior` implements accessible menu behavior. |  | 
|   19    * |  | 
|   20    * @demo demo/index.html |  | 
|   21    * @polymerBehavior Polymer.IronMenuBehavior |  | 
|   22    */ |  | 
|   23   Polymer.IronMenuBehaviorImpl = { |  | 
|   24  |  | 
|   25     properties: { |  | 
|   26  |  | 
|   27       /** |  | 
|   28        * Returns the currently focused item. |  | 
|   29        * |  | 
|   30        * @attribute focusedItem |  | 
|   31        * @type Object |  | 
|   32        */ |  | 
|   33       focusedItem: { |  | 
|   34         observer: '_focusedItemChanged', |  | 
|   35         readOnly: true, |  | 
|   36         type: Object |  | 
|   37       }, |  | 
|   38  |  | 
|   39       /** |  | 
|   40        * The attribute to use on menu items to look up the item title. Typing th
     e first |  | 
|   41        * letter of an item when the menu is open focuses that item. If unset, `t
     extContent` |  | 
|   42        * will be used. |  | 
|   43        * |  | 
|   44        * @attribute attrForItemTitle |  | 
|   45        * @type String |  | 
|   46        */ |  | 
|   47       attrForItemTitle: { |  | 
|   48         type: String |  | 
|   49       } |  | 
|   50     }, |  | 
|   51  |  | 
|   52     hostAttributes: { |  | 
|   53       'role': 'menu', |  | 
|   54       'tabindex': '0' |  | 
|   55     }, |  | 
|   56  |  | 
|   57     observers: [ |  | 
|   58       '_updateMultiselectable(multi)' |  | 
|   59     ], |  | 
|   60  |  | 
|   61     listeners: { |  | 
|   62       'focus': '_onFocus', |  | 
|   63       'keydown': '_onKeydown' |  | 
|   64     }, |  | 
|   65  |  | 
|   66     keyBindings: { |  | 
|   67       'up': '_onUpKey', |  | 
|   68       'down': '_onDownKey', |  | 
|   69       'esc': '_onEscKey', |  | 
|   70       'enter': '_onEnterKey', |  | 
|   71       'shift+tab:keydown': '_onShiftTabDown' |  | 
|   72     }, |  | 
|   73  |  | 
|   74     _updateMultiselectable: function(multi) { |  | 
|   75       if (multi) { |  | 
|   76         this.setAttribute('aria-multiselectable', 'true'); |  | 
|   77       } else { |  | 
|   78         this.removeAttribute('aria-multiselectable'); |  | 
|   79       } |  | 
|   80     }, |  | 
|   81  |  | 
|   82     _onShiftTabDown: function() { |  | 
|   83       var oldTabIndex; |  | 
|   84  |  | 
|   85       Polymer.IronMenuBehaviorImpl._shiftTabPressed = true; |  | 
|   86  |  | 
|   87       oldTabIndex = this.getAttribute('tabindex'); |  | 
|   88  |  | 
|   89       this.setAttribute('tabindex', '-1'); |  | 
|   90  |  | 
|   91       this.async(function() { |  | 
|   92         this.setAttribute('tabindex', oldTabIndex); |  | 
|   93         Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; |  | 
|   94       // Note: polymer/polymer#1305 |  | 
|   95       }, 1); |  | 
|   96     }, |  | 
|   97  |  | 
|   98     _applySelection: function(item, isSelected) { |  | 
|   99       if (isSelected) { |  | 
|  100         item.setAttribute('aria-selected', 'true'); |  | 
|  101       } else { |  | 
|  102         item.removeAttribute('aria-selected'); |  | 
|  103       } |  | 
|  104  |  | 
|  105       Polymer.IronSelectableBehavior._applySelection.apply(this, arguments); |  | 
|  106     }, |  | 
|  107  |  | 
|  108     _focusedItemChanged: function(focusedItem, old) { |  | 
|  109       old && old.setAttribute('tabindex', '-1'); |  | 
|  110       if (focusedItem) { |  | 
|  111         focusedItem.setAttribute('tabindex', '0'); |  | 
|  112         focusedItem.focus(); |  | 
|  113       } |  | 
|  114     }, |  | 
|  115  |  | 
|  116     select: function(value) { |  | 
|  117       if (this._defaultFocusAsync) { |  | 
|  118         this.cancelAsync(this._defaultFocusAsync); |  | 
|  119         this._defaultFocusAsync = null; |  | 
|  120       } |  | 
|  121       var item = this._valueToItem(value); |  | 
|  122       this._setFocusedItem(item); |  | 
|  123       Polymer.IronMultiSelectableBehaviorImpl.select.apply(this, arguments); |  | 
|  124     }, |  | 
|  125  |  | 
|  126     _onFocus: function(event) { |  | 
|  127       if (Polymer.IronMenuBehaviorImpl._shiftTabPressed) { |  | 
|  128         return; |  | 
|  129       } |  | 
|  130       // do not focus the menu itself |  | 
|  131       this.blur(); |  | 
|  132       // clear the cached focus item |  | 
|  133       this._setFocusedItem(null); |  | 
|  134       this._defaultFocusAsync = this.async(function() { |  | 
|  135         // focus the selected item when the menu receives focus, or the first it
     em |  | 
|  136         // if no item is selected |  | 
|  137         var selectedItem = this.multi ? (this.selectedItems && this.selectedItem
     s[0]) : this.selectedItem; |  | 
|  138         if (selectedItem) { |  | 
|  139           this._setFocusedItem(selectedItem); |  | 
|  140         } else { |  | 
|  141           this._setFocusedItem(this.items[0]); |  | 
|  142         } |  | 
|  143       // async 100ms to wait for `select` to get called from `_itemActivate` |  | 
|  144       }, 100); |  | 
|  145     }, |  | 
|  146  |  | 
|  147     _onUpKey: function() { |  | 
|  148       // up and down arrows moves the focus |  | 
|  149       this._focusPrevious(); |  | 
|  150     }, |  | 
|  151  |  | 
|  152     _onDownKey: function() { |  | 
|  153       this._focusNext(); |  | 
|  154     }, |  | 
|  155  |  | 
|  156     _onEscKey: function() { |  | 
|  157       // esc blurs the control |  | 
|  158       this.focusedItem.blur(); |  | 
|  159     }, |  | 
|  160  |  | 
|  161     _onEnterKey: function(event) { |  | 
|  162       // enter activates the item unless it is disabled |  | 
|  163       this._activateFocused(event.detail.keyboardEvent); |  | 
|  164     }, |  | 
|  165  |  | 
|  166     _onKeydown: function(event) { |  | 
|  167       if (this.keyboardEventMatchesKeys(event, 'up down esc enter')) { |  | 
|  168         return; |  | 
|  169       } |  | 
|  170  |  | 
|  171       // all other keys focus the menu item starting with that character |  | 
|  172       this._focusWithKeyboardEvent(event); |  | 
|  173     }, |  | 
|  174  |  | 
|  175     _focusWithKeyboardEvent: function(event) { |  | 
|  176       for (var i = 0, item; item = this.items[i]; i++) { |  | 
|  177         var attr = this.attrForItemTitle || 'textContent'; |  | 
|  178         var title = item[attr] || item.getAttribute(attr); |  | 
|  179         if (title && title.trim().charAt(0).toLowerCase() === String.fromCharCod
     e(event.keyCode).toLowerCase()) { |  | 
|  180           this._setFocusedItem(item); |  | 
|  181           break; |  | 
|  182         } |  | 
|  183       } |  | 
|  184     }, |  | 
|  185  |  | 
|  186     _activateFocused: function(event) { |  | 
|  187       if (!this.focusedItem.hasAttribute('disabled')) { |  | 
|  188         this._activateHandler(event); |  | 
|  189       } |  | 
|  190     }, |  | 
|  191  |  | 
|  192     _focusPrevious: function() { |  | 
|  193       var length = this.items.length; |  | 
|  194       var index = (Number(this.indexOf(this.focusedItem)) - 1 + length) % length
     ; |  | 
|  195       this._setFocusedItem(this.items[index]); |  | 
|  196     }, |  | 
|  197  |  | 
|  198     _focusNext: function() { |  | 
|  199       var index = (Number(this.indexOf(this.focusedItem)) + 1) % this.items.leng
     th; |  | 
|  200       this._setFocusedItem(this.items[index]); |  | 
|  201     } |  | 
|  202  |  | 
|  203   }; |  | 
|  204  |  | 
|  205   Polymer.IronMenuBehaviorImpl._shiftTabPressed = false; |  | 
|  206  |  | 
|  207   /** @polymerBehavior Polymer.IronMenuBehavior */ |  | 
|  208   Polymer.IronMenuBehavior = [ |  | 
|  209     Polymer.IronMultiSelectableBehavior, |  | 
|  210     Polymer.IronA11yKeysBehavior, |  | 
|  211     Polymer.IronMenuBehaviorImpl |  | 
|  212   ]; |  | 
|  213  |  | 
|  214 </script> |  | 
| OLD | NEW |