Youtube Spacebar resume/pause fix

Fixes Spacebar not resuming/pausing YouTube videos after alt-tabbing

  1. // ==UserScript==
  2. // @name Youtube Spacebar resume/pause fix
  3. // @namespace https://github.com/lucassilvas1/youtube-spacebar-fix
  4. // @description Fixes Spacebar not resuming/pausing YouTube videos after alt-tabbing
  5. // @version 1.1.1
  6. // @author lucassilvas1
  7. // @match https://www.youtube.com/*
  8. // @run-at document-start
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. const LISTENER_TRIGGER_DELAY = 10; // Try increasing this number if the script doesn't always work for you
  14.  
  15. const playerState = {
  16. UNSTARTED: -1,
  17. ENDED: 0,
  18. PLAYING: 1,
  19. PAUSED: 2,
  20. BUFFERING: 3,
  21. CUED: 5,
  22. };
  23. Object.freeze(playerState);
  24.  
  25. /**
  26. * @type {(() => void) | null}
  27. */
  28. let playVideo = null;
  29. /**
  30. * @type {(() => void) | null}
  31. */
  32. let pauseVideo = null;
  33. /**
  34. * @type {(() => -1 | 0 | 1 | 2 | 3 | 5) | null}
  35. */
  36. let getPlayerState = null;
  37.  
  38. addKeyListener();
  39. document.addEventListener("yt-player-updated", onUpdate);
  40.  
  41. function onUpdate({ detail }) {
  42. playVideo = detail.playVideo;
  43. pauseVideo = detail.pauseVideo;
  44. getPlayerState = detail.getPlayerState;
  45. }
  46.  
  47. /**
  48. * Ignore keyboard events if they came from an input so the user can still type comments/search
  49. * @param {Element} element
  50. * @returns
  51. */
  52. function isInput(element) {
  53. if (element.getAttribute("contenteditable") === "true") {
  54. return true;
  55. }
  56.  
  57. if (
  58. element.tagName.toLowerCase() === "input" ||
  59. element.tagName.toLowerCase() === "textarea" ||
  60. element.tagName.toLowerCase() === "select"
  61. ) {
  62. return true;
  63. }
  64.  
  65. return false;
  66. }
  67.  
  68. function addKeyListener() {
  69. window.addEventListener(
  70. "keyup",
  71. (e) => {
  72. // Ignore event if it came from a text input
  73. if (e.key !== " " || isInput(document.activeElement)) return;
  74.  
  75. const oldState = getPlayerState();
  76.  
  77. setTimeout(() => {
  78. const state = getPlayerState();
  79.  
  80. if (oldState !== state) return;
  81.  
  82. switch (state) {
  83. case playerState.PLAYING:
  84. pauseVideo();
  85. break;
  86. case playerState.PAUSED:
  87. case playerState.CUED:
  88. case playerState.ENDED:
  89. case playerState.UNSTARTED:
  90. playVideo();
  91. break;
  92. // Do nothing if video is buffering
  93. }
  94. }, LISTENER_TRIGGER_DELAY);
  95. },
  96. { capture: true }
  97. );
  98. }
  99. })();