jellyfish-web/src/scripts/keyboardNavigation.js

172 lines
4.7 KiB
JavaScript
Raw Normal View History

2020-03-29 00:06:27 +03:00
/**
* Module for performing keyboard navigation.
* @module components/input/keyboardnavigation
*/
2020-05-04 12:44:12 +02:00
import inputManager from 'inputManager';
import layoutManager from 'layoutManager';
2020-03-19 21:20:47 -04:00
/**
* Key name mapping.
*/
const KeyNames = {
2020-05-04 12:44:12 +02:00
13: 'Enter',
19: 'Pause',
27: 'Escape',
32: 'Space',
37: 'ArrowLeft',
38: 'ArrowUp',
39: 'ArrowRight',
40: 'ArrowDown',
2020-03-19 21:20:47 -04:00
// MediaRewind (Tizen/WebOS)
2020-05-04 12:44:12 +02:00
412: 'MediaRewind',
2020-03-19 21:20:47 -04:00
// MediaStop (Tizen/WebOS)
2020-05-04 12:44:12 +02:00
413: 'MediaStop',
2020-03-19 21:20:47 -04:00
// MediaPlay (Tizen/WebOS)
2020-05-04 12:44:12 +02:00
415: 'MediaPlay',
2020-03-19 21:20:47 -04:00
// MediaFastForward (Tizen/WebOS)
2020-05-04 12:44:12 +02:00
417: 'MediaFastForward',
2020-03-19 21:20:47 -04:00
// Back (WebOS)
2020-05-04 12:44:12 +02:00
461: 'Back',
2020-03-19 21:20:47 -04:00
// Back (Tizen)
2020-05-04 12:44:12 +02:00
10009: 'Back',
2020-03-19 21:20:47 -04:00
// MediaTrackPrevious (Tizen)
2020-05-04 12:44:12 +02:00
10232: 'MediaTrackPrevious',
2020-03-19 21:20:47 -04:00
// MediaTrackNext (Tizen)
2020-05-04 12:44:12 +02:00
10233: 'MediaTrackNext',
2020-03-19 21:20:47 -04:00
// MediaPlayPause (Tizen)
2020-05-04 12:44:12 +02:00
10252: 'MediaPlayPause'
2020-03-19 21:20:47 -04:00
};
/**
* Keys used for keyboard navigation.
*/
2020-05-04 12:44:12 +02:00
const NavigationKeys = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
2020-03-19 21:20:47 -04:00
let hasFieldKey = false;
try {
2020-05-04 12:44:12 +02:00
hasFieldKey = 'key' in new KeyboardEvent('keydown');
2020-03-19 21:20:47 -04:00
} catch (e) {
console.error("error checking 'key' field");
}
if (!hasFieldKey) {
// Add [a..z]
for (let i = 65; i <= 90; i++) {
KeyNames[i] = String.fromCharCode(i).toLowerCase();
}
2020-03-19 21:20:47 -04:00
}
/**
* Returns key name from event.
*
2020-03-31 19:07:03 +03:00
* @param {KeyboardEvent} event - Keyboard event.
* @return {string} Key name.
2020-03-19 21:20:47 -04:00
*/
export function getKeyName(event) {
return KeyNames[event.keyCode] || event.key;
}
/**
* Returns _true_ if key is used for navigation.
*
2020-03-31 19:07:03 +03:00
* @param {string} key - Key name.
* @return {boolean} _true_ if key is used for navigation.
2020-03-19 21:20:47 -04:00
*/
export function isNavigationKey(key) {
return NavigationKeys.indexOf(key) != -1;
}
export function enable() {
2020-06-28 23:46:27 +03:00
window.addEventListener('keydown', function (e) {
2020-03-19 21:20:47 -04:00
const key = getKeyName(e);
// Ignore navigation keys for non-TV
if (!layoutManager.tv && isNavigationKey(key)) {
return;
}
2020-03-19 21:20:47 -04:00
let capture = true;
switch (key) {
2020-05-04 12:44:12 +02:00
case 'ArrowLeft':
inputManager.handleCommand('left');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'ArrowUp':
inputManager.handleCommand('up');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'ArrowRight':
inputManager.handleCommand('right');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'ArrowDown':
inputManager.handleCommand('down');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'Back':
inputManager.handleCommand('back');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'Escape':
2020-03-19 21:20:47 -04:00
if (layoutManager.tv) {
inputManager.handleCommand('back');
2020-03-19 21:20:47 -04:00
} else {
capture = false;
2020-03-19 21:20:47 -04:00
}
break;
2020-05-04 12:44:12 +02:00
case 'MediaPlay':
inputManager.handleCommand('play');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'Pause':
inputManager.handleCommand('pause');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'MediaPlayPause':
inputManager.handleCommand('playpause');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'MediaRewind':
inputManager.handleCommand('rewind');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'MediaFastForward':
inputManager.handleCommand('fastforward');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'MediaStop':
inputManager.handleCommand('stop');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'MediaTrackPrevious':
inputManager.handleCommand('previoustrack');
2020-03-19 21:20:47 -04:00
break;
2020-05-04 12:44:12 +02:00
case 'MediaTrackNext':
inputManager.handleCommand('nexttrack');
2020-03-19 21:20:47 -04:00
break;
default:
capture = false;
}
2020-03-19 21:20:47 -04:00
if (capture) {
2020-05-04 12:44:12 +02:00
console.debug('disabling default event handling');
2020-03-19 21:20:47 -04:00
e.preventDefault();
}
});
}
// Gamepad initialisation. No script is required if no gamepads are present at init time, saving a bit of resources.
// Whenever the gamepad is connected, we hand all the control of the gamepad to gamepadtokey.js by removing the event handler
function attachGamepadScript(e) {
2020-05-04 12:44:12 +02:00
console.log('Gamepad connected! Attaching gamepadtokey.js script');
window.removeEventListener('gamepadconnected', attachGamepadScript);
2020-08-01 04:07:00 +02:00
/* eslint-disable-next-line @babel/no-unused-expressions */
2020-07-21 13:25:50 +01:00
import('scripts/gamepadtokey');
2020-03-19 21:20:47 -04:00
}
// No need to check for gamepads manually at load time, the eventhandler will be fired for that
if (navigator.getGamepads) { /* eslint-disable-line compat/compat */
2020-05-04 12:44:12 +02:00
window.addEventListener('gamepadconnected', attachGamepadScript);
}
2020-03-29 00:06:27 +03:00
export default {
enable: enable,
getKeyName: getKeyName,
isNavigationKey: isNavigationKey
};