1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * Namespace for keyboard utility functions.
7 */
8var keyboard = {};
9
10/**
11 * Swallows keypress and keyup events of arrow keys.
12 * @param {Event} event Raised event.
13 * @private
14 */
15keyboard.onKeyIgnore_ = function(event) {
16  event = /** @type {KeyboardEvent} */(event);
17
18  if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey)
19    return;
20
21  if (event.keyIdentifier == 'Left' ||
22      event.keyIdentifier == 'Right' ||
23      event.keyIdentifier == 'Up' ||
24      event.keyIdentifier == 'Down') {
25    event.stopPropagation();
26    event.preventDefault();
27  }
28};
29
30/**
31 * Converts arrow keys into tab/shift-tab key events.
32 * @param {Event} event Raised event.
33 * @private
34 */
35keyboard.onKeyDown_ = function(event) {
36  event = /** @type {KeyboardEvent} */(event);
37
38  if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey)
39    return;
40
41  var needsUpDownKeys = event.target.classList.contains('needs-up-down-keys');
42
43  if (event.keyIdentifier == 'Left' ||
44      (!needsUpDownKeys && event.keyIdentifier == 'Up')) {
45    keyboard.raiseKeyFocusPrevious(document.activeElement);
46    event.stopPropagation();
47    event.preventDefault();
48  } else if (event.keyIdentifier == 'Right' ||
49             (!needsUpDownKeys && event.keyIdentifier == 'Down')) {
50    keyboard.raiseKeyFocusNext(document.activeElement);
51    event.stopPropagation();
52    event.preventDefault();
53  }
54};
55
56/**
57 * Raises tab/shift-tab keyboard events.
58 * @param {HTMLElement} element Element that should receive the event.
59 * @param {string} eventType Keyboard event type.
60 * @param {boolean} shift True if shift should be on.
61 * @private
62 */
63keyboard.raiseTabKeyEvent_ = function(element, eventType, shift) {
64  var event = document.createEvent('KeyboardEvent');
65  event.initKeyboardEvent(
66      eventType,
67      true,  // canBubble
68      true,  // cancelable
69      window,
70      'U+0009',
71      0,  // keyLocation
72      false,  // ctrl
73      false,  // alt
74      shift,  // shift
75      false);  // meta
76  element.dispatchEvent(event);
77};
78
79/**
80 * Raises shift+tab keyboard events to focus previous element.
81 * @param {HTMLElement} element Element that should receive the event.
82 */
83keyboard.raiseKeyFocusPrevious = function(element) {
84  keyboard.raiseTabKeyEvent_(element, 'keydown', true);
85  keyboard.raiseTabKeyEvent_(element, 'keypress', true);
86  keyboard.raiseTabKeyEvent_(element, 'keyup', true);
87};
88
89/**
90 * Raises tab keyboard events to focus next element.
91 * @param {HTMLElement} element Element that should receive the event.
92 */
93keyboard.raiseKeyFocusNext = function(element) {
94  keyboard.raiseTabKeyEvent_(element, 'keydown', false);
95  keyboard.raiseTabKeyEvent_(element, 'keypress', false);
96  keyboard.raiseTabKeyEvent_(element, 'keyup', false);
97};
98
99/**
100 * Initializes event handling for arrow keys driven focus flow.
101 */
102keyboard.initializeKeyboardFlow = function() {
103  document.addEventListener('keydown',
104      keyboard.onKeyDown_, true);
105  document.addEventListener('keypress',
106      keyboard.onKeyIgnore_, true);
107  document.addEventListener('keyup',
108      keyboard.onKeyIgnore_, true);
109};
110