PageSourceSearch

https://hodaielab.github.io/aframe-keyboard-controls.js

js hodaielab.github.io collected 2026-10-03 09:18:04 UTC 40,275 bytes, 1,119 lines download raw bytes

1/******/ (function(modules) { // webpackBootstrap
2/******/ 	// The module cache
3/******/ 	var installedModules = {};
4
5/******/ 	// The require function
6/******/ 	function __webpack_require__(moduleId) {
7
8/******/ 		// Check if module is in cache
9/******/ 		if(installedModules[moduleId])
10/******/ 			return installedModules[moduleId].exports;
11
12/******/ 		// Create a new module (and put it into the cache)
13/******/ 		var module = installedModules[moduleId] = {
14/******/ 			exports: {},
15/******/ 			id: moduleId,
16/******/ 			loaded: false
17/******/ 		};
18
19/******/ 		// Execute the module function
20/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21
22/******/ 		// Flag the module as loaded
23/******/ 		module.loaded = true;
24
25/******/ 		// Return the exports of the module
26/******/ 		return module.exports;
27/******/ 	}
28
29
30/******/ 	// expose the modules object (__webpack_modules__)
31/******/ 	__webpack_require__.m = modules;
32
33/******/ 	// expose the module cache
34/******/ 	__webpack_require__.c = installedModules;
35
36/******/ 	// __webpack_public_path__
37/******/ 	__webpack_require__.p = "";
38
39/******/ 	// Load entry module and return exports
40/******/ 	return __webpack_require__(0);
41/******/ })
42/************************************************************************/
43/******/ ([
44/* 0 */
45/***/ function(module, exports, __webpack_require__) {
46
47	
48	// Browser distrubution of the A-Frame component.
49	(function (AFRAME) {
50	  if (!AFRAME) {
51	    console.error('Component attempted to register before AFRAME was available.');
52	    return;
53	  }
54
55	  (AFRAME.aframeCore || AFRAME).registerComponent('keyboard-controls', __webpack_require__(1));
56
57	}(window.AFRAME));
58
59
60/***/ },
61/* 1 */
62/***/ function(module, exports, __webpack_require__) {
63
64	__webpack_require__(2);
65
66	var MAX_DELTA = 0.2,
67	    PROXY_FLAG = '__keyboard-controls-proxy';
68
69	var KeyboardEvent = window.KeyboardEvent;
70
71	/**
72	 * Keyboard Controls component.
73	 *
74	 * Bind keyboard events to components, or control your entities with the WASD keys.
75	 *
76	 * @namespace wasd-controls
77	 * @param {number} [easing=20] - How fast the movement decelerates. If you hold the
78	 * keys the entity moves and if you release it will stop. Easing simulates friction.
79	 * @param {number} [acceleration=65] - Determines the acceleration given
80	 * to the entity when pressing the keys.
81	 * @param {bool} [enabled=true] - To completely enable or disable the controls
82	 * @param {bool} [fly=false] - Determines if the direction of the movement sticks
83	 * to the plane where the entity started off or if there are 6 degrees of
84	 * freedom as a diver underwater or a plane flying.
85	 * @param {string} [rollAxis='z'] - The front-to-back axis.
86	 * @param {string} [pitchAxis='x'] - The left-to-right axis.
87	 * @param {bool} [rollAxisInverted=false] - Roll axis is inverted
88	 * @param {bool} [pitchAxisInverted=false] - Pitch axis is inverted
89	 */
90	module.exports = {
91	  schema: {
92	 
93	    easing:            { default: 20 },
94	    acceleration:      { default: 65 },
95	    enabled:           { default: true },
96	    fly:               { default: false },
97	    rollAxis:          { default: 'z', oneOf: [ 'x', 'y', 'z' ] },
98	    pitchAxis:         { default: 'x', oneOf: [ 'x', 'y', 'z' ] },
99	    yawAxis:           { default: 'y', oneOf: [ 'x', 'y', 'z' ] },
100	    rollAxisInverted:  { default: false },
101	    rollAxisEnabled:   { default: true },
102	    pitchAxisInverted: { default: false },
103	    pitchAxisEnabled:  { default: true },
104	    yawAxisInverted:   { default: false },
105	    yawAxisEnabled:    { default: true },
106	    debug:             { default: false },
107
108	    //added for rotation 
109	    cameraUse: 	       { default: true } 
110	  },
111
112
113	init: function () {
114	    this.velocity = new THREE.Vector3();
115	    this.angle= new THREE.Euler();
116	    this.localKeys = {};
117	    this.listeners = {
118	      keydown: this.onKeyDown.bind(this),
119	      keyup: this.onKeyUp.bind(this),
120	      blur: this.onBlur.bind(this)
121	    };
122
123	    var sceneEl = this.el.sceneEl;
124	    if (sceneEl.addBehavior) {
125	      sceneEl.addBehavior(this);
126	      this.attachEventListeners();
127	    }
128	  },
129
130	  /*******************************************************************
131	  * Movement
132	  */
133
134	  tick: function () { 
135	  	this.update(); 
136	  },
137
138	  update: function (previousData) {
139	    var data = this.data;
140	    var acceleration = data.acceleration;
141	    var easing = data.easing;
142	    var velocity = this.velocity;
143	    var prevTime = this.prevTime = this.prevTime || Date.now();
144	    var time = window.performance.now();
145	    var delta = (time - prevTime) / 1000;
146	    var keys = this.getKeys();
147
148	    var movementVector;
149	    var pitchAxis = data.pitchAxis;
150	    var rollAxis = data.rollAxis;
151	    var yawAxis = data.yawAxis;
152	    var pitchSign = data.pitchAxisInverted ? -1 : 1;
153	    var rollSign = data.rollAxisInverted ? -1 : 1;
154	    var yawSign = data.yawAxisInverted ? -1 : 1;
155	    var el = this.el;
156	    this.prevTime = time;
157
158	    //added for rotation 
159	    var angle = this.angle;
160	    var object3D = el.object3D; 
161	    var rotationVector;
162	 	object3D.rotation.order='YXZ';
163
164	    // If data changed or FPS too low, reset velocity.
165	    if (previousData || delta > MAX_DELTA) {
166	      velocity[pitchAxis] = 0;
167	      velocity[rollAxis] = 0;
168	      velocity[yawAxis] = 0;
169
170	      //added for rotation 
171	      angle[pitchAxis] = 0;
172	      angle[rollAxis] = 0;
173	      angle[yawAxis] = 0;
174	      //
175
176	      return;
177	    }
178
179	    if (data.cameraUse){
180		    velocity[pitchAxis] -= velocity[pitchAxis] * easing * delta;
181		    velocity[rollAxis] -= velocity[rollAxis] * easing * delta;
182		    velocity[yawAxis] -= velocity[yawAxis] * easing * delta;
183		}
184
185	    else if (!data.cameraUse){
186		    angle[pitchAxis] -= angle[pitchAxis] * easing * delta;
187		    angle[rollAxis] -= angle[rollAxis] * easing * delta;
188		    angle[yawAxis] -= angle[yawAxis] * easing * delta;
189		}    
190
191	    var position = el.getComputedAttribute('position');
192
193	    //added for rotation 
194	    var rotation = el.getComputedAttribute('rotation');
195
196        if (data.cameraUse){
197		    if (data.enabled) {
198		      if (data.pitchAxisEnabled) {
199		        if (keys.KeyA)  {
200		          velocity[pitchAxis] -= pitchSign * acceleration * delta;
201		        }
202		        if (keys.KeyD) {
203		          velocity[pitchAxis] += pitchSign * acceleration * delta;
204		        }
205		      }
206		      if (data.rollAxisEnabled) {
207		        if (keys.KeyW)   {
208		          velocity[rollAxis] -= rollSign * acceleration * delta;
209		        }
210		        if (keys.KeyS) {
211		          velocity[rollAxis] += rollSign * acceleration * delta;
212		        }
213		      }
214		      if (data.yawAxisEnabled) {
215		        if (keys.KeyQ)   {
216		          velocity[yawAxis] -= yawSign * acceleration * delta;
217		        }
218		        if (keys.KeyE) {
219		          velocity[yawAxis] += yawSign * acceleration * delta;
220		        }
221		      }
222		    }
223		}
224
225		//added for rotation 
226		else if(!data.cameraUse){
227			if (data.enabled) {
228		      if (data.pitchAxisEnabled) {
229		        if (keys.KeyJ)  {
230		          angle[pitchAxis] -= pitchSign * acceleration * delta;
231		        }
232		        if (keys.KeyL) {
233		          angle[pitchAxis] += pitchSign * acceleration * delta;
234		        }
235		      }
236		      if (data.rollAxisEnabled) {
237		        if (keys.KeyI)   {
238		          angle[rollAxis] -= rollSign * acceleration * delta;
239		        }
240		        if (keys.KeyK) {
241		          angle[rollAxis] += rollSign * acceleration * delta;
242		        }
243		      }
244		      if (data.yawAxisEnabled) {
245		        if (keys.KeyU)   {
246		          angle[yawAxis] -= yawSign * acceleration * delta;
247		        }
248		        if (keys.KeyO) {
249		          angle[yawAxis] += yawSign * acceleration * delta;
250		        }
251		      }
252		    }
253		}
254
255	    if (data.cameraUse){
256		    movementVector = this.getMovementVector(delta);
257		    el.setAttribute('position', {
258		      x: position.x + movementVector.x,
259		      y: position.y + movementVector.y,
260		      z: position.z + movementVector.z
261		    });
262		}
263
264	    //added for rotation 
265
266	    else if (!data.cameraUse){
267		    el.setAttribute('rotation',{
268		      x: rotation.x + angle.x,
269		      y: rotation.y + angle.y,
270		      z: rotation.z + angle.z
271		    });
272		}
273	  },
274
275	  getMovementVector: (function (delta) {
276	    var direction = new THREE.Vector3(0, 0, 0);
277	    var rotation = new THREE.Euler(0, 0, 0, 'YXZ');
278	    return function (delta) {
279	      var velocity = this.velocity;
280	      var elRotation = this.el.getAttribute('rotation');
281	      direction.copy(velocity);
282	      direction.multiplyScalar(delta);
283	      if (!elRotation) { return direction; }
284	      if (!this.data.fly) { elRotation.x = 0; }
285	      rotation.set(THREE.Math.degToRad(elRotation.x),
286	                   THREE.Math.degToRad(elRotation.y), 0);
287	      direction.applyEuler(rotation);
288	      return direction;
289	    };
290	  })
291	  (),
292
293	  /*******************************************************************
294	  * Events
295	  */
296
297	  play: function () {
298	    this.attachEventListeners();
299	  },
300
301	  pause: function () {
302	    this.removeEventListeners();
303	  },
304
305	  tick: function (t) { // jshint ignore:line
306	    this.update();
307	  },
308
309	  remove: function () {
310	    this.pause();
311	  },
312
313	  attachEventListeners: function () {
314	    window.addEventListener('keydown', this.listeners.keydown, false);
315	    window.addEventListener('keyup', this.listeners.keyup, false);
316	    window.addEventListener('blur', this.listeners.blur, false);
317	  },
318
319	  removeEventListeners: function () {
320	    window.removeEventListener('keydown', this.listeners.keydown);
321	    window.removeEventListener('keyup', this.listeners.keyup);
322	    window.removeEventListener('blur', this.listeners.blur);
323	  },
324
325	  onKeyDown: function (event) {
326	    this.localKeys[event.code] = true;
327	    this.emit(event);
328	  },
329
330	  onKeyUp: function (event) {
331	    delete this.localKeys[event.code];
332	    this.emit(event);
333	  },
334
335	  onBlur: function () {
336	    for (var code in this.localKeys) {
337	      if (this.localKeys.hasOwnProperty(code)) {
338	        delete this.localKeys[code];
339	      }
340	    }
341	  },
342
343	  emit: function (event) {
344	    // TODO - keydown only initially?
345	    // TODO - where the f is the spacebar
346
347	    // Emit original event.
348	    if (PROXY_FLAG in event) {
349	      // TODO - Method never triggered.
350	      this.el.emit(event.type, event);
351	    }
352
353	    // Emit convenience event, identifying key.
354	    this.el.emit(event.type + ':' + event.code, new KeyboardEvent(event.type, event));
355	    if (this.data.debug) console.log(event.type + ':' + event.code);
356	  },
357
358	  /*******************************************************************
359	  * Accessors
360	  */
361	 
362	  isPressed: function (code) {
363	    return code in this.getKeys();
364	  },
365
366	  getKeys: function () {
367	    if (this.isProxied()) {
368	      return this.el.sceneEl.components['proxy-controls'].getKeyboard();
369	    }
370	    return this.localKeys;
371	  },
372
373	  isProxied: function () {
374	    var proxyControls = this.el.sceneEl.components['proxy-controls'];
375	    return proxyControls && proxyControls.isConnected();
376	  }
377
378	};
379
380
381/***/ },
382/* 2 */
383/***/ function(module, exports) {
384
385	/**
386	 * Polyfill for the additional KeyboardEvent properties defined in the D3E and
387	 * D4E draft specifications, by @inexorabletash.
388	 *
389	 * See: https://github.com/inexorabletash/polyfill
390	 */
391	(function(global) {
392	  var nativeKeyboardEvent = ('KeyboardEvent' in global);
393	  if (!nativeKeyboardEvent)
394	    global.KeyboardEvent = function KeyboardEvent() { throw TypeError('Illegal constructor'); };
395
396	  global.KeyboardEvent.DOM_KEY_LOCATION_STANDARD = 0x00; // Default or unknown location
397	  global.KeyboardEvent.DOM_KEY_LOCATION_LEFT          = 0x01; // e.g. Left Alt key
398	  global.KeyboardEvent.DOM_KEY_LOCATION_RIGHT         = 0x02; // e.g. Right Alt key
399	  global.KeyboardEvent.DOM_KEY_LOCATION_NUMPAD        = 0x03; // e.g. Numpad 0 or +
400
401	  var STANDARD = window.KeyboardEvent.DOM_KEY_LOCATION_STANDARD,
402	      LEFT = window.KeyboardEvent.DOM_KEY_LOCATION_LEFT,
403	      RIGHT = window.KeyboardEvent.DOM_KEY_LOCATION_RIGHT,
404	      NUMPAD = window.KeyboardEvent.DOM_KEY_LOCATION_NUMPAD;
405
406	  //--------------------------------------------------------------------
407	  //
408	  // Utilities
409	  //
410	  //--------------------------------------------------------------------
411
412	  function contains(s, ss) { return String(s).indexOf(ss) !== -1; }
413
414	  var os = (function() {
415	    if (contains(navigator.platform, 'Win')) { return 'win'; }
416	    if (contains(navigator.platform, 'Mac')) { return 'mac'; }
417	    if (contains(navigator.platform, 'CrOS')) { return 'cros'; }
418	    if (contains(navigator.platform, 'Linux')) { return 'linux'; }
419	    if (contains(navigator.userAgent, 'iPad') || contains(navigator.platform, 'iPod') || contains(navigator.platform, 'iPhone')) { return 'ios'; }
420	    return '';
421	  } ());
422
423	  var browser = (function() {
424	    if (contains(navigator.userAgent, 'Chrome/')) { return 'chrome'; }
425	    if (contains(navigator.vendor, 'Apple')) { return 'safari'; }
426	    if (contains(navigator.userAgent, 'MSIE')) { return 'ie'; }
427	    if (contains(navigator.userAgent, 'Gecko/')) { return 'moz'; }
428	    if (contains(navigator.userAgent, 'Opera/')) { return 'opera'; }
429	    return '';
430	  } ());
431
432	  var browser_os = browser + '-' + os;
433
434	  function mergeIf(baseTable, select, table) {
435	    if (browser_os === select || browser === select || os === select) {
436	      Object.keys(table).forEach(function(keyCode) {
437	        baseTable[keyCode] = table[keyCode];
438	      });
439	    }
440	  }
441
442	  function remap(o, key) {
443	    var r = {};
444	    Object.keys(o).forEach(function(k) {
445	      var item = o[k];
446	      if (key in item) {
447	        r[item[key]] = item;
448	      }
449	    });
450	    return r;
451	  }
452
453	  function invert(o) {
454	    var r = {};
455	    Object.keys(o).forEach(function(k) {
456	      r[o[k]] = k;
457	    });
458	    return r;
459	  }
460
461	  //--------------------------------------------------------------------
462	  //
463	  // Generic Mappings
464	  //
465	  //--------------------------------------------------------------------
466
467	  // "keyInfo" is a dictionary:
468	  //   code: string - name from DOM Level 3 KeyboardEvent code Values
469	  //     https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3Events-code.html
470	  //   location (optional): number - one of the DOM_KEY_LOCATION values
471	  //   keyCap (optional): string - keyboard label in en-US locale
472	  // USB code Usage ID from page 0x07 unless otherwise noted (Informative)
473
474	  // Map of keyCode to keyInfo
475	  var keyCodeToInfoTable = {
476	    // 0x01 - VK_LBUTTON
477	    // 0x02 - VK_RBUTTON
478	    0x03: { code: 'Cancel' }
478, // [USB: 0x9b] char \x0018 ??? (Not in D3E)
479	    // 0x04 - VK_MBUTTON
480	    // 0x05 - VK_XBUTTON1
481	    // 0x06 - VK_XBUTTON2
482	    0x06: { code: 'Help' }, // [USB: 0x75] ???
483	    // 0x07 - undefined
484	    0x08: { code: 'Backspace' }, // [USB: 0x2a] Labelled Delete on Macintosh keyboards.
485	    0x09: { code: 'Tab' }, // [USB: 0x2b]
486	    // 0x0A-0x0B - reserved
487	    0X0C: { code: 'Clear' }, // [USB: 0x9c] NumPad Center (Not in D3E)
488	    0X0D: { code: 'Enter' }, // [USB: 0x28]
489	    // 0x0E-0x0F - undefined
490
491	    0x10: { code: 'Shift' },
492	    0x11: { code: 'Control' },
493	    0x12: { code: 'Alt' },
494	    0x13: { code: 'Pause' }, // [USB: 0x48]
495	    0x14: { code: 'CapsLock' }, // [USB: 0x39]
496	    0x15: { code: 'KanaMode' }, // [USB: 0x88] - "HangulMode" for Korean layout
497	    0x16: { code: 'HangulMode' }, // [USB: 0x90] 0x15 as well in MSDN VK table ???
498	    0x17: { code: 'JunjaMode' }, // (Not in D3E)
499	    0x18: { code: 'FinalMode' }, // (Not in D3E)
500	    0x19: { code: 'KanjiMode' }, // [USB: 0x91] - "HanjaMode" for Korean layout
501	    // 0x1A - undefined
502	    0x1B: { code: 'Escape' }
502, // [USB: 0x29]
503	    0x1C: { code: 'Convert' }, // [USB: 0x8a]
504	    0x1D: { code: 'NonConvert' }, // [USB: 0x8b]
505	    0x1E: { code: 'Accept' }, // (Not in D3E)
506	    0x1F: { code: 'ModeChange' }, // (Not in D3E)
507
508	    0x20: { code: 'Space' }, // [USB: 0x2c]
509	    0x21: { code: 'PageUp' }, // [USB: 0x4b]
510	    0x22: { code: 'PageDown' }, // [USB: 0x4e]
511	    0x23: { code: 'End' }, // [USB: 0x4d]
512	    0x24: { code: 'Home' }, // [USB: 0x4a]
513	    0x25: { code: 'ArrowLeft' }, // [USB: 0x50]
514	    0x26: { code: 'ArrowUp' }, // [USB: 0x52]
515	    0x27: { code: 'ArrowRight' }, // [USB: 0x4f]
516	    0x28: { code: 'ArrowDown' }, // [USB: 0x51]
517	    0x29: { code: 'Select' }, // (Not in D3E)
518	    0x2A: { code: 'Print' }, // (Not in D3E)
519	    0x2B: { code: 'Execute' }, // [USB: 0x74] (Not in D3E)
520	    0x2C: { code: 'PrintScreen' }, // [USB: 0x46]
521	    0x2D: { code: 'Insert' }, // [USB: 0x49]
522	    0x2E: { code: 'Delete' }, // [USB: 0x4c]
523	    0x2F: { code: 'Help' }, // [USB: 0x75] ???
524
525	    0x30: { code: 'Digit0', keyCap: '0' }, // [USB: 0x27] 0)
526	    0x31: { code: 'Digit1', keyCap: '1' }
526, // [USB: 0x1e] 1!
527	    0x32: { code: 'Digit2', keyCap: '2' }, // [USB: 0x1f] 2@
528	    0x33: { code: 'Digit3', keyCap: '3' }, // [USB: 0x20] 3#
529	    0x34: { code: 'Digit4', keyCap: '4' }, // [USB: 0x21] 4$
530	    0x35: { code: 'Digit5', keyCap: '5' }, // [USB: 0x22] 5%
531	    0x36: { code: 'Digit6', keyCap: '6' }, // [USB: 0x23] 6^
532	    0x37: { code: 'Digit7', keyCap: '7' }, // [USB: 0x24] 7&
533	    0x38: { code: 'Digit8', keyCap: '8' }, // [USB: 0x25] 8*
534	    0x39: { code: 'Digit9', keyCap: '9' }, // [USB: 0x26] 9(
535	    // 0x3A-0x40 - undefined
536
537	    0x41: { code: 'KeyA', keyCap: 'a' }, // [USB: 0x04]
538	    0x42: { code: 'KeyB', keyCap: 'b' }, // [USB: 0x05]
539	    0x43: { code: 'KeyC', keyCap: 'c' }, // [USB: 0x06]
540	    0x44: { code: 'KeyD', keyCap: 'd' }, // [USB: 0x07]
541	    0x45: { code: 'KeyE', keyCap: 'e' }, // [USB: 0x08]
542	    0x46: { code: 'KeyF', keyCap: 'f' }, // [USB: 0x09]
543	    0x47: { code: 'KeyG', keyCap: 'g' }, // [USB: 0x0a]
544	    0x48: { code: 'KeyH', keyCap: 'h' }, // [USB: 0x0b]
545	    0x49: { code: 'KeyI', keyCap: 'i' }
545, // [USB: 0x0c]
546	    0x4A: { code: 'KeyJ', keyCap: 'j' }, // [USB: 0x0d]
547	    0x4B: { code: 'KeyK', keyCap: 'k' }, // [USB: 0x0e]
548	    0x4C: { code: 'KeyL', keyCap: 'l' }, // [USB: 0x0f]
549	    0x4D: { code: 'KeyM', keyCap: 'm' }, // [USB: 0x10]
550	    0x4E: { code: 'KeyN', keyCap: 'n' }, // [USB: 0x11]
551	    0x4F: { code: 'KeyO', keyCap: 'o' }, // [USB: 0x12]
552
553	    0x50: { code: 'KeyP', keyCap: 'p' }, // [USB: 0x13]
554	    0x51: { code: 'KeyQ', keyCap: 'q' }, // [USB: 0x14]
555	    0x52: { code: 'KeyR', keyCap: 'r' }, // [USB: 0x15]
556	    0x53: { code: 'KeyS', keyCap: 's' }, // [USB: 0x16]
557	    0x54: { code: 'KeyT', keyCap: 't' }, // [USB: 0x17]
558	    0x55: { code: 'KeyU', keyCap: 'u' }, // [USB: 0x18]
559	    0x56: { code: 'KeyV', keyCap: 'v' }, // [USB: 0x19]
560	    0x57: { code: 'KeyW', keyCap: 'w' }, // [USB: 0x1a]
561	    0x58: { code: 'KeyX', keyCap: 'x' }, // [USB: 0x1b]
562	    0x59: { code: 'KeyY', keyCap: 'y' }, // [USB: 0x1c]
563	    0x5A: { code: 'KeyZ', keyCap: 'z' }, // [USB: 0x1d]
564	    0x5B: { code: 'OSLeft', location: LEFT }
564, // [USB: 0xe3]
565	    0x5C: { code: 'OSRight', location: RIGHT }, // [USB: 0xe7]
566	    0x5D: { code: 'ContextMenu' }, // [USB: 0x65] Context Menu
567	    // 0x5E - reserved
568	    0x5F: { code: 'Standby' }, // [USB: 0x82] Sleep
569
570	    0x60: { code: 'Numpad0', keyCap: '0', location: NUMPAD }, // [USB: 0x62]
571	    0x61: { code: 'Numpad1', keyCap: '1', location: NUMPAD }, // [USB: 0x59]
572	    0x62: { code: 'Numpad2', keyCap: '2', location: NUMPAD }, // [USB: 0x5a]
573	    0x63: { code: 'Numpad3', keyCap: '3', location: NUMPAD }, // [USB: 0x5b]
574	    0x64: { code: 'Numpad4', keyCap: '4', location: NUMPAD }, // [USB: 0x5c]
575	    0x65: { code: 'Numpad5', keyCap: '5', location: NUMPAD }, // [USB: 0x5d]
576	    0x66: { code: 'Numpad6', keyCap: '6', location: NUMPAD }, // [USB: 0x5e]
577	    0x67: { code: 'Numpad7', keyCap: '7', location: NUMPAD }, // [USB: 0x5f]
578	    0x68: { code: 'Numpad8', keyCap: '8', location: NUMPAD }, // [USB: 0x60]
579	    0x69: { code: 'Numpad9', keyCap: '9', location: NUMPAD }, // [USB: 0x61]
580	    0x6A: { code: 'NumpadMultiply', keyCap: '*', location: NUMPAD }
580, // [USB: 0x55]
581	    0x6B: { code: 'NumpadAdd', keyCap: '+', location: NUMPAD }, // [USB: 0x57]
582	    0x6C: { code: 'NumpadComma', keyCap: ',', location: NUMPAD }, // [USB: 0x85]
583	    0x6D: { code: 'NumpadSubtract', keyCap: '-', location: NUMPAD }, // [USB: 0x56]
584	    0x6E: { code: 'NumpadDecimal', keyCap: '.', location: NUMPAD }, // [USB: 0x63]
585	    0x6F: { code: 'NumpadDivide', keyCap: '/', location: NUMPAD }, // [USB: 0x54]
586
587	    0x70: { code: 'F1' }, // [USB: 0x3a]
588	    0x71: { code: 'F2' }, // [USB: 0x3b]
589	    0x72: { code: 'F3' }, // [USB: 0x3c]
590	    0x73: { code: 'F4' }, // [USB: 0x3d]
591	    0x74: { code: 'F5' }, // [USB: 0x3e]
592	    0x75: { code: 'F6' }, // [USB: 0x3f]
593	    0x76: { code: 'F7' }, // [USB: 0x40]
594	    0x77: { code: 'F8' }, // [USB: 0x41]
595	    0x78: { code: 'F9' }, // [USB: 0x42]
596	    0x79: { code: 'F10' }, // [USB: 0x43]
597	    0x7A: { code: 'F11' }, // [USB: 0x44]
598	    0x7B: { code: 'F12' }, // [USB: 0x45]
599	    0x7C: { code: 'F13' }, // [USB: 0x68]
600	    0x7D: { code: 'F14' }, // [USB: 0x69]
601	    0x7E: { code: 'F15' }
601, // [USB: 0x6a]
602	    0x7F: { code: 'F16' }, // [USB: 0x6b]
603
604	    0x80: { code: 'F17' }, // [USB: 0x6c]
605	    0x81: { code: 'F18' }, // [USB: 0x6d]
606	    0x82: { code: 'F19' }, // [USB: 0x6e]
607	    0x83: { code: 'F20' }, // [USB: 0x6f]
608	    0x84: { code: 'F21' }, // [USB: 0x70]
609	    0x85: { code: 'F22' }, // [USB: 0x71]
610	    0x86: { code: 'F23' }, // [USB: 0x72]
611	    0x87: { code: 'F24' }, // [USB: 0x73]
612	    // 0x88-0x8F - unassigned
613
614	    0x90: { code: 'NumLock', location: NUMPAD }, // [USB: 0x53]
615	    0x91: { code: 'ScrollLock' }, // [USB: 0x47]
616	    // 0x92-0x96 - OEM specific
617	    // 0x97-0x9F - unassigned
618
619	    // NOTE: 0xA0-0xA5 usually mapped to 0x10-0x12 in browsers
620	    0xA0: { code: 'ShiftLeft', location: LEFT }, // [USB: 0xe1]
621	    0xA1: { code: 'ShiftRight', location: RIGHT }, // [USB: 0xe5]
622	    0xA2: { code: 'ControlLeft', location: LEFT }, // [USB: 0xe0]
623	    0xA3: { code: 'ControlRight', location: RIGHT }, // [USB: 0xe4]
624	    0xA4: { code: 'AltLeft', location: LEFT }, // [USB: 0xe2]
625	    0xA5: { code: 'AltRight', location: RIGHT }
625, // [USB: 0xe6]
626
627	    0xA6: { code: 'BrowserBack' }, // [USB: 0x0c/0x0224]
628	    0xA7: { code: 'BrowserForward' }, // [USB: 0x0c/0x0225]
629	    0xA8: { code: 'BrowserRefresh' }, // [USB: 0x0c/0x0227]
630	    0xA9: { code: 'BrowserStop' }, // [USB: 0x0c/0x0226]
631	    0xAA: { code: 'BrowserSearch' }, // [USB: 0x0c/0x0221]
632	    0xAB: { code: 'BrowserFavorites' }, // [USB: 0x0c/0x0228]
633	    0xAC: { code: 'BrowserHome' }, // [USB: 0x0c/0x0222]
634	    0xAD: { code: 'VolumeMute' }, // [USB: 0x7f]
635	    0xAE: { code: 'VolumeDown' }, // [USB: 0x81]
636	    0xAF: { code: 'VolumeUp' }, // [USB: 0x80]
637
638	    0xB0: { code: 'MediaTrackNext' }, // [USB: 0x0c/0x00b5]
639	    0xB1: { code: 'MediaTrackPrevious' }, // [USB: 0x0c/0x00b6]
640	    0xB2: { code: 'MediaStop' }, // [USB: 0x0c/0x00b7]
641	    0xB3: { code: 'MediaPlayPause' }, // [USB: 0x0c/0x00cd]
642	    0xB4: { code: 'LaunchMail' }, // [USB: 0x0c/0x018a]
643	    0xB5: { code: 'MediaSelect' },
644	    0xB6: { code: 'LaunchApp1' },
645	    0xB7: { code: 'LaunchApp2' },
646	    // 0xB8-0xB9 - reserved
647	    0xBA: { code: 'Semicolon',  keyCap: ';' }
647, // [USB: 0x33] ;: (US Standard 101)
648	    0xBB: { code: 'Equal', keyCap: '=' }, // [USB: 0x2e] =+
649	    0xBC: { code: 'Comma', keyCap: ',' }, // [USB: 0x36] ,<
650	    0xBD: { code: 'Minus', keyCap: '-' }, // [USB: 0x2d] -_
651	    0xBE: { code: 'Period', keyCap: '.' }, // [USB: 0x37] .>
652	    0xBF: { code: 'Slash', keyCap: '/' }, // [USB: 0x38] /? (US Standard 101)
653
654	    0xC0: { code: 'Backquote', keyCap: '`' }, // [USB: 0x35] `~ (US Standard 101)
655	    // 0xC1-0xCF - reserved
656
657	    // 0xD0-0xD7 - reserved
658	    // 0xD8-0xDA - unassigned
659	    0xDB: { code: 'BracketLeft', keyCap: '[' }, // [USB: 0x2f] [{ (US Standard 101)
660	    0xDC: { code: 'Backslash',  keyCap: '\\' }, // [USB: 0x31] \| (US Standard 101)
661	    0xDD: { code: 'BracketRight', keyCap: ']' }, // [USB: 0x30] ]} (US Standard 101)
662	    0xDE: { code: 'Quote', keyCap: '\'' }, // [USB: 0x34] '" (US Standard 101)
663	    // 0xDF - miscellaneous/varies
664
665	    // 0xE0 - reserved
666	    // 0xE1 - OEM specific
667	    0xE2: { code: 'IntlBackslash',  keyCap: '\\' }, // [USB: 0x64] \| (UK Standard 102)
668	    // 0xE3-0xE4 - OEM specific
669	    0xE5: { code: 'Process' }, // (Not in D3E)
670	    // 0xE6 - OEM specific
671	    // 0xE7 - VK_PACKET
672	    // 0xE8 - unassigned
673	    // 0xE9-0xEF - OEM specific
674
675	    // 0xF0-0xF5 - OEM specific
676	    0xF6: { code: 'Attn' }
676, // [USB: 0x9a] (Not in D3E)
677	    0xF7: { code: 'CrSel' }, // [USB: 0xa3] (Not in D3E)
678	    0xF8: { code: 'ExSel' }, // [USB: 0xa4] (Not in D3E)
679	    0xF9: { code: 'EraseEof' }, // (Not in D3E)
680	    0xFA: { code: 'Play' }, // (Not in D3E)
681	    0xFB: { code: 'ZoomToggle' }, // (Not in D3E)
682	    // 0xFC - VK_NONAME - reserved
683	    // 0xFD - VK_PA1
684	    0xFE: { code: 'Clear' } // [USB: 0x9c] (Not in D3E)
685	  };
686
687	  // No legacy keyCode, but listed in D3E:
688
689	  // code: usb
690	  // 'IntlHash': 0x070032,
691	  // 'IntlRo': 0x070087,
692	  // 'IntlYen': 0x070089,
693	  // 'NumpadBackspace': 0x0700bb,
694	  // 'NumpadClear': 0x0700d8,
695	  // 'NumpadClearEntry': 0x0700d9,
696	  // 'NumpadMemoryAdd': 0x0700d3,
697	  // 'NumpadMemoryClear': 0x0700d2,
698	  // 'NumpadMemoryRecall': 0x0700d1,
699	  // 'NumpadMemoryStore': 0x0700d0,
700	  // 'NumpadMemorySubtract': 0x0700d4,
701	  // 'NumpadParenLeft': 0x0700b6,
702	  // 'NumpadParenRight': 0x0700b7,
703
704	  //--------------------------------------------------------------------
705	  //
706	  // Browser/OS Specific Mappings
707	  //
708	  //--------------------------------------------------------------------
709
710	  mergeIf(keyCodeToInfoTable,
711	          'moz', {
712	            0x3B: { code: 'Semicolon', keyCap: ';' }
712, // [USB: 0x33] ;: (US Standard 101)
713	            0x3D: { code: 'Equal', keyCap: '=' }, // [USB: 0x2e] =+
714	            0x6B: { code: 'Equal', keyCap: '=' }, // [USB: 0x2e] =+
715	            0x6D: { code: 'Minus', keyCap: '-' }, // [USB: 0x2d] -_
716	            0xBB: { code: 'NumpadAdd', keyCap: '+', location: NUMPAD }, // [USB: 0x57]
717	            0xBD: { code: 'NumpadSubtract', keyCap: '-', location: NUMPAD } // [USB: 0x56]
718	          });
719
720	  mergeIf(keyCodeToInfoTable,
721	          'moz-mac', {
722	            0x0C: { code: 'NumLock', location: NUMPAD }, // [USB: 0x53]
723	            0xAD: { code: 'Minus', keyCap: '-' } // [USB: 0x2d] -_
724	          });
725
726	  mergeIf(keyCodeToInfoTable,
727	          'moz-win', {
728	            0xAD: { code: 'Minus', keyCap: '-' } // [USB: 0x2d] -_
729	          });
730
731	  mergeIf(keyCodeToInfoTable,
732	          'chrome-mac', {
733	            0x5D: { code: 'OSRight', location: RIGHT } // [USB: 0xe7]
734	          });
735
736	  // Windows via Bootcamp (!)
737	  if (0) {
738	    mergeIf(keyCodeToInfoTable,
739	            'chrome-win', {
740	              0xC0: { code: 'Quote', keyCap: '\'' }
740, // [USB: 0x34] '" (US Standard 101)
741	              0xDE: { code: 'Backslash',  keyCap: '\\' }, // [USB: 0x31] \| (US Standard 101)
742	              0xDF: { code: 'Backquote', keyCap: '`' } // [USB: 0x35] `~ (US Standard 101)
743	            });
744
745	    mergeIf(keyCodeToInfoTable,
746	            'ie', {
747	              0xC0: { code: 'Quote', keyCap: '\'' }, // [USB: 0x34] '" (US Standard 101)
748	              0xDE: { code: 'Backslash',  keyCap: '\\' }, // [USB: 0x31] \| (US Standard 101)
749	              0xDF: { code: 'Backquote', keyCap: '`' } // [USB: 0x35] `~ (US Standard 101)
750	            });
751	  }
752
753	  mergeIf(keyCodeToInfoTable,
754	          'safari', {
755	            0x03: { code: 'Enter' }, // [USB: 0x28] old Safari
756	            0x19: { code: 'Tab' } // [USB: 0x2b] old Safari for Shift+Tab
757	          });
758
759	  mergeIf(keyCodeToInfoTable,
760	          'ios', {
761	            0x0A: { code: 'Enter', location: STANDARD } // [USB: 0x28]
762	          });
763
764	  mergeIf(keyCodeToInfoTable,
765	          'safari-mac', {
766	            0x5B: { code: 'OSLeft', location: LEFT }
vendor: 2,428 bytes, lines 766-824
766, // [USB: 0xe3]
767	            0x5D: { code: 'OSRight', location: RIGHT }, // [USB: 0xe7]
768	            0xE5: { code: 'KeyQ', keyCap: 'Q' } // [USB: 0x14] On alternate presses, Ctrl+Q sends this
769	          });
770
771	  //--------------------------------------------------------------------
772	  //
773	  // Identifier Mappings
774	  //
775	  //--------------------------------------------------------------------
776
777	  // Cases where newer-ish browsers send keyIdentifier which can be
778	  // used to disambiguate keys.
779
780	  // keyIdentifierTable[keyIdentifier] -> keyInfo
781
782	  var keyIdentifierTable = {};
783	  if ('cros' === os) {
784	    keyIdentifierTable['U+00A0'] = { code: 'ShiftLeft', location: LEFT };
785	    keyIdentifierTable['U+00A1'] = { code: 'ShiftRight', location: RIGHT };
786	    keyIdentifierTable['U+00A2'] = { code: 'ControlLeft', location: LEFT };
787	    keyIdentifierTable['U+00A3'] = { code: 'ControlRight', location: RIGHT };
788	    keyIdentifierTable['U+00A4'] = { code: 'AltLeft', location: LEFT };
789	    keyIdentifierTable['U+00A5'] = { code: 'AltRight', location: RIGHT };
790	  }
791	  if ('chrome-mac' === browser_os) {
792	    keyIdentifierTable['U+0010'] = { code: 'ContextMenu' };
793	  }
794	  if ('safari-mac' === browser_os) {
795	    keyIdentifierTable['U+0010'] = { code: 'ContextMenu' };
796	  }
797	  if ('ios' === os) {
798	    // These only generate keyup events
799	    keyIdentifierTable['U+0010'] = { code: 'Function' };
800
801	    keyIdentifierTable['U+001C'] = { code: 'ArrowLeft' };
802	    keyIdentifierTable['U+001D'] = { code: 'ArrowRight' };
803	    keyIdentifierTable['U+001E'] = { code: 'ArrowUp' };
804	    keyIdentifierTable['U+001F'] = { code: 'ArrowDown' };
805
806	    keyIdentifierTable['U+0001'] = { code: 'Home' }; // [USB: 0x4a] Fn + ArrowLeft
807	    keyIdentifierTable['U+0004'] = { code: 'End' }; // [USB: 0x4d] Fn + ArrowRight
808	    keyIdentifierTable['U+000B'] = { code: 'PageUp' }; // [USB: 0x4b] Fn + ArrowUp
809	    keyIdentifierTable['U+000C'] = { code: 'PageDown' }; // [USB: 0x4e] Fn + ArrowDown
810	  }
811
812	  //--------------------------------------------------------------------
813	  //
814	  // Location Mappings
815	  //
816	  //--------------------------------------------------------------------
817
818	  // Cases where newer-ish browsers send location/keyLocation which
819	  // can be used to disambiguate keys.
820
821	  // locationTable[location][keyCode] -> keyInfo
822	  var locationTable = [];
823	  locationTable[LEFT] = {
824	    0x10: { code: 'ShiftLeft', location: LEFT }
824, // [USB: 0xe1]
825	    0x11: { code: 'ControlLeft', location: LEFT }, // [USB: 0xe0]
826	    0x12: { code: 'AltLeft', location: LEFT } // [USB: 0xe2]
827	  };
828	  locationTable[RIGHT] = {
829	    0x10: { code: 'ShiftRight', location: RIGHT }, // [USB: 0xe5]
830	    0x11: { code: 'ControlRight', location: RIGHT }, // [USB: 0xe4]
831	    0x12: { code: 'AltRight', location: RIGHT } // [USB: 0xe6]
832	  };
833	  locationTable[NUMPAD] = {
834	    0x0D: { code: 'NumpadEnter', location: NUMPAD } // [USB: 0x58]
835	  };
836
837	  mergeIf(locationTable[NUMPAD], 'moz', {
838	    0x6D: { code: 'NumpadSubtract', location: NUMPAD }, // [USB: 0x56]
839	    0x6B: { code: 'NumpadAdd', location: NUMPAD } // [USB: 0x57]
840	  });
841	  mergeIf(locationTable[LEFT], 'moz-mac', {
842	    0xE0: { code: 'OSLeft', location: LEFT } // [USB: 0xe3]
843	  });
844	  mergeIf(locationTable[RIGHT], 'moz-mac', {
845	    0xE0: { code: 'OSRight', location: RIGHT } // [USB: 0xe7]
846	  });
847	  mergeIf(locationTable[RIGHT], 'moz-win', {
848	    0x5B: { code: 'OSRight', location: RIGHT } // [USB: 0xe7]
849	  });
850
851
852	  mergeIf(locationTable[RIGHT], 'mac', {
853	    0x5D: { code: 'OSRight', location: RIGHT } // [USB: 0xe7]
854	  });
855
856	  mergeIf(locationTable[NUMPAD], 'chrome-mac', {
857	    0x0C: { code: 'NumLock', location: NUMPAD } // [USB: 0x53]
858	  });
859
860	  mergeIf(locationTable[NUMPAD], 'safari-mac', {
861	    0x0C: { code: 'NumLock', location: NUMPAD }
vendor: 8,748 bytes, lines 861-1119
861, // [USB: 0x53]
862	    0xBB: { code: 'NumpadAdd', location: NUMPAD }, // [USB: 0x57]
863	    0xBD: { code: 'NumpadSubtract', location: NUMPAD }, // [USB: 0x56]
864	    0xBE: { code: 'NumpadDecimal', location: NUMPAD }, // [USB: 0x63]
865	    0xBF: { code: 'NumpadDivide', location: NUMPAD } // [USB: 0x54]
866	  });
867
868
869	  //--------------------------------------------------------------------
870	  //
871	  // Key Values
872	  //
873	  //--------------------------------------------------------------------
874
875	  // Mapping from `code` values to `key` values. Values defined at:
876	  // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3Events-key.html
877	  // Entries are only provided when `key` differs from `code`. If
878	  // printable, `shiftKey` has the shifted printable character. This
879	  // assumes US Standard 101 layout
880
881	  var codeToKeyTable = {
882	    // Modifier Keys
883	    ShiftLeft: { key: 'Shift' },
884	    ShiftRight: { key: 'Shift' },
885	    ControlLeft: { key: 'Control' },
886	    ControlRight: { key: 'Control' },
887	    AltLeft: { key: 'Alt' },
888	    AltRight: { key: 'Alt' },
889	    OSLeft: { key: 'OS' },
890	    OSRight: { key: 'OS' },
891
892	    // Whitespace Keys
893	    NumpadEnter: { key: 'Enter' },
894	    Space: { key: ' ' },
895
896	    // Printable Keys
897	    Digit0: { key: '0', shiftKey: ')' },
898	    Digit1: { key: '1', shiftKey: '!' },
899	    Digit2: { key: '2', shiftKey: '@' },
900	    Digit3: { key: '3', shiftKey: '#' },
901	    Digit4: { key: '4', shiftKey: '$' },
902	    Digit5: { key: '5', shiftKey: '%' },
903	    Digit6: { key: '6', shiftKey: '^' },
904	    Digit7: { key: '7', shiftKey: '&' },
905	    Digit8: { key: '8', shiftKey: '*' },
906	    Digit9: { key: '9', shiftKey: '(' },
907	    KeyA: { key: 'a', shiftKey: 'A' },
908	    KeyB: { key: 'b', shiftKey: 'B' },
909	    KeyC: { key: 'c', shiftKey: 'C' },
910	    KeyD: { key: 'd', shiftKey: 'D' },
911	    KeyE: { key: 'e', shiftKey: 'E' },
912	    KeyF: { key: 'f', shiftKey: 'F' },
913	    KeyG: { key: 'g', shiftKey: 'G' },
914	    KeyH: { key: 'h', shiftKey: 'H' },
915	    KeyI: { key: 'i', shiftKey: 'I' },
916	    KeyJ: { key: 'j', shiftKey: 'J' },
917	    KeyK: { key: 'k', shiftKey: 'K' },
918	    KeyL: { key: 'l', shiftKey: 'L' },
919	    KeyM: { key: 'm', shiftKey: 'M' },
920	    KeyN: { key: 'n', shiftKey: 'N' },
921	    KeyO: { key: 'o', shiftKey: 'O' },
922	    KeyP: { key: 'p', shiftKey: 'P' },
923	    KeyQ: { key: 'q', shiftKey: 'Q' },
924	    KeyR: { key: 'r', shiftKey: 'R' },
925	    KeyS: { key: 's', shiftKey: 'S' },
926	    KeyT: { key: 't', shiftKey: 'T' },
927	    KeyU: { key: 'u', shiftKey: 'U' },
928	    KeyV: { key: 'v', shiftKey: 'V' },
929	    KeyW: { key: 'w', shiftKey: 'W' },
930	    KeyX: { key: 'x', shiftKey: 'X' },
931	    KeyY: { key: 'y', shiftKey: 'Y' },
932	    KeyZ: { key: 'z', shiftKey: 'Z' },
933	    Numpad0: { key: '0' },
934	    Numpad1: { key: '1' },
935	    Numpad2: { key: '2' },
936	    Numpad3: { key: '3' },
937	    Numpad4: { key: '4' },
938	    Numpad5: { key: '5' },
939	    Numpad6: { key: '6' },
940	    Numpad7: { key: '7' },
941	    Numpad8: { key: '8' },
942	    Numpad9: { key: '9' },
943	    NumpadMultiply: { key: '*' },
944	    NumpadAdd: { key: '+' },
945	    NumpadComma: { key: ',' },
946	    NumpadSubtract: { key: '-' },
947	    NumpadDecimal: { key: '.' },
948	    NumpadDivide: { key: '/' },
949	    Semicolon: { key: ';', shiftKey: ':' },
950	    Equal: { key: '=', shiftKey: '+' },
951	    Comma: { key: ',', shiftKey: '<' },
952	    Minus: { key: '-', shiftKey: '_' },
953	    Period: { key: '.', shiftKey: '>' },
954	    Slash: { key: '/', shiftKey: '?' },
955	    Backquote: { key: '`', shiftKey: '~' },
956	    BracketLeft: { key: '[', shiftKey: '{' },
957	    Backslash: { key: '\\', shiftKey: '|' },
958	    BracketRight: { key: ']', shiftKey: '}' },
959	    Quote: { key: '\'', shiftKey: '"' },
960	    IntlBackslash: { key: '\\', shiftKey: '|' }
961	  };
962
963	  mergeIf(codeToKeyTable, 'mac', {
964	    OSLeft: { key: 'Meta' },
965	    OSRight: { key: 'Meta' }
966	  });
967
968	  // Corrections for 'key' names in older browsers (e.g. FF36-)
969	  // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.key#Key_values
970	  var keyFixTable = {
971	    Esc: 'Escape',
972	    Nonconvert: 'NonConvert',
973	    Left: 'ArrowLeft',
974	    Up: 'ArrowUp',
975	    Right: 'ArrowRight',
976	    Down: 'ArrowDown',
977	    Del: 'Delete',
978	    Menu: 'ContextMenu',
979	    MediaNextTrack: 'MediaTrackNext',
980	    MediaPreviousTrack: 'MediaTrackPrevious',
981	    SelectMedia: 'MediaSelect',
982	    HalfWidth: 'Hankaku',
983	    FullWidth: 'Zenkaku',
984	    RomanCharacters: 'Romaji',
985	    Crsel: 'CrSel',
986	    Exsel: 'ExSel',
987	    Zoom: 'ZoomToggle'
988	  };
989
990	  //--------------------------------------------------------------------
991	  //
992	  // Exported Functions
993	  //
994	  //--------------------------------------------------------------------
995
996
997	  var codeTable = remap(keyCodeToInfoTable, 'code');
998
999	  try {
1000	    var nativeLocation = nativeKeyboardEvent && ('location' in new KeyboardEvent(''));
1001	  } catch (_) {}
1002
1003	  function keyInfoForEvent(event) {
1004	    var keyCode = 'keyCode' in event ? event.keyCode : 'which' in event ? event.which : 0;
1005
1006	    var keyInfo = (function(){
1007	      if (nativeLocation || 'keyLocation' in event) {
1008	        var location = nativeLocation ? event.location : event.keyLocation;
1009	        if (location && keyCode in locationTable[location]) {
1010	          return locationTable[location][keyCode];
1011	        }
1012	      }
1013	      if ('keyIdentifier' in event && event.keyIdentifier in keyIdentifierTable) {
1014	        return keyIdentifierTable[event.keyIdentifier];
1015	      }
1016	      if (keyCode in keyCodeToInfoTable) {
1017	        return keyCodeToInfoTable[keyCode];
1018	      }
1019	      return null;
1020	    }());
1021
1022	    // TODO: Track these down and move to general tables
1023	    if (0) {
1024	      // TODO: Map these for newerish browsers?
1025	      // TODO: iOS only?
1026	      // TODO: Override with more common keyIdentifier name?
1027	      switch (event.keyIdentifier) {
1028	      case 'U+0010': keyInfo = { code: 'Function' }; break;
1029	      case 'U+001C': keyInfo = { code: 'ArrowLeft' }; break;
1030	      case 'U+001D': keyInfo = { code: 'ArrowRight' }; break;
1031	      case 'U+001E': keyInfo = { code: 'ArrowUp' }; break;
1032	      case 'U+001F': keyInfo = { code: 'ArrowDown' }; break;
1033	      }
1034	    }
1035
1036	    if (!keyInfo)
1037	      return null;
1038
1039	    var key = (function() {
1040	      var entry = codeToKeyTable[keyInfo.code];
1041	      if (!entry) return keyInfo.code;
1042	      return (event.shiftKey && 'shiftKey' in entry) ? entry.shiftKey : entry.key;
1043	    }());
1044
1045	    return {
1046	      code: keyInfo.code,
1047	      key: key,
1048	      location: keyInfo.location,
1049	      keyCap: keyInfo.keyCap
1050	    };
1051	  }
1052
1053	  function queryKeyCap(code, locale) {
1054	    code = String(code);
1055	    if (!codeTable.hasOwnProperty(code)) return 'Undefined';
1056	    if (locale && String(locale).toLowerCase() !== 'en-us') throw Error('Unsupported locale');
1057	    var keyInfo = codeTable[code];
1058	    return keyInfo.keyCap || keyInfo.code || 'Undefined';
1059	  }
1060
1061	  if ('KeyboardEvent' in global && 'defineProperty' in Object) {
1062	    (function() {
1063	      function define(o, p, v) {
1064	        if (p in o) return;
1065	        Object.defineProperty(o, p, v);
1066	      }
1067
1068	      define(KeyboardEvent.prototype, 'code', { get: function() {
1069	        var keyInfo = keyInfoForEvent(this);
1070	        return keyInfo ? keyInfo.code : '';
1071	      }});
1072
1073	      // Fix for nonstandard `key` values (FF36-)
1074	      if ('key' in KeyboardEvent.prototype) {
1075	        var desc = Object.getOwnPropertyDescriptor(KeyboardEvent.prototype, 'key');
1076	        Object.defineProperty(KeyboardEvent.prototype, 'key', { get: function() {
1077	          var key = desc.get.call(this);
1078	          return keyFixTable.hasOwnProperty(key) ? keyFixTable[key] : key;
1079	        }});
1080	      }
1081
1082	      define(KeyboardEvent.prototype, 'key', { get: function() {
1083	        var keyInfo = keyInfoForEvent(this);
1084	        return (keyInfo && 'key' in keyInfo) ? keyInfo.key : 'Unidentified';
1085	      }});
1086
1087	      define(KeyboardEvent.prototype, 'location', { get: function() {
1088	        var keyInfo = keyInfoForEvent(this);
1089	        return (keyInfo && 'location' in keyInfo) ? keyInfo.location : STANDARD;
1090	      }});
1091
1092	      define(KeyboardEvent.prototype, 'locale', { get: function() {
1093	        return '';
1094	      }});
1095	    }());
1096	  }
1097
1098	  if (!('queryKeyCap' in global.KeyboardEvent))
1099	    global.KeyboardEvent.queryKeyCap = queryKeyCap;
1100
1101	  // Helper for IE8-
1102	  global.identifyKey = function(event) {
1103	    if ('code' in event)
1104	      return;
1105
1106	    var keyInfo = keyInfoForEvent(event);
1107	    event.code = keyInfo ? keyInfo.code : '';
1108	    event.key = (keyInfo && 'key' in keyInfo) ? keyInfo.key : 'Unidentified';
1109	    event.location = ('location' in event) ? event.location :
1110	      ('keyLocation' in event) ? event.keyLocation :
1111	      (keyInfo && 'location' in keyInfo) ? keyInfo.location : STANDARD;
1112	    event.locale = '';
1113	  };
1114
1115	} (window));
1116
1117
1118/***/ }
1119/******/ ]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.