OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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 var BASE_KEYBOARD = { |
| 6 top: 0, |
| 7 left: 0, |
| 8 width: 1237, |
| 9 height: 468 |
| 10 }; |
| 11 |
| 12 var BASE_INSTRUCTIONS = { |
| 13 top: 174, |
| 14 left: 370, |
| 15 width: 498, |
| 16 height: 81 |
| 17 }; |
| 18 |
| 19 var LABEL_TO_KEY_TEXT = { |
| 20 alt: 'alt', |
| 21 backspace: 'backspace', |
| 22 ctrl: 'ctrl', |
| 23 enter: 'enter', |
| 24 esc: 'esc', |
| 25 glyph_arrow_down: 'down', |
| 26 glyph_arrow_left: 'left', |
| 27 glyph_arrow_right: 'right', |
| 28 glyph_arrow_up: 'up', |
| 29 glyph_back: 'back', |
| 30 glyph_backspace: 'backspace', |
| 31 glyph_brightness_down: 'bright down', |
| 32 glyph_brightness_up: 'bright up', |
| 33 glyph_enter: 'enter', |
| 34 glyph_forward: 'forward', |
| 35 glyph_fullscreen: 'fullscreen', |
| 36 glyph_overview: 'windows', |
| 37 glyph_power: 'power', |
| 38 glyph_reload: 'reload', |
| 39 glyph_reload: 'reload', |
| 40 glyph_search: 'search', |
| 41 glyph_tab: 'tab', |
| 42 glyph_tools: 'tools', |
| 43 glyph_volume_down: 'vol. down', |
| 44 glyph_volume_mute: 'mute', |
| 45 glyph_volume_up: 'vol. up', |
| 46 shift: 'shift', |
| 47 tab: 'tab' |
| 48 }; |
| 49 |
| 50 var MODIFIER_TO_CLASS = { |
| 51 'SHIFT': 'modifier-shift', |
| 52 'CTRL': 'modifier-ctrl', |
| 53 'ALT': 'modifier-alt' |
| 54 }; |
| 55 |
| 56 var IDENTIFIER_TO_CLASS = { |
| 57 '2A': 'is-shift', |
| 58 '1D': 'is-ctrl', |
| 59 '38': 'is-alt' |
| 60 }; |
| 61 |
| 62 var languageCode = 'en_US'; |
| 63 |
| 64 /** |
| 65 * Returns layouts data. |
| 66 */ |
| 67 function getLayouts() { |
| 68 return keyboardOverlayData['layouts']; |
| 69 } |
| 70 |
| 71 /** |
| 72 * Returns shortcut data. |
| 73 */ |
| 74 function getShortcutData() { |
| 75 return keyboardOverlayData['shortcut']; |
| 76 } |
| 77 |
| 78 /** |
| 79 * Returns the language code of the system. |
| 80 */ |
| 81 function getLanguageCode() { |
| 82 // TODO(mazda): Retrieve the language code from the system. |
| 83 return languageCode; |
| 84 } |
| 85 |
| 86 /** |
| 87 * Returns keyboard glyph data. |
| 88 */ |
| 89 function getKeyboardGlyphData() { |
| 90 return keyboardOverlayData['keyboardGlyph'][getLanguageCode()]; |
| 91 } |
| 92 |
| 93 /** |
| 94 * Converts a single hex number to a character. |
| 95 */ |
| 96 function hex2char(hex) { |
| 97 if (!hex) { |
| 98 return ''; |
| 99 } |
| 100 var result = ''; |
| 101 var n = parseInt(hex, 16); |
| 102 if (n <= 0xFFFF) { |
| 103 result += String.fromCharCode(n); |
| 104 } else if (n <= 0x10FFFF) { |
| 105 n -= 0x10000; |
| 106 result += (String.fromCharCode(0xD800 | (n >> 10)) + |
| 107 String.fromCharCode(0xDC00 | (n & 0x3FF))); |
| 108 } else { |
| 109 console.error('hex2Char error: Code point out of range :' + hex); |
| 110 } |
| 111 return result; |
| 112 } |
| 113 |
| 114 /** |
| 115 * Returns a list of modifiers from the key event. |
| 116 */ |
| 117 function getModifiers(e) { |
| 118 if (!e) { |
| 119 return []; |
| 120 } |
| 121 var modifiers = []; |
| 122 if (e.keyCode == 16 || e.shiftKey) { |
| 123 modifiers.push('SHIFT'); |
| 124 } |
| 125 if (e.keyCode == 17 || e.ctrlKey) { |
| 126 modifiers.push('CTRL'); |
| 127 } |
| 128 if (e.keyCode == 18 || e.altKey) { |
| 129 modifiers.push('ALT'); |
| 130 } |
| 131 return modifiers.sort(); |
| 132 } |
| 133 |
| 134 /** |
| 135 * Returns an ID of the key. |
| 136 */ |
| 137 function keyId(identifier, i) { |
| 138 return identifier + '-key-' + i; |
| 139 } |
| 140 |
| 141 /** |
| 142 * Returns an ID of the text on the key. |
| 143 */ |
| 144 function keyTextId(identifier, i) { |
| 145 return identifier + '-key-text-' + i; |
| 146 } |
| 147 |
| 148 /** |
| 149 * Returns an ID of the shortcut text. |
| 150 */ |
| 151 function shortcutTextId(identifier, i) { |
| 152 return identifier + '-shortcut-text-' + i; |
| 153 } |
| 154 |
| 155 /** |
| 156 * Returns true if |list| contains |e|. |
| 157 */ |
| 158 function contains(list, e) { |
| 159 return list.indexOf(e) != -1; |
| 160 } |
| 161 |
| 162 /** |
| 163 * Returns a list of the class names corresponding to the identifier and |
| 164 * modifiers. |
| 165 */ |
| 166 function getKeyClasses(identifier, modifiers) { |
| 167 var classes = ['keyboard-overlay-key']; |
| 168 for (var i = 0; i < modifiers.length; ++i) { |
| 169 classes.push(MODIFIER_TO_CLASS[modifiers[i]]); |
| 170 } |
| 171 |
| 172 if ((identifier == '2A' && contains(modifiers, 'SHIFT')) || |
| 173 (identifier == '1D' && contains(modifiers, 'CTRL')) || |
| 174 (identifier == '38' && contains(modifiers, 'ALT'))) { |
| 175 classes.push('pressed'); |
| 176 classes.push(IDENTIFIER_TO_CLASS[identifier]); |
| 177 } |
| 178 return classes; |
| 179 } |
| 180 |
| 181 /** |
| 182 * Returns true if a character is a ASCII character. |
| 183 */ |
| 184 function isAscii(c) { |
| 185 var charCode = c.charCodeAt(0); |
| 186 return 0x00 <= charCode && charCode <= 0x7F; |
| 187 } |
| 188 |
| 189 /** |
| 190 * Returns a label of the key. |
| 191 */ |
| 192 function getKeyLabel(keyData, modifiers) { |
| 193 if (!keyData) { |
| 194 return ''; |
| 195 } |
| 196 if (keyData.label in LABEL_TO_KEY_TEXT) { |
| 197 return LABEL_TO_KEY_TEXT[keyData.label]; |
| 198 } |
| 199 var keyLabel = ''; |
| 200 for (var j = 1; j <= 9; j++) { |
| 201 var pos = keyData['p' + j]; |
| 202 if (!pos) { |
| 203 continue; |
| 204 } |
| 205 if (LABEL_TO_KEY_TEXT[pos]) { |
| 206 return LABEL_TO_KEY_TEXT[pos]; |
| 207 } |
| 208 keyLabel = hex2char(pos); |
| 209 if (!keyLabel) { |
| 210 continue; |
| 211 } |
| 212 if (isAscii(keyLabel) && |
| 213 getShortcutData()[getAction(keyLabel, modifiers)]) { |
| 214 break; |
| 215 } |
| 216 } |
| 217 return keyLabel; |
| 218 } |
| 219 |
| 220 /** |
| 221 * Returns a normalized string used for a key of shortcutData. |
| 222 */ |
| 223 function getAction(keycode, modifiers) { |
| 224 return [keycode].concat(modifiers).join(' '); |
| 225 } |
| 226 |
| 227 /** |
| 228 * Returns a text which displayed on a key. |
| 229 */ |
| 230 function getKeyTextValue(keyData) { |
| 231 if (LABEL_TO_KEY_TEXT[keyData.label]) { |
| 232 return LABEL_TO_KEY_TEXT[keyData.label]; |
| 233 } |
| 234 |
| 235 var chars = []; |
| 236 for (var j = 1; j <= 9; ++j) { |
| 237 var pos = keyData['p' + j]; |
| 238 if (LABEL_TO_KEY_TEXT[pos]) { |
| 239 return LABEL_TO_KEY_TEXT[pos]; |
| 240 } |
| 241 if (pos && pos.length > 0) { |
| 242 chars.push(hex2char(pos)); |
| 243 } |
| 244 } |
| 245 return chars.join(' '); |
| 246 } |
| 247 |
| 248 /** |
| 249 * Updates the whole keyboard. |
| 250 */ |
| 251 function update(e) { |
| 252 var modifiers = getModifiers(e); |
| 253 var instructions = document.getElementById('instructions'); |
| 254 if (modifiers.length == 0) { |
| 255 instructions.style.visibility = 'visible'; |
| 256 } else { |
| 257 instructions.style.visibility = 'hidden'; |
| 258 } |
| 259 |
| 260 var keyboardGlyphData = getKeyboardGlyphData(); |
| 261 var shortcutData = getShortcutData(); |
| 262 var layout = getLayouts()[keyboardGlyphData.layoutName]; |
| 263 for (var i = 0; i < layout.length; ++i) { |
| 264 var identifier = layout[i][0]; |
| 265 var keyData = keyboardGlyphData.keys[identifier]; |
| 266 var classes = getKeyClasses(identifier, modifiers, keyData); |
| 267 var keyLabel = getKeyLabel(keyData, modifiers); |
| 268 var shortcutId = shortcutData[getAction(keyLabel, modifiers)]; |
| 269 if (shortcutId) { |
| 270 classes.push('is-shortcut'); |
| 271 } |
| 272 |
| 273 var key = document.getElementById(keyId(identifier, i)); |
| 274 key.className = classes.join(' '); |
| 275 |
| 276 if (!keyData) { |
| 277 continue; |
| 278 } |
| 279 |
| 280 var keyText = document.getElementById(keyTextId(identifier, i)); |
| 281 var keyTextValue = getKeyTextValue(keyData); |
| 282 if (keyTextValue) { |
| 283 keyText.style.visibility = 'visible'; |
| 284 } else { |
| 285 keyText.style.visibility = 'hidden'; |
| 286 } |
| 287 keyText.textContent = keyTextValue; |
| 288 |
| 289 var shortcutText = document.getElementById(shortcutTextId(identifier, i)); |
| 290 if (shortcutId) { |
| 291 shortcutText.style.visibility = 'visible'; |
| 292 shortcutText.textContent = templateData[shortcutId]; |
| 293 } else { |
| 294 shortcutText.style.visibility = 'hidden'; |
| 295 } |
| 296 |
| 297 if (keyData.format) { |
| 298 var format = keyData.format; |
| 299 if (format == 'left' || format == 'right') { |
| 300 shortcutText.style.textAlign = format; |
| 301 keyText.style.textAlign = format; |
| 302 } |
| 303 } |
| 304 } |
| 305 } |
| 306 |
| 307 /** |
| 308 * A callback furnction for the onkeydown event. |
| 309 */ |
| 310 function keydown(e) { |
| 311 update(e); |
| 312 } |
| 313 |
| 314 /** |
| 315 * A callback furnction for the onkeyup event. |
| 316 */ |
| 317 function keyup(e) { |
| 318 update(); |
| 319 } |
| 320 |
| 321 /** |
| 322 * Initializes the layout of the keys. |
| 323 */ |
| 324 function initLayout() { |
| 325 var layout = getLayouts()[getKeyboardGlyphData().layoutName]; |
| 326 var keyboard = document.body; |
| 327 var minX = window.innerWidth; |
| 328 var maxX = 0; |
| 329 var minY = window.innerHeight; |
| 330 var maxY = 0; |
| 331 var multiplier = 1.38 * window.innerWidth / BASE_KEYBOARD.width; |
| 332 var keyMargin = 7; |
| 333 var offsetX = 10; |
| 334 var offsetY = 7; |
| 335 for (var i = 0; i < layout.length; i++) { |
| 336 var array = layout[i]; |
| 337 var identifier = array[0]; |
| 338 var x = Math.round((array[1] + offsetX) * multiplier); |
| 339 var y = Math.round((array[2] + offsetY) * multiplier); |
| 340 var w = Math.round((array[3] - keyMargin) * multiplier); |
| 341 var h = Math.round((array[4] - keyMargin) * multiplier); |
| 342 |
| 343 var key = document.createElement('div'); |
| 344 key.id = keyId(identifier, i); |
| 345 key.className = 'keyboard-overlay-key'; |
| 346 key.style.left = x + 'px'; |
| 347 key.style.top = y + 'px'; |
| 348 key.style.width = w + 'px'; |
| 349 key.style.height = h + 'px'; |
| 350 |
| 351 var keyText = document.createElement('div'); |
| 352 keyText.id = keyTextId(identifier, i); |
| 353 keyText.className = 'keyboard-overlay-key-text'; |
| 354 keyText.style.visibility = 'hidden'; |
| 355 key.appendChild(keyText); |
| 356 |
| 357 var shortcutText = document.createElement('div'); |
| 358 shortcutText.id = shortcutTextId(identifier, i); |
| 359 shortcutText.className = 'keyboard-overlay-shortcut-text'; |
| 360 shortcutText.style.visilibity = 'hidden'; |
| 361 key.appendChild(shortcutText); |
| 362 keyboard.appendChild(key); |
| 363 |
| 364 minX = Math.min(minX, x); |
| 365 maxX = Math.max(maxX, x + w); |
| 366 minY = Math.min(minY, y); |
| 367 maxY = Math.max(maxY, y + h); |
| 368 } |
| 369 |
| 370 var width = maxX - minX + 1; |
| 371 var height = maxY - minY + 1; |
| 372 keyboard.style.width = (width + 2 * (minX + 1)) + 'px'; |
| 373 keyboard.style.height = (height + 2 * (minY + 1)) + 'px'; |
| 374 |
| 375 var instructions = document.createElement('instructions'); |
| 376 instructions = document.createElement('div'); |
| 377 instructions.id = 'instructions'; |
| 378 instructions.className = 'keyboard-overlay-instructions'; |
| 379 instructions.style.left = ((BASE_INSTRUCTIONS.left - BASE_KEYBOARD.left) * |
| 380 width / BASE_KEYBOARD.width + minX) + 'px'; |
| 381 instructions.style.top = ((BASE_INSTRUCTIONS.top - BASE_KEYBOARD.top) * |
| 382 height / BASE_KEYBOARD.height + minY) + 'px'; |
| 383 instructions.style.width = (width * BASE_INSTRUCTIONS.width / |
| 384 BASE_KEYBOARD.width) + 'px'; |
| 385 instructions.style.height = (height * BASE_INSTRUCTIONS.height / |
| 386 BASE_KEYBOARD.height) + 'px'; |
| 387 |
| 388 var instructionsText = document.createElement('span'); |
| 389 instructionsText.id = 'instructions-text'; |
| 390 instructionsText.className = 'keyboard-overlay-instructions-text'; |
| 391 instructionsText.innerHTML = templateData.keyboardOverlayInstructions; |
| 392 instructions.appendChild(instructionsText); |
| 393 keyboard.appendChild(instructions); |
| 394 } |
| 395 |
| 396 /** |
| 397 * A callback function for the onload event of the body element. |
| 398 */ |
| 399 function init() { |
| 400 document.addEventListener('keydown', keydown); |
| 401 document.addEventListener('keyup', keyup); |
| 402 initLayout(); |
| 403 update(); |
| 404 } |
| 405 |
| 406 document.addEventListener('DOMContentLoaded', init); |
OLD | NEW |