Merge pull request #1776 from MrTimscampi/focus-prevent-scroll

Remove focus-prevent-scroll, migrate gamepadtokey and chromecastHelper to ES6
This commit is contained in:
Bond-009 2020-08-22 21:04:14 +02:00 committed by GitHub
commit fb55fe9e7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 524 additions and 527 deletions

View file

@ -320,6 +320,7 @@
"src/plugins/backdropScreensaver/plugin.js", "src/plugins/backdropScreensaver/plugin.js",
"src/plugins/bookPlayer/plugin.js", "src/plugins/bookPlayer/plugin.js",
"src/plugins/bookPlayer/tableOfContents.js", "src/plugins/bookPlayer/tableOfContents.js",
"src/plugins/chromecastPlayer/chromecastHelper.js",
"src/plugins/photoPlayer/plugin.js", "src/plugins/photoPlayer/plugin.js",
"src/plugins/youtubePlayer/plugin.js", "src/plugins/youtubePlayer/plugin.js",
"src/scripts/alphanumericshortcuts.js", "src/scripts/alphanumericshortcuts.js",

View file

@ -1,4 +1,3 @@
// TODO: Move to external library (https://github.com/calvellido/focus-options-polyfill)
// Polyfill to add support for preventScroll by focus function // Polyfill to add support for preventScroll by focus function
if (HTMLElement.prototype.nativeFocus === undefined) { if (HTMLElement.prototype.nativeFocus === undefined) {

View file

@ -1,16 +1,15 @@
define(['events'], function (events) { import events from 'events';
'use strict';
// LinkParser // LinkParser
// //
// https://github.com/ravisorg/LinkParser // https://github.com/ravisorg/LinkParser
// //
// Locate and extract almost any URL within a string. Handles protocol-less domains, IPv4 and // Locate and extract almost any URL within a string. Handles protocol-less domains, IPv4 and
// IPv6, unrecognised TLDs, and more. // IPv6, unrecognised TLDs, and more.
// //
// This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. // This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
// http://creativecommons.org/licenses/by-sa/4.0/ // http://creativecommons.org/licenses/by-sa/4.0/
(function () { (function () {
// Original URL regex from the Android android.text.util.Linkify function, found here: // Original URL regex from the Android android.text.util.Linkify function, found here:
// http://stackoverflow.com/a/19696443 // http://stackoverflow.com/a/19696443
// //
@ -36,15 +35,15 @@ define(['events'], function (events) {
// 5) It wasn't as smart as it could have been about what should be part of a // 5) It wasn't as smart as it could have been about what should be part of a
// URL and what should be part of human language. // URL and what should be part of human language.
var protocols = '(?:(?:http|https|rtsp|ftp):\\/\\/)'; const protocols = '(?:(?:http|https|rtsp|ftp):\\/\\/)';
var credentials = "(?:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,64}" // username (1-64 normal or url escaped characters) const credentials = "(?:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,64}" // username (1-64 normal or url escaped characters)
+ "(?:\\:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,25})?" // followed by optional password (: + 1-25 normal or url escaped characters) + "(?:\\:(?:[a-z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-f0-9]{2})){1,25})?" // followed by optional password (: + 1-25 normal or url escaped characters)
+ '\\@)'; + '\\@)';
// IPv6 Regex http://forums.intermapper.com/viewtopic.php?t=452 // IPv6 Regex http://forums.intermapper.com/viewtopic.php?t=452
// by Dartware, LLC is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License // by Dartware, LLC is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License
// http://intermapper.com/ // http://intermapper.com/
var ipv6 = '(' const ipv6 = '('
+ '(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))' + '(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))'
+ '|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))' + '|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))'
+ '|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))' + '|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))'
@ -55,13 +54,13 @@ define(['events'], function (events) {
+ '|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))' + '|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))'
+ ')(%.+)?'; + ')(%.+)?';
var ipv4 = '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.' const ipv4 = '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.'
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.' + '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.'
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.' + '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.'
+ '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])'; + '(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])';
// This would have been a lot cleaner if JS RegExp supported conditionals... // This would have been a lot cleaner if JS RegExp supported conditionals...
var linkRegExpString = const linkRegExpString =
// begin match for protocol / username / password / host // begin match for protocol / username / password / host
'(?:' '(?:'
@ -112,9 +111,9 @@ define(['events'], function (events) {
+ ')'; + ')';
// regex = XRegExp(regex,'gi'); // regex = XRegExp(regex,'gi');
var linkRegExp = RegExp(linkRegExpString, 'gi'); const linkRegExp = RegExp(linkRegExpString, 'gi');
var protocolRegExp = RegExp('^' + protocols, 'i'); const protocolRegExp = RegExp('^' + protocols, 'i');
// if url doesn't begin with a known protocol, add http by default // if url doesn't begin with a known protocol, add http by default
function ensureProtocol(url) { function ensureProtocol(url) {
@ -125,18 +124,18 @@ define(['events'], function (events) {
} }
// look for links in the text // look for links in the text
var LinkParser = { const LinkParser = {
parse: function (text) { parse: function (text) {
var links = []; const links = [];
var match; let match;
// eslint-disable-next-line no-cond-assign // eslint-disable-next-line no-cond-assign
while (match = linkRegExp.exec(text)) { while (match = linkRegExp.exec(text)) {
console.debug(match); console.debug(match);
var txt = match[0]; const txt = match[0];
var pos = match.index; const pos = match.index;
var len = txt.length; const len = txt.length;
var url = ensureProtocol(text); const url = ensureProtocol(text);
links.push({ 'pos': pos, 'text': txt, 'len': len, 'url': url }); links.push({ 'pos': pos, 'text': txt, 'len': len, 'url': url });
} }
@ -146,37 +145,39 @@ define(['events'], function (events) {
}; };
window.LinkParser = LinkParser; window.LinkParser = LinkParser;
})(); })();
var cache = {}; let cache = {};
function isValidIpAddress(address) { // TODO: Replace with isIP (https://www.npmjs.com/package/is-ip)
var links = LinkParser.parse(address); function isValidIpAddress(address) {
const links = LinkParser.parse(address);
return links.length == 1; return links.length == 1;
} }
function isLocalIpAddress(address) { // TODO: Add IPv6 support. Potentially replace with isLocalhost (https://www.npmjs.com/package/is-localhost-ip)
function isLocalIpAddress(address) {
address = address.toLowerCase(); address = address.toLowerCase();
if (address.indexOf('127.0.0.1') !== -1) { if (address.includes('127.0.0.1')) {
return true; return true;
} }
if (address.indexOf('localhost') !== -1) { if (address.includes('localhost')) {
return true; return true;
} }
return false; return false;
} }
function getServerAddress(apiClient) { export function getServerAddress(apiClient) {
var serverAddress = apiClient.serverAddress(); const serverAddress = apiClient.serverAddress();
if (isValidIpAddress(serverAddress) && !isLocalIpAddress(serverAddress)) { if (isValidIpAddress(serverAddress) && !isLocalIpAddress(serverAddress)) {
return Promise.resolve(serverAddress); return Promise.resolve(serverAddress);
} }
var cachedValue = getCachedValue(serverAddress); const cachedValue = getCachedValue(serverAddress);
if (cachedValue) { if (cachedValue) {
return Promise.resolve(cachedValue); return Promise.resolve(cachedValue);
} }
@ -184,7 +185,7 @@ define(['events'], function (events) {
return apiClient.getEndpointInfo().then(function (endpoint) { return apiClient.getEndpointInfo().then(function (endpoint) {
if (endpoint.IsInNetwork) { if (endpoint.IsInNetwork) {
return apiClient.getPublicSystemInfo().then(function (info) { return apiClient.getPublicSystemInfo().then(function (info) {
var localAddress = info.LocalAddress; let localAddress = info.LocalAddress;
if (!localAddress) { if (!localAddress) {
console.debug('No valid local address returned, defaulting to external one'); console.debug('No valid local address returned, defaulting to external one');
localAddress = serverAddress; localAddress = serverAddress;
@ -197,33 +198,32 @@ define(['events'], function (events) {
return serverAddress; return serverAddress;
} }
}); });
} }
function clearCache() { function clearCache() {
cache = {}; cache = {};
} }
function addToCache(key, value) { function addToCache(key, value) {
cache[key] = { cache[key] = {
value: value, value: value,
time: new Date().getTime() time: new Date().getTime()
}; };
} }
function getCachedValue(key) { function getCachedValue(key) {
var obj = cache[key]; const obj = cache[key];
if (obj && (new Date().getTime() - obj.time) < 180000) { if (obj && (new Date().getTime() - obj.time) < 180000) {
return obj.value; return obj.value;
} }
return null; return null;
} }
events.on(ConnectionManager, 'localusersignedin', clearCache); events.on(ConnectionManager, 'localusersignedin', clearCache);
events.on(ConnectionManager, 'localusersignedout', clearCache); events.on(ConnectionManager, 'localusersignedout', clearCache);
return { export default {
getServerAddress: getServerAddress getServerAddress: getServerAddress
}; };
});

View file

@ -19,154 +19,152 @@
// # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// # THE SOFTWARE. // # THE SOFTWARE.
require(['apphost'], function (appHost) {
'use strict';
appHost = appHost.default || appHost; import appHost from 'apphost';
var _GAMEPAD_A_BUTTON_INDEX = 0; var _GAMEPAD_A_BUTTON_INDEX = 0;
var _GAMEPAD_B_BUTTON_INDEX = 1; var _GAMEPAD_B_BUTTON_INDEX = 1;
var _GAMEPAD_DPAD_UP_BUTTON_INDEX = 12; var _GAMEPAD_DPAD_UP_BUTTON_INDEX = 12;
var _GAMEPAD_DPAD_DOWN_BUTTON_INDEX = 13; var _GAMEPAD_DPAD_DOWN_BUTTON_INDEX = 13;
var _GAMEPAD_DPAD_LEFT_BUTTON_INDEX = 14; var _GAMEPAD_DPAD_LEFT_BUTTON_INDEX = 14;
var _GAMEPAD_DPAD_RIGHT_BUTTON_INDEX = 15; var _GAMEPAD_DPAD_RIGHT_BUTTON_INDEX = 15;
var _GAMEPAD_A_KEY = 'GamepadA'; var _GAMEPAD_A_KEY = 'GamepadA';
var _GAMEPAD_B_KEY = 'GamepadB'; var _GAMEPAD_B_KEY = 'GamepadB';
var _GAMEPAD_DPAD_UP_KEY = 'GamepadDPadUp'; var _GAMEPAD_DPAD_UP_KEY = 'GamepadDPadUp';
var _GAMEPAD_DPAD_DOWN_KEY = 'GamepadDPadDown'; var _GAMEPAD_DPAD_DOWN_KEY = 'GamepadDPadDown';
var _GAMEPAD_DPAD_LEFT_KEY = 'GamepadDPadLeft'; var _GAMEPAD_DPAD_LEFT_KEY = 'GamepadDPadLeft';
var _GAMEPAD_DPAD_RIGHT_KEY = 'GamepadDPadRight'; var _GAMEPAD_DPAD_RIGHT_KEY = 'GamepadDPadRight';
var _GAMEPAD_LEFT_THUMBSTICK_UP_KEY = 'GamepadLeftThumbStickUp'; var _GAMEPAD_LEFT_THUMBSTICK_UP_KEY = 'GamepadLeftThumbStickUp';
var _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEY = 'GamepadLeftThumbStickDown'; var _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEY = 'GamepadLeftThumbStickDown';
var _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEY = 'GamepadLeftThumbStickLeft'; var _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEY = 'GamepadLeftThumbStickLeft';
var _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEY = 'GamepadLeftThumbStickRight'; var _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEY = 'GamepadLeftThumbStickRight';
var _GAMEPAD_A_KEYCODE = 0; var _GAMEPAD_A_KEYCODE = 0;
var _GAMEPAD_B_KEYCODE = 27; var _GAMEPAD_B_KEYCODE = 27;
var _GAMEPAD_DPAD_UP_KEYCODE = 38; var _GAMEPAD_DPAD_UP_KEYCODE = 38;
var _GAMEPAD_DPAD_DOWN_KEYCODE = 40; var _GAMEPAD_DPAD_DOWN_KEYCODE = 40;
var _GAMEPAD_DPAD_LEFT_KEYCODE = 37; var _GAMEPAD_DPAD_LEFT_KEYCODE = 37;
var _GAMEPAD_DPAD_RIGHT_KEYCODE = 39; var _GAMEPAD_DPAD_RIGHT_KEYCODE = 39;
var _GAMEPAD_LEFT_THUMBSTICK_UP_KEYCODE = 38; var _GAMEPAD_LEFT_THUMBSTICK_UP_KEYCODE = 38;
var _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEYCODE = 40; var _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEYCODE = 40;
var _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEYCODE = 37; var _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEYCODE = 37;
var _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEYCODE = 39; var _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEYCODE = 39;
var _THUMB_STICK_THRESHOLD = 0.75; var _THUMB_STICK_THRESHOLD = 0.75;
var _leftThumbstickUpPressed = false; var _leftThumbstickUpPressed = false;
var _leftThumbstickDownPressed = false; var _leftThumbstickDownPressed = false;
var _leftThumbstickLeftPressed = false; var _leftThumbstickLeftPressed = false;
var _leftThumbstickRightPressed = false; var _leftThumbstickRightPressed = false;
var _dPadUpPressed = false; var _dPadUpPressed = false;
var _dPadDownPressed = false; var _dPadDownPressed = false;
var _dPadLeftPressed = false; var _dPadLeftPressed = false;
var _dPadRightPressed = false; var _dPadRightPressed = false;
var _gamepadAPressed = false; var _gamepadAPressed = false;
var _gamepadBPressed = false; var _gamepadBPressed = false;
// The set of buttons on the gamepad we listen for. // The set of buttons on the gamepad we listen for.
var ProcessedButtons = [ var ProcessedButtons = [
_GAMEPAD_DPAD_UP_BUTTON_INDEX, _GAMEPAD_DPAD_UP_BUTTON_INDEX,
_GAMEPAD_DPAD_DOWN_BUTTON_INDEX, _GAMEPAD_DPAD_DOWN_BUTTON_INDEX,
_GAMEPAD_DPAD_LEFT_BUTTON_INDEX, _GAMEPAD_DPAD_LEFT_BUTTON_INDEX,
_GAMEPAD_DPAD_RIGHT_BUTTON_INDEX, _GAMEPAD_DPAD_RIGHT_BUTTON_INDEX,
_GAMEPAD_A_BUTTON_INDEX, _GAMEPAD_A_BUTTON_INDEX,
_GAMEPAD_B_BUTTON_INDEX _GAMEPAD_B_BUTTON_INDEX
]; ];
var _ButtonPressedState = {}; var _ButtonPressedState = {};
_ButtonPressedState.getgamepadA = function () { _ButtonPressedState.getgamepadA = function () {
return _gamepadAPressed; return _gamepadAPressed;
}; };
_ButtonPressedState.setgamepadA = function (newPressedState) { _ButtonPressedState.setgamepadA = function (newPressedState) {
raiseKeyEvent(_gamepadAPressed, newPressedState, _GAMEPAD_A_KEY, _GAMEPAD_A_KEYCODE, false, true); raiseKeyEvent(_gamepadAPressed, newPressedState, _GAMEPAD_A_KEY, _GAMEPAD_A_KEYCODE, false, true);
_gamepadAPressed = newPressedState; _gamepadAPressed = newPressedState;
}; };
_ButtonPressedState.getgamepadB = function () { _ButtonPressedState.getgamepadB = function () {
return _gamepadBPressed; return _gamepadBPressed;
}; };
_ButtonPressedState.setgamepadB = function (newPressedState) { _ButtonPressedState.setgamepadB = function (newPressedState) {
raiseKeyEvent(_gamepadBPressed, newPressedState, _GAMEPAD_B_KEY, _GAMEPAD_B_KEYCODE); raiseKeyEvent(_gamepadBPressed, newPressedState, _GAMEPAD_B_KEY, _GAMEPAD_B_KEYCODE);
_gamepadBPressed = newPressedState; _gamepadBPressed = newPressedState;
}; };
_ButtonPressedState.getleftThumbstickUp = function () { _ButtonPressedState.getleftThumbstickUp = function () {
return _leftThumbstickUpPressed; return _leftThumbstickUpPressed;
}; };
_ButtonPressedState.setleftThumbstickUp = function (newPressedState) { _ButtonPressedState.setleftThumbstickUp = function (newPressedState) {
raiseKeyEvent(_leftThumbstickUpPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_UP_KEY, _GAMEPAD_LEFT_THUMBSTICK_UP_KEYCODE, true); raiseKeyEvent(_leftThumbstickUpPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_UP_KEY, _GAMEPAD_LEFT_THUMBSTICK_UP_KEYCODE, true);
_leftThumbstickUpPressed = newPressedState; _leftThumbstickUpPressed = newPressedState;
}; };
_ButtonPressedState.getleftThumbstickDown = function () { _ButtonPressedState.getleftThumbstickDown = function () {
return _leftThumbstickDownPressed; return _leftThumbstickDownPressed;
}; };
_ButtonPressedState.setleftThumbstickDown = function (newPressedState) { _ButtonPressedState.setleftThumbstickDown = function (newPressedState) {
raiseKeyEvent(_leftThumbstickDownPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEY, _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEYCODE, true); raiseKeyEvent(_leftThumbstickDownPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEY, _GAMEPAD_LEFT_THUMBSTICK_DOWN_KEYCODE, true);
_leftThumbstickDownPressed = newPressedState; _leftThumbstickDownPressed = newPressedState;
}; };
_ButtonPressedState.getleftThumbstickLeft = function () { _ButtonPressedState.getleftThumbstickLeft = function () {
return _leftThumbstickLeftPressed; return _leftThumbstickLeftPressed;
}; };
_ButtonPressedState.setleftThumbstickLeft = function (newPressedState) { _ButtonPressedState.setleftThumbstickLeft = function (newPressedState) {
raiseKeyEvent(_leftThumbstickLeftPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEY, _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEYCODE, true); raiseKeyEvent(_leftThumbstickLeftPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEY, _GAMEPAD_LEFT_THUMBSTICK_LEFT_KEYCODE, true);
_leftThumbstickLeftPressed = newPressedState; _leftThumbstickLeftPressed = newPressedState;
}; };
_ButtonPressedState.getleftThumbstickRight = function () { _ButtonPressedState.getleftThumbstickRight = function () {
return _leftThumbstickRightPressed; return _leftThumbstickRightPressed;
}; };
_ButtonPressedState.setleftThumbstickRight = function (newPressedState) { _ButtonPressedState.setleftThumbstickRight = function (newPressedState) {
raiseKeyEvent(_leftThumbstickRightPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEY, _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEYCODE, true); raiseKeyEvent(_leftThumbstickRightPressed, newPressedState, _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEY, _GAMEPAD_LEFT_THUMBSTICK_RIGHT_KEYCODE, true);
_leftThumbstickRightPressed = newPressedState; _leftThumbstickRightPressed = newPressedState;
}; };
_ButtonPressedState.getdPadUp = function () { _ButtonPressedState.getdPadUp = function () {
return _dPadUpPressed; return _dPadUpPressed;
}; };
_ButtonPressedState.setdPadUp = function (newPressedState) { _ButtonPressedState.setdPadUp = function (newPressedState) {
raiseKeyEvent(_dPadUpPressed, newPressedState, _GAMEPAD_DPAD_UP_KEY, _GAMEPAD_DPAD_UP_KEYCODE, true); raiseKeyEvent(_dPadUpPressed, newPressedState, _GAMEPAD_DPAD_UP_KEY, _GAMEPAD_DPAD_UP_KEYCODE, true);
_dPadUpPressed = newPressedState; _dPadUpPressed = newPressedState;
}; };
_ButtonPressedState.getdPadDown = function () { _ButtonPressedState.getdPadDown = function () {
return _dPadDownPressed; return _dPadDownPressed;
}; };
_ButtonPressedState.setdPadDown = function (newPressedState) { _ButtonPressedState.setdPadDown = function (newPressedState) {
raiseKeyEvent(_dPadDownPressed, newPressedState, _GAMEPAD_DPAD_DOWN_KEY, _GAMEPAD_DPAD_DOWN_KEYCODE, true); raiseKeyEvent(_dPadDownPressed, newPressedState, _GAMEPAD_DPAD_DOWN_KEY, _GAMEPAD_DPAD_DOWN_KEYCODE, true);
_dPadDownPressed = newPressedState; _dPadDownPressed = newPressedState;
}; };
_ButtonPressedState.getdPadLeft = function () { _ButtonPressedState.getdPadLeft = function () {
return _dPadLeftPressed; return _dPadLeftPressed;
}; };
_ButtonPressedState.setdPadLeft = function (newPressedState) { _ButtonPressedState.setdPadLeft = function (newPressedState) {
raiseKeyEvent(_dPadLeftPressed, newPressedState, _GAMEPAD_DPAD_LEFT_KEY, _GAMEPAD_DPAD_LEFT_KEYCODE, true); raiseKeyEvent(_dPadLeftPressed, newPressedState, _GAMEPAD_DPAD_LEFT_KEY, _GAMEPAD_DPAD_LEFT_KEYCODE, true);
_dPadLeftPressed = newPressedState; _dPadLeftPressed = newPressedState;
}; };
_ButtonPressedState.getdPadRight = function () { _ButtonPressedState.getdPadRight = function () {
return _dPadRightPressed; return _dPadRightPressed;
}; };
_ButtonPressedState.setdPadRight = function (newPressedState) { _ButtonPressedState.setdPadRight = function (newPressedState) {
raiseKeyEvent(_dPadRightPressed, newPressedState, _GAMEPAD_DPAD_RIGHT_KEY, _GAMEPAD_DPAD_RIGHT_KEYCODE, true); raiseKeyEvent(_dPadRightPressed, newPressedState, _GAMEPAD_DPAD_RIGHT_KEY, _GAMEPAD_DPAD_RIGHT_KEYCODE, true);
_dPadRightPressed = newPressedState; _dPadRightPressed = newPressedState;
}; };
var times = {}; var times = {};
function throttle(key) { function throttle(key) {
var time = times[key] || 0; var time = times[key] || 0;
var now = new Date().getTime(); var now = new Date().getTime();
@ -176,14 +174,14 @@ require(['apphost'], function (appHost) {
} }
return false; return false;
} }
function resetThrottle(key) { function resetThrottle(key) {
times[key] = new Date().getTime(); times[key] = new Date().getTime();
} }
var isElectron = navigator.userAgent.toLowerCase().indexOf('electron') !== -1; var isElectron = navigator.userAgent.toLowerCase().indexOf('electron') !== -1;
function allowInput() { function allowInput() {
// This would be nice but always seems to return true with electron // This would be nice but always seems to return true with electron
if (!isElectron && document.hidden) { /* eslint-disable-line compat/compat */ if (!isElectron && document.hidden) { /* eslint-disable-line compat/compat */
return false; return false;
@ -194,9 +192,9 @@ require(['apphost'], function (appHost) {
} }
return true; return true;
} }
function raiseEvent(name, key, keyCode) { function raiseEvent(name, key, keyCode) {
if (!allowInput()) { if (!allowInput()) {
return; return;
} }
@ -206,17 +204,17 @@ require(['apphost'], function (appHost) {
event.key = key; event.key = key;
event.keyCode = keyCode; event.keyCode = keyCode;
(document.activeElement || document.body).dispatchEvent(event); (document.activeElement || document.body).dispatchEvent(event);
} }
function clickElement(elem) { function clickElement(elem) {
if (!allowInput()) { if (!allowInput()) {
return; return;
} }
elem.click(); elem.click();
} }
function raiseKeyEvent(oldPressedState, newPressedState, key, keyCode, enableRepeatKeyDown, clickonKeyUp) { function raiseKeyEvent(oldPressedState, newPressedState, key, keyCode, enableRepeatKeyDown, clickonKeyUp) {
// No-op if oldPressedState === newPressedState // No-op if oldPressedState === newPressedState
if (newPressedState === true) { if (newPressedState === true) {
// button down // button down
@ -244,10 +242,10 @@ require(['apphost'], function (appHost) {
clickElement(document.activeElement || window); clickElement(document.activeElement || window);
} }
} }
} }
var inputLoopTimer; var inputLoopTimer;
function runInputLoop() { function runInputLoop() {
// Get the latest gamepad state. // Get the latest gamepad state.
var gamepads = navigator.getGamepads(); /* eslint-disable-line compat/compat */ var gamepads = navigator.getGamepads(); /* eslint-disable-line compat/compat */
for (var i = 0, len = gamepads.length; i < len; i++) { for (var i = 0, len = gamepads.length; i < len; i++) {
@ -343,20 +341,20 @@ require(['apphost'], function (appHost) {
} }
// Schedule the next one // Schedule the next one
inputLoopTimer = requestAnimationFrame(runInputLoop); inputLoopTimer = requestAnimationFrame(runInputLoop);
} }
function startInputLoop() { function startInputLoop() {
if (!inputLoopTimer) { if (!inputLoopTimer) {
runInputLoop(); runInputLoop();
} }
} }
function stopInputLoop() { function stopInputLoop() {
cancelAnimationFrame(inputLoopTimer); cancelAnimationFrame(inputLoopTimer);
inputLoopTimer = undefined; inputLoopTimer = undefined;
} }
function isGamepadConnected() { function isGamepadConnected() {
var gamepads = navigator.getGamepads(); /* eslint-disable-line compat/compat */ var gamepads = navigator.getGamepads(); /* eslint-disable-line compat/compat */
for (var i = 0, len = gamepads.length; i < len; i++) { for (var i = 0, len = gamepads.length; i < len; i++) {
var gamepad = gamepads[i]; var gamepad = gamepads[i];
@ -365,17 +363,17 @@ require(['apphost'], function (appHost) {
} }
} }
return false; return false;
} }
function onFocusOrGamepadAttach(e) { function onFocusOrGamepadAttach(e) {
/* eslint-disable-next-line compat/compat */ /* eslint-disable-next-line compat/compat */
if (isGamepadConnected() && document.hasFocus()) { if (isGamepadConnected() && document.hasFocus()) {
console.log('Gamepad connected! Starting input loop'); console.log('Gamepad connected! Starting input loop');
startInputLoop(); startInputLoop();
} }
} }
function onFocusOrGamepadDetach(e) { function onFocusOrGamepadDetach(e) {
/* eslint-disable-next-line compat/compat */ /* eslint-disable-next-line compat/compat */
if (!isGamepadConnected() || !document.hasFocus()) { if (!isGamepadConnected() || !document.hasFocus()) {
console.log('Gamepad disconnected! No other gamepads are connected, stopping input loop'); console.log('Gamepad disconnected! No other gamepads are connected, stopping input loop');
@ -383,22 +381,21 @@ require(['apphost'], function (appHost) {
} else { } else {
console.log('Gamepad disconnected! There are gamepads still connected.'); console.log('Gamepad disconnected! There are gamepads still connected.');
} }
} }
// Event listeners for any change in gamepads' state. // Event listeners for any change in gamepads' state.
window.addEventListener('gamepaddisconnected', onFocusOrGamepadDetach); window.addEventListener('gamepaddisconnected', onFocusOrGamepadDetach);
window.addEventListener('gamepadconnected', onFocusOrGamepadAttach); window.addEventListener('gamepadconnected', onFocusOrGamepadAttach);
window.addEventListener('blur', onFocusOrGamepadDetach); window.addEventListener('blur', onFocusOrGamepadDetach);
window.addEventListener('focus', onFocusOrGamepadAttach); window.addEventListener('focus', onFocusOrGamepadAttach);
onFocusOrGamepadAttach(); onFocusOrGamepadAttach();
// The gamepadInputEmulation is a string property that exists in JavaScript UWAs and in WebViews in UWAs. // The gamepadInputEmulation is a string property that exists in JavaScript UWAs and in WebViews in UWAs.
// It won't exist in Win8.1 style apps or browsers. // It won't exist in Win8.1 style apps or browsers.
if (window.navigator && typeof window.navigator.gamepadInputEmulation === 'string') { if (window.navigator && typeof window.navigator.gamepadInputEmulation === 'string') {
// We want the gamepad to provide gamepad VK keyboard events rather than moving a // We want the gamepad to provide gamepad VK keyboard events rather than moving a
// mouse like cursor. Set to "keyboard", the gamepad will provide such keyboard events // mouse like cursor. Set to "keyboard", the gamepad will provide such keyboard events
// and provide input to the DOM navigator.getGamepads API. // and provide input to the DOM navigator.getGamepads API.
window.navigator.gamepadInputEmulation = 'gamepad'; window.navigator.gamepadInputEmulation = 'gamepad';
} }
});