1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Namespace for keyboard utility functions. 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)var keyboard = {}; 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Swallows keypress and keyup events of arrow keys. 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {Event} event Raised event. 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @private 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)keyboard.onKeyIgnore_ = function(event) { 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci event = /** @type {KeyboardEvent} */(event); 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (event.keyIdentifier == 'Left' || 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) event.keyIdentifier == 'Right' || 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) event.keyIdentifier == 'Up' || 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) event.keyIdentifier == 'Down') { 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event.stopPropagation(); 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event.preventDefault(); 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Converts arrow keys into tab/shift-tab key events. 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {Event} event Raised event. 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @private 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)keyboard.onKeyDown_ = function(event) { 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci event = /** @type {KeyboardEvent} */(event); 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var needsUpDownKeys = event.target.classList.contains('needs-up-down-keys'); 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (event.keyIdentifier == 'Left' || 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (!needsUpDownKeys && event.keyIdentifier == 'Up')) { 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci keyboard.raiseKeyFocusPrevious(document.activeElement); 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci event.stopPropagation(); 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci event.preventDefault(); 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (event.keyIdentifier == 'Right' || 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (!needsUpDownKeys && event.keyIdentifier == 'Down')) { 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci keyboard.raiseKeyFocusNext(document.activeElement); 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci event.stopPropagation(); 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci event.preventDefault(); 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Raises tab/shift-tab keyboard events. 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {HTMLElement} element Element that should receive the event. 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {string} eventType Keyboard event type. 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {boolean} shift True if shift should be on. 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @private 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)keyboard.raiseTabKeyEvent_ = function(element, eventType, shift) { 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) var event = document.createEvent('KeyboardEvent'); 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) event.initKeyboardEvent( 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) eventType, 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) true, // canBubble 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) true, // cancelable 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) window, 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 'U+0009', 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, // keyLocation 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) false, // ctrl 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) false, // alt 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) shift, // shift 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) false); // meta 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) element.dispatchEvent(event); 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Raises shift+tab keyboard events to focus previous element. 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {HTMLElement} element Element that should receive the event. 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)keyboard.raiseKeyFocusPrevious = function(element) { 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) keyboard.raiseTabKeyEvent_(element, 'keydown', true); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) keyboard.raiseTabKeyEvent_(element, 'keypress', true); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) keyboard.raiseTabKeyEvent_(element, 'keyup', true); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Raises tab keyboard events to focus next element. 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @param {HTMLElement} element Element that should receive the event. 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)keyboard.raiseKeyFocusNext = function(element) { 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) keyboard.raiseTabKeyEvent_(element, 'keydown', false); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) keyboard.raiseTabKeyEvent_(element, 'keypress', false); 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) keyboard.raiseTabKeyEvent_(element, 'keyup', false); 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/** 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Initializes event handling for arrow keys driven focus flow. 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */ 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)keyboard.initializeKeyboardFlow = function() { 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) document.addEventListener('keydown', 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) keyboard.onKeyDown_, true); 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) document.addEventListener('keypress', 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) keyboard.onKeyIgnore_, true); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) document.addEventListener('keyup', 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) keyboard.onKeyIgnore_, true); 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 110