Skip to content

Instantly share code, notes, and snippets.

@maninak
Last active February 5, 2021 12:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maninak/a0f2ebd1facd9da4feb1293963b790f7 to your computer and use it in GitHub Desktop.
Save maninak/a0f2ebd1facd9da4feb1293963b790f7 to your computer and use it in GitHub Desktop.
Change presentation slides with a Nintendo Switch Joycon controller with the power of the web's native Gamepad API. The joycon must already be connected with your computer (pc/mac/linux) via bluetooth (hold connect button on controller until "searching" mode). Only left and right buttons implemented. Any button could easily be mapped differenly..
// connect the left joycon to any computer via bluetooth and paste the following script in the console of a webpage
(() => {
const VENDOR_ID = '057e';
const DEVICE_ID = '2006';
const [LEFT_BUTTON, RIGHT_BUTTON] = [0, 3];
const [LEFT_ARROW_KEY_CODE, RIGHT_ARROW_KEY_CODE] = [37, 39];
let gamepadIndex, intervalID, isPressing = false;
function pressKey(keyCode) {
if (isPressing) {
return;
}
const activeElement = document.activeElement;
const targetDocument = activeElement.tagName === 'IFRAME' ? activeElement.contentDocument : document;
['keydown', 'keyup'].forEach(typeArg => {
targetDocument.body.dispatchEvent(new KeyboardEvent(typeArg, { keyCode, bubbles: true }));
});
isPressing = true;
};
addEventListener('gamepadconnected', e => {
const gamepadId = e.gamepad.id;
if (gamepadIndex != null || !gamepadId.includes(VENDOR_ID) || !gamepadId.includes(DEVICE_ID)) {
return;
}
gamepadIndex = e.gamepad.index;
intervalID = setInterval(() => {
const buttons = navigator.getGamepads()[gamepadIndex].buttons;
if (buttons[LEFT_BUTTON].pressed) {
pressKey(LEFT_ARROW_KEY_CODE);
return;
} else if (buttons[RIGHT_BUTTON].pressed) {
pressKey(RIGHT_ARROW_KEY_CODE);
return;
}
isPressing = false;
}, 1000 / 60);
});
addEventListener('gamepaddisconnected', e => {
if (gamepadIndex === e.gamepad.index) {
clearInterval(intervalID);
gamepadIndex = intervalID = null;
}
});
if (navigator.wakeLock) {
const requestWakeLock = (isFirstRequest) => {
if (document.visibilityState !== 'visible') {
return;
}
navigator.wakeLock.request('screen').then(() => {
if (isFirstRequest) {
document.addEventListener('visibilitychange', requestWakeLock);
document.addEventListener('fullscreenchange', requestWakeLock);
}
}).catch(() => {});
};
requestWakeLock(true);
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment