UNPKG

five-bells-visualization

Version:
343 lines (304 loc) 11 kB
<!-- @license Copyright (c) 2014 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt --> <!-- `core-a11y-keys` provides a normalized interface for processing keyboard commands that pertain to [WAI-ARIA best practices](http://www.w3.org/TR/wai-aria-practices/#kbd_general_binding). The element takes care of browser differences with respect to Keyboard events and uses an expressive syntax to filter key presses. Use the `keys` attribute to express what combination of keys will trigger the event to fire. Use the `target` attribute to set up event handlers on a specific node. The `keys-pressed` event will fire when one of the key combinations set with the `keys` attribute is pressed. Example: This element will call `arrowHandler` on all arrow keys: <core-a11y-keys target="{{}}" keys="up down left right" on-keys-pressed="{{arrowHandler}}"></core-a11y-keys> Keys Syntax: The `keys` attribute can accepts a space seprated, `+` concatenated set of modifier keys and some common keyboard keys. The common keys are `a-z`, `0-9` (top row and number pad), `*` (shift 8 and number pad), `F1-F12`, `Page Up`, `Page Down`, `Left Arrow`, `Right Arrow`, `Down Arrow`, `Up Arrow`, `Home`, `End`, `Escape`, `Space`, `Tab`, and `Enter` keys. The modifier keys are `Shift`, `Control`, and `Alt`. All keys are expected to be lowercase and shortened: `Left Arrow` is `left`, `Page Down` is `pagedown`, `Control` is `ctrl`, `F1` is `f1`, `Escape` is `esc` etc. Keys Syntax Example: Given the `keys` attribute value "ctrl+shift+f7 up pagedown esc space alt+m", the `<core-a11y-keys>` element will send the `keys-pressed` event if any of the follow key combos are pressed: Control and Shift and F7 keys, Up Arrow key, Page Down key, Escape key, Space key, Alt and M key. Slider Example: The following is an example of the set of keys that fulfil the WAI-ARIA "slider" role [best practices](http://www.w3.org/TR/wai-aria-practices/#slider): <core-a11y-keys target="{{}}" keys="left pagedown down" on-keys-pressed="{{decrement}}"></core-a11y-keys> <core-a11y-keys target="{{}}" keys="right pageup up" on-keys-pressed="{{increment}}"></core-a11y-keys> <core-a11y-keys target="{{}}" keys="home" on-keys-pressed="{{setMin}}"></core-a11y-keys> <core-a11y-keys target="{{}}" keys="end" on-keys-pressed="{{setMax}}"></core-a11y-keys> The `increment` function will move the slider a set amount toward the maximum value. The `decrement` function will move the slider a set amount toward the minimum value. The `setMin` function will move the slider to the minimum value. The `setMax` function will move the slider to the maximum value. Keys Syntax Grammar: [EBNF](http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form) Grammar of the `keys` attribute. modifier = "shift" | "ctrl" | "alt"; ascii = ? /[a-z0-9]/ ? ; fnkey = ? f1 through f12 ? ; arrow = "up" | "down" | "left" | "right" ; key = "tab" | "esc" | "space" | "*" | "pageup" | "pagedown" | "home" | "end" | arrow | ascii | fnkey ; keycombo = { modifier, "+" }, key ; keys = keycombo, { " ", keycombo } ; @group Core Elements @element core-a11y-keys @homepage github.io --> <!-- Fired when a keycombo in `keys` is pressed. @event keys-pressed @param {Object} detail @param {boolean} detail.shift true if shift key is pressed @param {boolean} detail.ctrl true if ctrl key is pressed @param {boolean} detail.meta true if meta key is pressed @param {boolean} detail.alt true if alt key is pressed @param {String} detail.key the normalized key --> <link rel="import" href="../polymer/polymer.html"> <style shim-shadowdom> html /deep/ core-a11y-keys { display: none; } </style> <polymer-element name="core-a11y-keys"> <script> (function() { /* * Chrome uses an older version of DOM Level 3 Keyboard Events * * Most keys are labeled as text, but some are Unicode codepoints. * Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html#KeySet-Set */ var KEY_IDENTIFIER = { 'U+0009': 'tab', 'U+001B': 'esc', 'U+0020': 'space', 'U+002A': '*', 'U+0030': '0', 'U+0031': '1', 'U+0032': '2', 'U+0033': '3', 'U+0034': '4', 'U+0035': '5', 'U+0036': '6', 'U+0037': '7', 'U+0038': '8', 'U+0039': '9', 'U+0041': 'a', 'U+0042': 'b', 'U+0043': 'c', 'U+0044': 'd', 'U+0045': 'e', 'U+0046': 'f', 'U+0047': 'g', 'U+0048': 'h', 'U+0049': 'i', 'U+004A': 'j', 'U+004B': 'k', 'U+004C': 'l', 'U+004D': 'm', 'U+004E': 'n', 'U+004F': 'o', 'U+0050': 'p', 'U+0051': 'q', 'U+0052': 'r', 'U+0053': 's', 'U+0054': 't', 'U+0055': 'u', 'U+0056': 'v', 'U+0057': 'w', 'U+0058': 'x', 'U+0059': 'y', 'U+005A': 'z', 'U+007F': 'del' }; /* * Special table for KeyboardEvent.keyCode. * KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even better than that * * Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode#Value_of_keyCode */ var KEY_CODE = { 9: 'tab', 13: 'enter', 27: 'esc', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 32: 'space', 37: 'left', 38: 'up', 39: 'right', 40: 'down', 46: 'del', 106: '*' }; /* * KeyboardEvent.key is mostly represented by printable character made by the keyboard, with unprintable keys labeled * nicely. * * However, on OS X, Alt+char can make a Unicode character that follows an Apple-specific mapping. In this case, we * fall back to .keyCode. */ var KEY_CHAR = /[a-z0-9*]/; function transformKey(key) { var validKey = ''; if (key) { var lKey = key.toLowerCase(); if (lKey.length == 1) { if (KEY_CHAR.test(lKey)) { validKey = lKey; } } else if (lKey == 'multiply') { // numpad '*' can map to Multiply on IE/Windows validKey = '*'; } else { validKey = lKey; } } return validKey; } var IDENT_CHAR = /U\+/; function transformKeyIdentifier(keyIdent) { var validKey = ''; if (keyIdent) { if (IDENT_CHAR.test(keyIdent)) { validKey = KEY_IDENTIFIER[keyIdent]; } else { validKey = keyIdent.toLowerCase(); } } return validKey; } function transformKeyCode(keyCode) { var validKey = ''; if (Number(keyCode)) { if (keyCode >= 65 && keyCode <= 90) { // ascii a-z // lowercase is 32 offset from uppercase validKey = String.fromCharCode(32 + keyCode); } else if (keyCode >= 112 && keyCode <= 123) { // function keys f1-f12 validKey = 'f' + (keyCode - 112); } else if (keyCode >= 48 && keyCode <= 57) { // top 0-9 keys validKey = String(48 - keyCode); } else if (keyCode >= 96 && keyCode <= 105) { // num pad 0-9 validKey = String(96 - keyCode); } else { validKey = KEY_CODE[keyCode]; } } return validKey; } function keyboardEventToKey(ev) { // fall back from .key, to .keyIdentifier, to .keyCode, and then to .detail.key to support artificial keyboard events var normalizedKey = transformKey(ev.key) || transformKeyIdentifier(ev.keyIdentifier) || transformKeyCode(ev.keyCode) || transformKey(ev.detail.key) || ''; return { shift: ev.shiftKey, ctrl: ev.ctrlKey, meta: ev.metaKey, alt: ev.altKey, key: normalizedKey }; } /* * Input: ctrl+shift+f7 => {ctrl: true, shift: true, key: 'f7'} * ctrl/space => {ctrl: true} || {key: space} */ function stringToKey(keyCombo) { var keys = keyCombo.split('+'); var keyObj = Object.create(null); keys.forEach(function(key) { if (key == 'shift') { keyObj.shift = true; } else if (key == 'ctrl') { keyObj.ctrl = true; } else if (key == 'alt') { keyObj.alt = true; } else { keyObj.key = key; } }); return keyObj; } function keyMatches(a, b) { return Boolean(a.alt) == Boolean(b.alt) && Boolean(a.ctrl) == Boolean(b.ctrl) && Boolean(a.shift) == Boolean(b.shift) && a.key === b.key; } function processKeys(ev) { var current = keyboardEventToKey(ev); for (var i = 0, dk; i < this._desiredKeys.length; i++) { dk = this._desiredKeys[i]; if (keyMatches(dk, current)) { ev.preventDefault(); ev.stopPropagation(); this.fire('keys-pressed', current, this, false); break; } } } function listen(node, handler) { if (node && node.addEventListener) { node.addEventListener('keydown', handler); } } function unlisten(node, handler) { if (node && node.removeEventListener) { node.removeEventListener('keydown', handler); } } Polymer('core-a11y-keys', { created: function() { this._keyHandler = processKeys.bind(this); }, attached: function() { if (!this.target) { this.target = this.parentNode; } listen(this.target, this._keyHandler); }, detached: function() { unlisten(this.target, this._keyHandler); }, publish: { /** * The set of key combinations that will be matched (in keys syntax). * * @attribute keys * @type string * @default '' */ keys: '', /** * The node that will fire keyboard events. * Default to this element's parentNode unless one is assigned * * @attribute target * @type Node * @default this.parentNode */ target: null }, keysChanged: function() { // * can have multiple mappings: shift+8, * on numpad or Multiply on numpad var normalized = this.keys.replace('*', '* shift+*'); this._desiredKeys = normalized.toLowerCase().split(' ').map(stringToKey); }, targetChanged: function(oldTarget) { unlisten(oldTarget, this._keyHandler); listen(this.target, this._keyHandler); } }); })(); </script> </polymer-element>