| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 |  | 
| 2   (function() { |  | 
| 3     /* |  | 
| 4      * Chrome uses an older version of DOM Level 3 Keyboard Events |  | 
| 5      * |  | 
| 6      * Most keys are labeled as text, but some are Unicode codepoints. |  | 
| 7      * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-200712
     21/keyset.html#KeySet-Set |  | 
| 8      */ |  | 
| 9     var KEY_IDENTIFIER = { |  | 
| 10       'U+0009': 'tab', |  | 
| 11       'U+001B': 'esc', |  | 
| 12       'U+0020': 'space', |  | 
| 13       'U+002A': '*', |  | 
| 14       'U+0030': '0', |  | 
| 15       'U+0031': '1', |  | 
| 16       'U+0032': '2', |  | 
| 17       'U+0033': '3', |  | 
| 18       'U+0034': '4', |  | 
| 19       'U+0035': '5', |  | 
| 20       'U+0036': '6', |  | 
| 21       'U+0037': '7', |  | 
| 22       'U+0038': '8', |  | 
| 23       'U+0039': '9', |  | 
| 24       'U+0041': 'a', |  | 
| 25       'U+0042': 'b', |  | 
| 26       'U+0043': 'c', |  | 
| 27       'U+0044': 'd', |  | 
| 28       'U+0045': 'e', |  | 
| 29       'U+0046': 'f', |  | 
| 30       'U+0047': 'g', |  | 
| 31       'U+0048': 'h', |  | 
| 32       'U+0049': 'i', |  | 
| 33       'U+004A': 'j', |  | 
| 34       'U+004B': 'k', |  | 
| 35       'U+004C': 'l', |  | 
| 36       'U+004D': 'm', |  | 
| 37       'U+004E': 'n', |  | 
| 38       'U+004F': 'o', |  | 
| 39       'U+0050': 'p', |  | 
| 40       'U+0051': 'q', |  | 
| 41       'U+0052': 'r', |  | 
| 42       'U+0053': 's', |  | 
| 43       'U+0054': 't', |  | 
| 44       'U+0055': 'u', |  | 
| 45       'U+0056': 'v', |  | 
| 46       'U+0057': 'w', |  | 
| 47       'U+0058': 'x', |  | 
| 48       'U+0059': 'y', |  | 
| 49       'U+005A': 'z', |  | 
| 50       'U+007F': 'del' |  | 
| 51     }; |  | 
| 52 |  | 
| 53     /* |  | 
| 54      * Special table for KeyboardEvent.keyCode. |  | 
| 55      * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even bett
     er than that |  | 
| 56      * |  | 
| 57      * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEve
     nt.keyCode#Value_of_keyCode |  | 
| 58      */ |  | 
| 59     var KEY_CODE = { |  | 
| 60       9: 'tab', |  | 
| 61       13: 'enter', |  | 
| 62       27: 'esc', |  | 
| 63       33: 'pageup', |  | 
| 64       34: 'pagedown', |  | 
| 65       35: 'end', |  | 
| 66       36: 'home', |  | 
| 67       32: 'space', |  | 
| 68       37: 'left', |  | 
| 69       38: 'up', |  | 
| 70       39: 'right', |  | 
| 71       40: 'down', |  | 
| 72       46: 'del', |  | 
| 73       106: '*' |  | 
| 74     }; |  | 
| 75 |  | 
| 76     /* |  | 
| 77      * KeyboardEvent.key is mostly represented by printable character made by th
     e keyboard, with unprintable keys labeled |  | 
| 78      * nicely. |  | 
| 79      * |  | 
| 80      * However, on OS X, Alt+char can make a Unicode character that follows an A
     pple-specific mapping. In this case, we |  | 
| 81      * fall back to .keyCode. |  | 
| 82      */ |  | 
| 83     var KEY_CHAR = /[a-z0-9*]/; |  | 
| 84 |  | 
| 85     function transformKey(key) { |  | 
| 86       var validKey = ''; |  | 
| 87       if (key) { |  | 
| 88         var lKey = key.toLowerCase(); |  | 
| 89         if (lKey.length == 1) { |  | 
| 90           if (KEY_CHAR.test(lKey)) { |  | 
| 91             validKey = lKey; |  | 
| 92           } |  | 
| 93         } else if (lKey == 'multiply') { |  | 
| 94           // numpad '*' can map to Multiply on IE/Windows |  | 
| 95           validKey = '*'; |  | 
| 96         } else { |  | 
| 97           validKey = lKey; |  | 
| 98         } |  | 
| 99       } |  | 
| 100       return validKey; |  | 
| 101     } |  | 
| 102 |  | 
| 103     var IDENT_CHAR = /U\+/; |  | 
| 104     function transformKeyIdentifier(keyIdent) { |  | 
| 105       var validKey = ''; |  | 
| 106       if (keyIdent) { |  | 
| 107         if (IDENT_CHAR.test(keyIdent)) { |  | 
| 108           validKey = KEY_IDENTIFIER[keyIdent]; |  | 
| 109         } else { |  | 
| 110           validKey = keyIdent.toLowerCase(); |  | 
| 111         } |  | 
| 112       } |  | 
| 113       return validKey; |  | 
| 114     } |  | 
| 115 |  | 
| 116     function transformKeyCode(keyCode) { |  | 
| 117       var validKey = ''; |  | 
| 118       if (Number(keyCode)) { |  | 
| 119         if (keyCode >= 65 && keyCode <= 90) { |  | 
| 120           // ascii a-z |  | 
| 121           // lowercase is 32 offset from uppercase |  | 
| 122           validKey = String.fromCharCode(32 + keyCode); |  | 
| 123         } else if (keyCode >= 112 && keyCode <= 123) { |  | 
| 124           // function keys f1-f12 |  | 
| 125           validKey = 'f' + (keyCode - 112); |  | 
| 126         } else if (keyCode >= 48 && keyCode <= 57) { |  | 
| 127           // top 0-9 keys |  | 
| 128           validKey = String(48 - keyCode); |  | 
| 129         } else if (keyCode >= 96 && keyCode <= 105) { |  | 
| 130           // num pad 0-9 |  | 
| 131           validKey = String(96 - keyCode); |  | 
| 132         } else { |  | 
| 133           validKey = KEY_CODE[keyCode]; |  | 
| 134         } |  | 
| 135       } |  | 
| 136       return validKey; |  | 
| 137     } |  | 
| 138 |  | 
| 139     function keyboardEventToKey(ev) { |  | 
| 140       // fall back from .key, to .keyIdentifier, to .keyCode, and then to .detai
     l.key to support artificial keyboard events |  | 
| 141       var normalizedKey = transformKey(ev.key) || transformKeyIdentifier(ev.keyI
     dentifier) || transformKeyCode(ev.keyCode) || transformKey(ev.detail.key) || ''; |  | 
| 142       return { |  | 
| 143         shift: ev.shiftKey, |  | 
| 144         ctrl: ev.ctrlKey, |  | 
| 145         meta: ev.metaKey, |  | 
| 146         alt: ev.altKey, |  | 
| 147         key: normalizedKey |  | 
| 148       }; |  | 
| 149     } |  | 
| 150 |  | 
| 151     /* |  | 
| 152      * Input: ctrl+shift+f7 => {ctrl: true, shift: true, key: 'f7'} |  | 
| 153      * ctrl/space => {ctrl: true} || {key: space} |  | 
| 154      */ |  | 
| 155     function stringToKey(keyCombo) { |  | 
| 156       var keys = keyCombo.split('+'); |  | 
| 157       var keyObj = Object.create(null); |  | 
| 158       keys.forEach(function(key) { |  | 
| 159         if (key == 'shift') { |  | 
| 160           keyObj.shift = true; |  | 
| 161         } else if (key == 'ctrl') { |  | 
| 162           keyObj.ctrl = true; |  | 
| 163         } else if (key == 'alt') { |  | 
| 164           keyObj.alt = true; |  | 
| 165         } else { |  | 
| 166           keyObj.key = key; |  | 
| 167         } |  | 
| 168       }); |  | 
| 169       return keyObj; |  | 
| 170     } |  | 
| 171 |  | 
| 172     function keyMatches(a, b) { |  | 
| 173       return Boolean(a.alt) == Boolean(b.alt) && Boolean(a.ctrl) == Boolean(b.ct
     rl) && Boolean(a.shift) == Boolean(b.shift) && a.key === b.key; |  | 
| 174     } |  | 
| 175 |  | 
| 176     /** |  | 
| 177      * Fired when a keycombo in `keys` is pressed. |  | 
| 178      * |  | 
| 179      * @event keys-pressed |  | 
| 180      */ |  | 
| 181     function processKeys(ev) { |  | 
| 182       var current = keyboardEventToKey(ev); |  | 
| 183       for (var i = 0, dk; i < this._desiredKeys.length; i++) { |  | 
| 184         dk = this._desiredKeys[i]; |  | 
| 185         if (keyMatches(dk, current)) { |  | 
| 186           ev.preventDefault(); |  | 
| 187           ev.stopPropagation(); |  | 
| 188           this.fire('keys-pressed', current, this, false); |  | 
| 189           break; |  | 
| 190         } |  | 
| 191       } |  | 
| 192     } |  | 
| 193 |  | 
| 194     function listen(node, handler) { |  | 
| 195       if (node && node.addEventListener) { |  | 
| 196         node.addEventListener('keydown', handler); |  | 
| 197       } |  | 
| 198     } |  | 
| 199 |  | 
| 200     function unlisten(node, handler) { |  | 
| 201       if (node && node.removeEventListener) { |  | 
| 202         node.removeEventListener('keydown', handler); |  | 
| 203       } |  | 
| 204     } |  | 
| 205 |  | 
| 206     Polymer('core-a11y-keys', { |  | 
| 207       created: function() { |  | 
| 208         this._keyHandler = processKeys.bind(this); |  | 
| 209       }, |  | 
| 210       attached: function() { |  | 
| 211         if (!this.target) { |  | 
| 212           this.target = this.parentNode; |  | 
| 213         } |  | 
| 214         listen(this.target, this._keyHandler); |  | 
| 215       }, |  | 
| 216       detached: function() { |  | 
| 217         unlisten(this.target, this._keyHandler); |  | 
| 218       }, |  | 
| 219       publish: { |  | 
| 220         /** |  | 
| 221          * The set of key combinations to listen for. |  | 
| 222          * |  | 
| 223          * @attribute keys |  | 
| 224          * @type string (keys syntax) |  | 
| 225          * @default '' |  | 
| 226          */ |  | 
| 227         keys: '', |  | 
| 228         /** |  | 
| 229          * The node that will fire keyboard events. |  | 
| 230          * Default to this element's parentNode unless one is assigned |  | 
| 231          * |  | 
| 232          * @attribute target |  | 
| 233          * @type Node |  | 
| 234          * @default this.parentNode |  | 
| 235          */ |  | 
| 236         target: null |  | 
| 237       }, |  | 
| 238       keysChanged: function() { |  | 
| 239         // * can have multiple mappings: shift+8, * on numpad or Multiply on num
     pad |  | 
| 240         var normalized = this.keys.replace('*', '* shift+*'); |  | 
| 241         this._desiredKeys = normalized.toLowerCase().split(' ').map(stringToKey)
     ; |  | 
| 242       }, |  | 
| 243       targetChanged: function(oldTarget) { |  | 
| 244         unlisten(oldTarget, this._keyHandler); |  | 
| 245         listen(this.target, this._keyHandler); |  | 
| 246       } |  | 
| 247     }); |  | 
| 248   })(); |  | 
| OLD | NEW | 
|---|