| OLD | NEW |
| 1 <!-- | 1 <!-- |
| 2 @license | 2 @license |
| 3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved. | 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 | 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 | 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 | 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 | 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 | 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --> | 9 --> |
| 10 | 10 |
| 11 <link rel="import" href="../polymer/polymer.html"> | 11 <link rel="import" href="../polymer/polymer.html"> |
| 12 | 12 |
| 13 <script> | 13 <script> |
| 14 (function() { | 14 (function() { |
| 15 'use strict'; | 15 'use strict'; |
| 16 | 16 |
| 17 /** | 17 /** |
| 18 * Chrome uses an older version of DOM Level 3 Keyboard Events | 18 * Chrome uses an older version of DOM Level 3 Keyboard Events |
| 19 * | 19 * |
| 20 * Most keys are labeled as text, but some are Unicode codepoints. | 20 * Most keys are labeled as text, but some are Unicode codepoints. |
| 21 * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-200712
21/keyset.html#KeySet-Set | 21 * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-200712
21/keyset.html#KeySet-Set |
| 22 */ | 22 */ |
| 23 var KEY_IDENTIFIER = { | 23 var KEY_IDENTIFIER = { |
| 24 'U+0008': 'backspace', |
| 24 'U+0009': 'tab', | 25 'U+0009': 'tab', |
| 25 'U+001B': 'esc', | 26 'U+001B': 'esc', |
| 26 'U+0020': 'space', | 27 'U+0020': 'space', |
| 27 'U+002A': '*', | |
| 28 'U+0030': '0', | |
| 29 'U+0031': '1', | |
| 30 'U+0032': '2', | |
| 31 'U+0033': '3', | |
| 32 'U+0034': '4', | |
| 33 'U+0035': '5', | |
| 34 'U+0036': '6', | |
| 35 'U+0037': '7', | |
| 36 'U+0038': '8', | |
| 37 'U+0039': '9', | |
| 38 'U+0041': 'a', | |
| 39 'U+0042': 'b', | |
| 40 'U+0043': 'c', | |
| 41 'U+0044': 'd', | |
| 42 'U+0045': 'e', | |
| 43 'U+0046': 'f', | |
| 44 'U+0047': 'g', | |
| 45 'U+0048': 'h', | |
| 46 'U+0049': 'i', | |
| 47 'U+004A': 'j', | |
| 48 'U+004B': 'k', | |
| 49 'U+004C': 'l', | |
| 50 'U+004D': 'm', | |
| 51 'U+004E': 'n', | |
| 52 'U+004F': 'o', | |
| 53 'U+0050': 'p', | |
| 54 'U+0051': 'q', | |
| 55 'U+0052': 'r', | |
| 56 'U+0053': 's', | |
| 57 'U+0054': 't', | |
| 58 'U+0055': 'u', | |
| 59 'U+0056': 'v', | |
| 60 'U+0057': 'w', | |
| 61 'U+0058': 'x', | |
| 62 'U+0059': 'y', | |
| 63 'U+005A': 'z', | |
| 64 'U+007F': 'del' | 28 'U+007F': 'del' |
| 65 }; | 29 }; |
| 66 | 30 |
| 67 /** | 31 /** |
| 68 * Special table for KeyboardEvent.keyCode. | 32 * Special table for KeyboardEvent.keyCode. |
| 69 * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even bett
er | 33 * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even bett
er |
| 70 * than that. | 34 * than that. |
| 71 * | 35 * |
| 72 * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEve
nt.keyCode#Value_of_keyCode | 36 * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEve
nt.keyCode#Value_of_keyCode |
| 73 */ | 37 */ |
| 74 var KEY_CODE = { | 38 var KEY_CODE = { |
| 39 8: 'backspace', |
| 75 9: 'tab', | 40 9: 'tab', |
| 76 13: 'enter', | 41 13: 'enter', |
| 77 27: 'esc', | 42 27: 'esc', |
| 78 33: 'pageup', | 43 33: 'pageup', |
| 79 34: 'pagedown', | 44 34: 'pagedown', |
| 80 35: 'end', | 45 35: 'end', |
| 81 36: 'home', | 46 36: 'home', |
| 82 32: 'space', | 47 32: 'space', |
| 83 37: 'left', | 48 37: 'left', |
| 84 38: 'up', | 49 38: 'up', |
| 85 39: 'right', | 50 39: 'right', |
| 86 40: 'down', | 51 40: 'down', |
| 87 46: 'del', | 52 46: 'del', |
| 88 106: '*' | 53 106: '*' |
| 89 }; | 54 }; |
| 90 | 55 |
| 91 /** | 56 /** |
| 92 * MODIFIER_KEYS maps the short name for modifier keys used in a key | 57 * MODIFIER_KEYS maps the short name for modifier keys used in a key |
| 93 * combo string to the property name that references those same keys | 58 * combo string to the property name that references those same keys |
| 94 * in a KeyboardEvent instance. | 59 * in a KeyboardEvent instance. |
| 95 */ | 60 */ |
| 96 var MODIFIER_KEYS = { | 61 var MODIFIER_KEYS = { |
| 97 shift: 'shiftKey', | 62 'shift': 'shiftKey', |
| 98 ctrl: 'ctrlKey', | 63 'ctrl': 'ctrlKey', |
| 99 alt: 'altKey', | 64 'alt': 'altKey', |
| 100 meta: 'metaKey' | 65 'meta': 'metaKey' |
| 101 }; | 66 }; |
| 102 | 67 |
| 103 /** | 68 /** |
| 104 * KeyboardEvent.key is mostly represented by printable character made by | 69 * KeyboardEvent.key is mostly represented by printable character made by |
| 105 * the keyboard, with unprintable keys labeled nicely. | 70 * the keyboard, with unprintable keys labeled nicely. |
| 106 * | 71 * |
| 107 * However, on OS X, Alt+char can make a Unicode character that follows an | 72 * However, on OS X, Alt+char can make a Unicode character that follows an |
| 108 * Apple-specific mapping. In this case, we | 73 * Apple-specific mapping. In this case, we fall back to .keyCode. |
| 109 * fall back to .keyCode. | |
| 110 */ | 74 */ |
| 111 var KEY_CHAR = /[a-z0-9*]/; | 75 var KEY_CHAR = /[a-z0-9*]/; |
| 112 | 76 |
| 113 /** | 77 /** |
| 114 * Matches a keyIdentifier string. | 78 * Matches a keyIdentifier string. |
| 115 */ | 79 */ |
| 116 var IDENT_CHAR = /U\+/; | 80 var IDENT_CHAR = /U\+/; |
| 117 | 81 |
| 118 /** | 82 /** |
| 119 * Matches arrow keys in Gecko 27.0+ | 83 * Matches arrow keys in Gecko 27.0+ |
| 120 */ | 84 */ |
| 121 var ARROW_KEY = /^arrow/; | 85 var ARROW_KEY = /^arrow/; |
| 122 | 86 |
| 123 /** | 87 /** |
| 124 * Matches space keys everywhere (notably including IE10's exceptional name | 88 * Matches space keys everywhere (notably including IE10's exceptional name |
| 125 * `spacebar`). | 89 * `spacebar`). |
| 126 */ | 90 */ |
| 127 var SPACE_KEY = /^space(bar)?/; | 91 var SPACE_KEY = /^space(bar)?/; |
| 128 | 92 |
| 129 function transformKey(key) { | 93 /** |
| 94 * Transforms the key. |
| 95 * @param {string} key The KeyBoardEvent.key |
| 96 * @param {Boolean} [noSpecialChars] Limits the transformation to |
| 97 * alpha-numeric characters. |
| 98 */ |
| 99 function transformKey(key, noSpecialChars) { |
| 130 var validKey = ''; | 100 var validKey = ''; |
| 131 if (key) { | 101 if (key) { |
| 132 var lKey = key.toLowerCase(); | 102 var lKey = key.toLowerCase(); |
| 133 if (lKey.length == 1) { | 103 if (lKey === ' ' || SPACE_KEY.test(lKey)) { |
| 134 if (KEY_CHAR.test(lKey)) { | 104 validKey = 'space'; |
| 105 } else if (lKey.length == 1) { |
| 106 if (!noSpecialChars || KEY_CHAR.test(lKey)) { |
| 135 validKey = lKey; | 107 validKey = lKey; |
| 136 } | 108 } |
| 137 } else if (ARROW_KEY.test(lKey)) { | 109 } else if (ARROW_KEY.test(lKey)) { |
| 138 validKey = lKey.replace('arrow', ''); | 110 validKey = lKey.replace('arrow', ''); |
| 139 } else if (SPACE_KEY.test(lKey)) { | |
| 140 validKey = 'space'; | |
| 141 } else if (lKey == 'multiply') { | 111 } else if (lKey == 'multiply') { |
| 142 // numpad '*' can map to Multiply on IE/Windows | 112 // numpad '*' can map to Multiply on IE/Windows |
| 143 validKey = '*'; | 113 validKey = '*'; |
| 144 } else { | 114 } else { |
| 145 validKey = lKey; | 115 validKey = lKey; |
| 146 } | 116 } |
| 147 } | 117 } |
| 148 return validKey; | 118 return validKey; |
| 149 } | 119 } |
| 150 | 120 |
| 151 function transformKeyIdentifier(keyIdent) { | 121 function transformKeyIdentifier(keyIdent) { |
| 152 var validKey = ''; | 122 var validKey = ''; |
| 153 if (keyIdent) { | 123 if (keyIdent) { |
| 154 if (IDENT_CHAR.test(keyIdent)) { | 124 if (keyIdent in KEY_IDENTIFIER) { |
| 155 validKey = KEY_IDENTIFIER[keyIdent]; | 125 validKey = KEY_IDENTIFIER[keyIdent]; |
| 126 } else if (IDENT_CHAR.test(keyIdent)) { |
| 127 keyIdent = parseInt(keyIdent.replace('U+', '0x'), 16); |
| 128 validKey = String.fromCharCode(keyIdent).toLowerCase(); |
| 156 } else { | 129 } else { |
| 157 validKey = keyIdent.toLowerCase(); | 130 validKey = keyIdent.toLowerCase(); |
| 158 } | 131 } |
| 159 } | 132 } |
| 160 return validKey; | 133 return validKey; |
| 161 } | 134 } |
| 162 | 135 |
| 163 function transformKeyCode(keyCode) { | 136 function transformKeyCode(keyCode) { |
| 164 var validKey = ''; | 137 var validKey = ''; |
| 165 if (Number(keyCode)) { | 138 if (Number(keyCode)) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 176 } else if (keyCode >= 96 && keyCode <= 105) { | 149 } else if (keyCode >= 96 && keyCode <= 105) { |
| 177 // num pad 0-9 | 150 // num pad 0-9 |
| 178 validKey = String(96 - keyCode); | 151 validKey = String(96 - keyCode); |
| 179 } else { | 152 } else { |
| 180 validKey = KEY_CODE[keyCode]; | 153 validKey = KEY_CODE[keyCode]; |
| 181 } | 154 } |
| 182 } | 155 } |
| 183 return validKey; | 156 return validKey; |
| 184 } | 157 } |
| 185 | 158 |
| 186 function normalizedKeyForEvent(keyEvent) { | 159 /** |
| 187 // fall back from .key, to .keyIdentifier, to .keyCode, and then to | 160 * Calculates the normalized key for a KeyboardEvent. |
| 188 // .detail.key to support artificial keyboard events | 161 * @param {KeyboardEvent} keyEvent |
| 189 return transformKey(keyEvent.key) || | 162 * @param {Boolean} [noSpecialChars] Set to true to limit keyEvent.key |
| 163 * transformation to alpha-numeric chars. This is useful with key |
| 164 * combinations like shift + 2, which on FF for MacOS produces |
| 165 * keyEvent.key = @ |
| 166 * To get 2 returned, set noSpecialChars = true |
| 167 * To get @ returned, set noSpecialChars = false |
| 168 */ |
| 169 function normalizedKeyForEvent(keyEvent, noSpecialChars) { |
| 170 // Fall back from .key, to .keyIdentifier, to .keyCode, and then to |
| 171 // .detail.key to support artificial keyboard events. |
| 172 return transformKey(keyEvent.key, noSpecialChars) || |
| 190 transformKeyIdentifier(keyEvent.keyIdentifier) || | 173 transformKeyIdentifier(keyEvent.keyIdentifier) || |
| 191 transformKeyCode(keyEvent.keyCode) || | 174 transformKeyCode(keyEvent.keyCode) || |
| 192 transformKey(keyEvent.detail.key) || ''; | 175 transformKey(keyEvent.detail.key, noSpecialChars) || ''; |
| 193 } | 176 } |
| 194 | 177 |
| 195 function keyComboMatchesEvent(keyCombo, keyEvent) { | 178 function keyComboMatchesEvent(keyCombo, event) { |
| 196 return normalizedKeyForEvent(keyEvent) === keyCombo.key && | 179 // For combos with modifiers we support only alpha-numeric keys |
| 197 !!keyEvent.shiftKey === !!keyCombo.shiftKey && | 180 var keyEvent = normalizedKeyForEvent(event, keyCombo.hasModifiers); |
| 198 !!keyEvent.ctrlKey === !!keyCombo.ctrlKey && | 181 return keyEvent === keyCombo.key && |
| 199 !!keyEvent.altKey === !!keyCombo.altKey && | 182 (!keyCombo.hasModifiers || ( |
| 200 !!keyEvent.metaKey === !!keyCombo.metaKey; | 183 !!event.shiftKey === !!keyCombo.shiftKey && |
| 184 !!event.ctrlKey === !!keyCombo.ctrlKey && |
| 185 !!event.altKey === !!keyCombo.altKey && |
| 186 !!event.metaKey === !!keyCombo.metaKey) |
| 187 ); |
| 201 } | 188 } |
| 202 | 189 |
| 203 function parseKeyComboString(keyComboString) { | 190 function parseKeyComboString(keyComboString) { |
| 191 if (keyComboString.length === 1) { |
| 192 return { |
| 193 combo: keyComboString, |
| 194 key: keyComboString, |
| 195 event: 'keydown' |
| 196 }; |
| 197 } |
| 204 return keyComboString.split('+').reduce(function(parsedKeyCombo, keyComboP
art) { | 198 return keyComboString.split('+').reduce(function(parsedKeyCombo, keyComboP
art) { |
| 205 var eventParts = keyComboPart.split(':'); | 199 var eventParts = keyComboPart.split(':'); |
| 206 var keyName = eventParts[0]; | 200 var keyName = eventParts[0]; |
| 207 var event = eventParts[1]; | 201 var event = eventParts[1]; |
| 208 | 202 |
| 209 if (keyName in MODIFIER_KEYS) { | 203 if (keyName in MODIFIER_KEYS) { |
| 210 parsedKeyCombo[MODIFIER_KEYS[keyName]] = true; | 204 parsedKeyCombo[MODIFIER_KEYS[keyName]] = true; |
| 205 parsedKeyCombo.hasModifiers = true; |
| 211 } else { | 206 } else { |
| 212 parsedKeyCombo.key = keyName; | 207 parsedKeyCombo.key = keyName; |
| 213 parsedKeyCombo.event = event || 'keydown'; | 208 parsedKeyCombo.event = event || 'keydown'; |
| 214 } | 209 } |
| 215 | 210 |
| 216 return parsedKeyCombo; | 211 return parsedKeyCombo; |
| 217 }, { | 212 }, { |
| 218 combo: keyComboString.split(':').shift() | 213 combo: keyComboString.split(':').shift() |
| 219 }); | 214 }); |
| 220 } | 215 } |
| 221 | 216 |
| 222 function parseEventString(eventString) { | 217 function parseEventString(eventString) { |
| 223 return eventString.split(' ').map(function(keyComboString) { | 218 return eventString.trim().split(' ').map(function(keyComboString) { |
| 224 return parseKeyComboString(keyComboString); | 219 return parseKeyComboString(keyComboString); |
| 225 }); | 220 }); |
| 226 } | 221 } |
| 227 | 222 |
| 228 | |
| 229 /** | 223 /** |
| 230 * `Polymer.IronA11yKeysBehavior` provides a normalized interface for proces
sing | 224 * `Polymer.IronA11yKeysBehavior` provides a normalized interface for proces
sing |
| 231 * keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3
.org/TR/wai-aria-practices/#kbd_general_binding). | 225 * keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3
.org/TR/wai-aria-practices/#kbd_general_binding). |
| 232 * The element takes care of browser differences with respect to Keyboard ev
ents | 226 * The element takes care of browser differences with respect to Keyboard ev
ents |
| 233 * and uses an expressive syntax to filter key presses. | 227 * and uses an expressive syntax to filter key presses. |
| 234 * | 228 * |
| 235 * Use the `keyBindings` prototype property to express what combination of k
eys | 229 * Use the `keyBindings` prototype property to express what combination of k
eys |
| 236 * will trigger the event to fire. | 230 * will trigger the event to fire. |
| 237 * | 231 * |
| 238 * Use the `key-event-target` attribute to set up event handlers on a specif
ic | 232 * Use the `key-event-target` attribute to set up event handlers on a specif
ic |
| 239 * node. | 233 * node. |
| 240 * The `keys-pressed` event will fire when one of the key combinations set w
ith the | 234 * The `keys-pressed` event will fire when one of the key combinations set w
ith the |
| 241 * `keys` property is pressed. | 235 * `keys` property is pressed. |
| 242 * | 236 * |
| 243 * @demo demo/index.html | 237 * @demo demo/index.html |
| 244 * @polymerBehavior IronA11yKeysBehavior | 238 * @polymerBehavior |
| 245 */ | 239 */ |
| 246 Polymer.IronA11yKeysBehavior = { | 240 Polymer.IronA11yKeysBehavior = { |
| 247 properties: { | 241 properties: { |
| 248 /** | 242 /** |
| 249 * The HTMLElement that will be firing relevant KeyboardEvents. | 243 * The HTMLElement that will be firing relevant KeyboardEvents. |
| 250 */ | 244 */ |
| 251 keyEventTarget: { | 245 keyEventTarget: { |
| 252 type: Object, | 246 type: Object, |
| 253 value: function() { | 247 value: function() { |
| 254 return this; | 248 return this; |
| 255 } | 249 } |
| 256 }, | 250 }, |
| 257 | 251 |
| 252 /** |
| 253 * If true, this property will cause the implementing element to |
| 254 * automatically stop propagation on any handled KeyboardEvents. |
| 255 */ |
| 256 stopKeyboardEventPropagation: { |
| 257 type: Boolean, |
| 258 value: false |
| 259 }, |
| 260 |
| 258 _boundKeyHandlers: { | 261 _boundKeyHandlers: { |
| 259 type: Array, | 262 type: Array, |
| 260 value: function() { | 263 value: function() { |
| 261 return []; | 264 return []; |
| 262 } | 265 } |
| 263 }, | 266 }, |
| 264 | 267 |
| 265 // We use this due to a limitation in IE10 where instances will have | 268 // We use this due to a limitation in IE10 where instances will have |
| 266 // own properties of everything on the "prototype". | 269 // own properties of everything on the "prototype". |
| 267 _imperativeKeyBindings: { | 270 _imperativeKeyBindings: { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 * When called, will remove all imperatively-added key bindings. | 308 * When called, will remove all imperatively-added key bindings. |
| 306 */ | 309 */ |
| 307 removeOwnKeyBindings: function() { | 310 removeOwnKeyBindings: function() { |
| 308 this._imperativeKeyBindings = {}; | 311 this._imperativeKeyBindings = {}; |
| 309 this._prepKeyBindings(); | 312 this._prepKeyBindings(); |
| 310 this._resetKeyEventListeners(); | 313 this._resetKeyEventListeners(); |
| 311 }, | 314 }, |
| 312 | 315 |
| 313 keyboardEventMatchesKeys: function(event, eventString) { | 316 keyboardEventMatchesKeys: function(event, eventString) { |
| 314 var keyCombos = parseEventString(eventString); | 317 var keyCombos = parseEventString(eventString); |
| 315 var index; | 318 for (var i = 0; i < keyCombos.length; ++i) { |
| 316 | 319 if (keyComboMatchesEvent(keyCombos[i], event)) { |
| 317 for (index = 0; index < keyCombos.length; ++index) { | |
| 318 if (keyComboMatchesEvent(keyCombos[index], event)) { | |
| 319 return true; | 320 return true; |
| 320 } | 321 } |
| 321 } | 322 } |
| 322 | |
| 323 return false; | 323 return false; |
| 324 }, | 324 }, |
| 325 | 325 |
| 326 _collectKeyBindings: function() { | 326 _collectKeyBindings: function() { |
| 327 var keyBindings = this.behaviors.map(function(behavior) { | 327 var keyBindings = this.behaviors.map(function(behavior) { |
| 328 return behavior.keyBindings; | 328 return behavior.keyBindings; |
| 329 }); | 329 }); |
| 330 | 330 |
| 331 if (keyBindings.indexOf(this.keyBindings) === -1) { | 331 if (keyBindings.indexOf(this.keyBindings) === -1) { |
| 332 keyBindings.push(this.keyBindings); | 332 keyBindings.push(this.keyBindings); |
| 333 } | 333 } |
| 334 | 334 |
| 335 return keyBindings; | 335 return keyBindings; |
| 336 }, | 336 }, |
| 337 | 337 |
| 338 _prepKeyBindings: function() { | 338 _prepKeyBindings: function() { |
| 339 this._keyBindings = {}; | 339 this._keyBindings = {}; |
| 340 | 340 |
| 341 this._collectKeyBindings().forEach(function(keyBindings) { | 341 this._collectKeyBindings().forEach(function(keyBindings) { |
| 342 for (var eventString in keyBindings) { | 342 for (var eventString in keyBindings) { |
| 343 this._addKeyBinding(eventString, keyBindings[eventString]); | 343 this._addKeyBinding(eventString, keyBindings[eventString]); |
| 344 } | 344 } |
| 345 }, this); | 345 }, this); |
| 346 | 346 |
| 347 for (var eventString in this._imperativeKeyBindings) { | 347 for (var eventString in this._imperativeKeyBindings) { |
| 348 this._addKeyBinding(eventString, this._imperativeKeyBindings[eventStri
ng]); | 348 this._addKeyBinding(eventString, this._imperativeKeyBindings[eventStri
ng]); |
| 349 } | 349 } |
| 350 |
| 351 // Give precedence to combos with modifiers to be checked first. |
| 352 for (var eventName in this._keyBindings) { |
| 353 this._keyBindings[eventName].sort(function (kb1, kb2) { |
| 354 var b1 = kb1[0].hasModifiers; |
| 355 var b2 = kb2[0].hasModifiers; |
| 356 return (b1 === b2) ? 0 : b1 ? -1 : 1; |
| 357 }) |
| 358 } |
| 350 }, | 359 }, |
| 351 | 360 |
| 352 _addKeyBinding: function(eventString, handlerName) { | 361 _addKeyBinding: function(eventString, handlerName) { |
| 353 parseEventString(eventString).forEach(function(keyCombo) { | 362 parseEventString(eventString).forEach(function(keyCombo) { |
| 354 this._keyBindings[keyCombo.event] = | 363 this._keyBindings[keyCombo.event] = |
| 355 this._keyBindings[keyCombo.event] || []; | 364 this._keyBindings[keyCombo.event] || []; |
| 356 | 365 |
| 357 this._keyBindings[keyCombo.event].push([ | 366 this._keyBindings[keyCombo.event].push([ |
| 358 keyCombo, | 367 keyCombo, |
| 359 handlerName | 368 handlerName |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 keyHandlerTuple = this._boundKeyHandlers.pop(); | 400 keyHandlerTuple = this._boundKeyHandlers.pop(); |
| 392 keyEventTarget = keyHandlerTuple[0]; | 401 keyEventTarget = keyHandlerTuple[0]; |
| 393 eventName = keyHandlerTuple[1]; | 402 eventName = keyHandlerTuple[1]; |
| 394 boundKeyHandler = keyHandlerTuple[2]; | 403 boundKeyHandler = keyHandlerTuple[2]; |
| 395 | 404 |
| 396 keyEventTarget.removeEventListener(eventName, boundKeyHandler); | 405 keyEventTarget.removeEventListener(eventName, boundKeyHandler); |
| 397 } | 406 } |
| 398 }, | 407 }, |
| 399 | 408 |
| 400 _onKeyBindingEvent: function(keyBindings, event) { | 409 _onKeyBindingEvent: function(keyBindings, event) { |
| 401 keyBindings.forEach(function(keyBinding) { | 410 if (this.stopKeyboardEventPropagation) { |
| 402 var keyCombo = keyBinding[0]; | 411 event.stopPropagation(); |
| 403 var handlerName = keyBinding[1]; | 412 } |
| 404 | 413 |
| 405 if (!event.defaultPrevented && keyComboMatchesEvent(keyCombo, event))
{ | 414 // if event has been already prevented, don't do anything |
| 415 if (event.defaultPrevented) { |
| 416 return; |
| 417 } |
| 418 |
| 419 for (var i = 0; i < keyBindings.length; i++) { |
| 420 var keyCombo = keyBindings[i][0]; |
| 421 var handlerName = keyBindings[i][1]; |
| 422 if (keyComboMatchesEvent(keyCombo, event)) { |
| 406 this._triggerKeyHandler(keyCombo, handlerName, event); | 423 this._triggerKeyHandler(keyCombo, handlerName, event); |
| 424 // exit the loop if eventDefault was prevented |
| 425 if (event.defaultPrevented) { |
| 426 return; |
| 427 } |
| 407 } | 428 } |
| 408 }, this); | 429 } |
| 409 }, | 430 }, |
| 410 | 431 |
| 411 _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) { | 432 _triggerKeyHandler: function(keyCombo, handlerName, keyboardEvent) { |
| 412 var detail = Object.create(keyCombo); | 433 var detail = Object.create(keyCombo); |
| 413 detail.keyboardEvent = keyboardEvent; | 434 detail.keyboardEvent = keyboardEvent; |
| 414 | 435 var event = new CustomEvent(keyCombo.event, { |
| 415 this[handlerName].call(this, new CustomEvent(keyCombo.event, { | 436 detail: detail, |
| 416 detail: detail | 437 cancelable: true |
| 417 })); | 438 }); |
| 439 this[handlerName].call(this, event); |
| 440 if (event.defaultPrevented) { |
| 441 keyboardEvent.preventDefault(); |
| 442 } |
| 418 } | 443 } |
| 419 }; | 444 }; |
| 420 })(); | 445 })(); |
| 421 </script> | 446 </script> |
| OLD | NEW |