mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-11-04 06:08:31 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			414 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			414 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/*
 | 
						|
 * Video.js Hotkeys
 | 
						|
 * https://github.com/ctd1500/videojs-hotkeys
 | 
						|
 *
 | 
						|
 * Copyright (c) 2015 Chris Dougherty
 | 
						|
 * Licensed under the Apache-2.0 license.
 | 
						|
 */
 | 
						|
 | 
						|
;(function(root, factory) {
 | 
						|
  if (typeof window !== 'undefined' && window.videojs) {
 | 
						|
    factory(window.videojs);
 | 
						|
  } else if (typeof define === 'function' && define.amd) {
 | 
						|
    define('videojs-hotkeys', ['video.js'], function (module) {
 | 
						|
      return factory(module.default || module);
 | 
						|
    });
 | 
						|
  } else if (typeof module !== 'undefined' && module.exports) {
 | 
						|
    module.exports = factory(require('video.js'));
 | 
						|
  }
 | 
						|
}(this, function (videojs) {
 | 
						|
  "use strict";
 | 
						|
  if (typeof window !== 'undefined') {
 | 
						|
    window['videojs_hotkeys'] = { version: "0.2.22" };
 | 
						|
  }
 | 
						|
 | 
						|
  var hotkeys = function(options) {
 | 
						|
    var player = this;
 | 
						|
    var pEl = player.el();
 | 
						|
    var doc = document;
 | 
						|
    var def_options = {
 | 
						|
      volumeStep: 0.1,
 | 
						|
      seekStep: 5,
 | 
						|
      enableMute: true,
 | 
						|
      enableVolumeScroll: true,
 | 
						|
      enableHoverScroll: true,
 | 
						|
      enableFullscreen: true,
 | 
						|
      enableNumbers: true,
 | 
						|
      enableJogStyle: false,
 | 
						|
      alwaysCaptureHotkeys: false,
 | 
						|
      enableModifiersForNumbers: true,
 | 
						|
      enableInactiveFocus: true,
 | 
						|
      skipInitialFocus: false,
 | 
						|
      playPauseKey: playPauseKey,
 | 
						|
      rewindKey: rewindKey,
 | 
						|
      forwardKey: forwardKey,
 | 
						|
      volumeUpKey: volumeUpKey,
 | 
						|
      volumeDownKey: volumeDownKey,
 | 
						|
      muteKey: muteKey,
 | 
						|
      fullscreenKey: fullscreenKey,
 | 
						|
      customKeys: {}
 | 
						|
    };
 | 
						|
 | 
						|
    var cPlay = 1,
 | 
						|
      cRewind = 2,
 | 
						|
      cForward = 3,
 | 
						|
      cVolumeUp = 4,
 | 
						|
      cVolumeDown = 5,
 | 
						|
      cMute = 6,
 | 
						|
      cFullscreen = 7;
 | 
						|
 | 
						|
    // Use built-in merge function from Video.js v5.0+ or v4.4.0+
 | 
						|
    var mergeOptions = videojs.mergeOptions || videojs.util.mergeOptions;
 | 
						|
    options = mergeOptions(def_options, options || {});
 | 
						|
 | 
						|
    var volumeStep = options.volumeStep,
 | 
						|
      seekStep = options.seekStep,
 | 
						|
      enableMute = options.enableMute,
 | 
						|
      enableVolumeScroll = options.enableVolumeScroll,
 | 
						|
      enableHoverScroll = options.enableHoverScroll,
 | 
						|
      enableFull = options.enableFullscreen,
 | 
						|
      enableNumbers = options.enableNumbers,
 | 
						|
      enableJogStyle = options.enableJogStyle,
 | 
						|
      alwaysCaptureHotkeys = options.alwaysCaptureHotkeys,
 | 
						|
      enableModifiersForNumbers = options.enableModifiersForNumbers,
 | 
						|
      enableInactiveFocus = options.enableInactiveFocus,
 | 
						|
      skipInitialFocus = options.skipInitialFocus;
 | 
						|
 | 
						|
    // Set default player tabindex to handle keydown and doubleclick events
 | 
						|
    if (!pEl.hasAttribute('tabIndex')) {
 | 
						|
      pEl.setAttribute('tabIndex', '-1');
 | 
						|
    }
 | 
						|
 | 
						|
    // Remove player outline to fix video performance issue
 | 
						|
    pEl.style.outline = "none";
 | 
						|
 | 
						|
    if (alwaysCaptureHotkeys || !player.autoplay()) {
 | 
						|
      if (!skipInitialFocus) {
 | 
						|
        player.one('play', function() {
 | 
						|
          pEl.focus(); // Fixes the .vjs-big-play-button handing focus back to body instead of the player
 | 
						|
        });
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (enableInactiveFocus) {
 | 
						|
      player.on('userinactive', function() {
 | 
						|
        // When the control bar fades, re-apply focus to the player if last focus was a control button
 | 
						|
        var cancelFocusingPlayer = function() {
 | 
						|
          clearTimeout(focusingPlayerTimeout);
 | 
						|
        };
 | 
						|
        var focusingPlayerTimeout = setTimeout(function() {
 | 
						|
          player.off('useractive', cancelFocusingPlayer);
 | 
						|
          var activeElement = doc.activeElement;
 | 
						|
          var controlBar = pEl.querySelector('.vjs-control-bar');
 | 
						|
          if (activeElement && activeElement.parentElement == controlBar) {
 | 
						|
            pEl.focus();
 | 
						|
          }
 | 
						|
        }, 10);
 | 
						|
 | 
						|
        player.one('useractive', cancelFocusingPlayer);
 | 
						|
      });
 | 
						|
    }
 | 
						|
 | 
						|
    player.on('play', function() {
 | 
						|
      // Fix allowing the YouTube plugin to have hotkey support.
 | 
						|
      var ifblocker = pEl.querySelector('.iframeblocker');
 | 
						|
      if (ifblocker && ifblocker.style.display === '') {
 | 
						|
        ifblocker.style.display = "block";
 | 
						|
        ifblocker.style.bottom = "39px";
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    var keyDown = function keyDown(event) {
 | 
						|
      var ewhich = event.which, wasPlaying, seekTime;
 | 
						|
      var ePreventDefault = event.preventDefault;
 | 
						|
      var duration = player.duration();
 | 
						|
      // When controls are disabled, hotkeys will be disabled as well
 | 
						|
      if (player.controls()) {
 | 
						|
 | 
						|
        // Don't catch keys if any control buttons are focused, unless alwaysCaptureHotkeys is true
 | 
						|
        var activeEl = doc.activeElement;
 | 
						|
        if (alwaysCaptureHotkeys ||
 | 
						|
            activeEl == pEl ||
 | 
						|
            activeEl == pEl.querySelector('.vjs-tech') ||
 | 
						|
            activeEl == pEl.querySelector('.vjs-control-bar') ||
 | 
						|
            activeEl == pEl.querySelector('.iframeblocker')) {
 | 
						|
 | 
						|
          switch (checkKeys(event, player)) {
 | 
						|
            // Spacebar toggles play/pause
 | 
						|
            case cPlay:
 | 
						|
              ePreventDefault();
 | 
						|
              if (alwaysCaptureHotkeys) {
 | 
						|
                // Prevent control activation with space
 | 
						|
                event.stopPropagation();
 | 
						|
              }
 | 
						|
 | 
						|
              if (player.paused()) {
 | 
						|
                player.play();
 | 
						|
              } else {
 | 
						|
                player.pause();
 | 
						|
              }
 | 
						|
              break;
 | 
						|
 | 
						|
            // Seeking with the left/right arrow keys
 | 
						|
            case cRewind: // Seek Backward
 | 
						|
              wasPlaying = !player.paused();
 | 
						|
              ePreventDefault();
 | 
						|
              if (wasPlaying) {
 | 
						|
                player.pause();
 | 
						|
              }
 | 
						|
              seekTime = player.currentTime() - seekStepD(event);
 | 
						|
              // The flash player tech will allow you to seek into negative
 | 
						|
              // numbers and break the seekbar, so try to prevent that.
 | 
						|
              if (seekTime <= 0) {
 | 
						|
                seekTime = 0;
 | 
						|
              }
 | 
						|
              player.currentTime(seekTime);
 | 
						|
              if (wasPlaying) {
 | 
						|
                player.play();
 | 
						|
              }
 | 
						|
              break;
 | 
						|
            case cForward: // Seek Forward
 | 
						|
              wasPlaying = !player.paused();
 | 
						|
              ePreventDefault();
 | 
						|
              if (wasPlaying) {
 | 
						|
                player.pause();
 | 
						|
              }
 | 
						|
              seekTime = player.currentTime() + seekStepD(event);
 | 
						|
              // Fixes the player not sending the end event if you
 | 
						|
              // try to seek past the duration on the seekbar.
 | 
						|
              if (seekTime >= duration) {
 | 
						|
                seekTime = wasPlaying ? duration - .001 : duration;
 | 
						|
              }
 | 
						|
              player.currentTime(seekTime);
 | 
						|
              if (wasPlaying) {
 | 
						|
                player.play();
 | 
						|
              }
 | 
						|
              break;
 | 
						|
 | 
						|
            // Volume control with the up/down arrow keys
 | 
						|
            case cVolumeDown:
 | 
						|
              ePreventDefault();
 | 
						|
              if (!enableJogStyle) {
 | 
						|
                player.volume(player.volume() - volumeStep);
 | 
						|
              } else {
 | 
						|
                seekTime = player.currentTime() - 1;
 | 
						|
                if (player.currentTime() <= 1) {
 | 
						|
                  seekTime = 0;
 | 
						|
                }
 | 
						|
                player.currentTime(seekTime);
 | 
						|
              }
 | 
						|
              break;
 | 
						|
            case cVolumeUp:
 | 
						|
              ePreventDefault();
 | 
						|
              if (!enableJogStyle) {
 | 
						|
                player.volume(player.volume() + volumeStep);
 | 
						|
              } else {
 | 
						|
                seekTime = player.currentTime() + 1;
 | 
						|
                if (seekTime >= duration) {
 | 
						|
                  seekTime = duration;
 | 
						|
                }
 | 
						|
                player.currentTime(seekTime);
 | 
						|
              }
 | 
						|
              break;
 | 
						|
 | 
						|
            // Toggle Mute with the M key
 | 
						|
            case cMute:
 | 
						|
              if (enableMute) {
 | 
						|
                player.muted(!player.muted());
 | 
						|
              }
 | 
						|
              break;
 | 
						|
 | 
						|
            // Toggle Fullscreen with the F key
 | 
						|
            case  cFullscreen:
 | 
						|
              if (enableFull) {
 | 
						|
                if (player.isFullscreen()) {
 | 
						|
                  player.exitFullscreen();
 | 
						|
                } else {
 | 
						|
                  player.requestFullscreen();
 | 
						|
                }
 | 
						|
              }
 | 
						|
              break;
 | 
						|
 | 
						|
            default:
 | 
						|
              // Number keys from 0-9 skip to a percentage of the video. 0 is 0% and 9 is 90%
 | 
						|
              if ((ewhich > 47 && ewhich < 59) || (ewhich > 95 && ewhich < 106)) {
 | 
						|
                // Do not handle if enableModifiersForNumbers set to false and keys are Ctrl, Cmd or Alt
 | 
						|
                if (enableModifiersForNumbers || !(event.metaKey || event.ctrlKey || event.altKey)) {
 | 
						|
                  if (enableNumbers) {
 | 
						|
                    var sub = 48;
 | 
						|
                    if (ewhich > 95) {
 | 
						|
                      sub = 96;
 | 
						|
                    }
 | 
						|
                    var number = ewhich - sub;
 | 
						|
                    ePreventDefault();
 | 
						|
                    player.currentTime(player.duration() * number * 0.1);
 | 
						|
                  }
 | 
						|
                }
 | 
						|
              }
 | 
						|
 | 
						|
              // Handle any custom hotkeys
 | 
						|
              for (var customKey in options.customKeys) {
 | 
						|
                var customHotkey = options.customKeys[customKey];
 | 
						|
                // Check for well formed custom keys
 | 
						|
                if (customHotkey && customHotkey.key && customHotkey.handler) {
 | 
						|
                  // Check if the custom key's condition matches
 | 
						|
                  if (customHotkey.key(event)) {
 | 
						|
                    ePreventDefault();
 | 
						|
                    customHotkey.handler(player, options, event);
 | 
						|
                  }
 | 
						|
                }
 | 
						|
              }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
    var doubleClick = function doubleClick(event) {
 | 
						|
      // When controls are disabled, hotkeys will be disabled as well
 | 
						|
      if (player.controls()) {
 | 
						|
 | 
						|
        // Don't catch clicks if any control buttons are focused
 | 
						|
        var activeEl = event.relatedTarget || event.toElement || doc.activeElement;
 | 
						|
        if (activeEl == pEl ||
 | 
						|
            activeEl == pEl.querySelector('.vjs-tech') ||
 | 
						|
            activeEl == pEl.querySelector('.iframeblocker')) {
 | 
						|
 | 
						|
          if (enableFull) {
 | 
						|
            if (player.isFullscreen()) {
 | 
						|
              player.exitFullscreen();
 | 
						|
            } else {
 | 
						|
              player.requestFullscreen();
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
    var volumeHover = false;
 | 
						|
    var volumeSelector = pEl.querySelector('.vjs-volume-menu-button') || pEl.querySelector('.vjs-volume-panel');
 | 
						|
    volumeSelector.onmouseover = function() { volumeHover = true; }
 | 
						|
    volumeSelector.onmouseout = function() { volumeHover = false; }
 | 
						|
    
 | 
						|
    var mouseScroll = function mouseScroll(event) {
 | 
						|
      if (enableHoverScroll) {
 | 
						|
        // If we leave this undefined then it can match non-existent elements below
 | 
						|
        var activeEl = 0;
 | 
						|
      } else {
 | 
						|
        var activeEl = doc.activeElement;
 | 
						|
      }
 | 
						|
 | 
						|
      // When controls are disabled, hotkeys will be disabled as well
 | 
						|
      if (player.controls()) {
 | 
						|
        if (alwaysCaptureHotkeys ||
 | 
						|
            activeEl == pEl ||
 | 
						|
            activeEl == pEl.querySelector('.vjs-tech') ||
 | 
						|
            activeEl == pEl.querySelector('.iframeblocker') ||
 | 
						|
            activeEl == pEl.querySelector('.vjs-control-bar') ||
 | 
						|
            volumeHover) {
 | 
						|
 | 
						|
          if (enableVolumeScroll) {
 | 
						|
            event = window.event || event;
 | 
						|
            var delta = Math.max(-1, Math.min(1, (event.wheelDelta || -event.detail)));
 | 
						|
            event.preventDefault();
 | 
						|
 | 
						|
            if (delta == 1) {
 | 
						|
              player.volume(player.volume() + volumeStep);
 | 
						|
            } else if (delta == -1) {
 | 
						|
              player.volume(player.volume() - volumeStep);
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
    var checkKeys = function checkKeys(e, player) {
 | 
						|
      // Allow some modularity in defining custom hotkeys
 | 
						|
 | 
						|
      // Play/Pause check
 | 
						|
      if (options.playPauseKey(e, player)) {
 | 
						|
        return cPlay;
 | 
						|
      }
 | 
						|
 | 
						|
      // Seek Backward check
 | 
						|
      if (options.rewindKey(e, player)) {
 | 
						|
        return cRewind;
 | 
						|
      }
 | 
						|
 | 
						|
      // Seek Forward check
 | 
						|
      if (options.forwardKey(e, player)) {
 | 
						|
        return cForward;
 | 
						|
      }
 | 
						|
 | 
						|
      // Volume Up check
 | 
						|
      if (options.volumeUpKey(e, player)) {
 | 
						|
        return cVolumeUp;
 | 
						|
      }
 | 
						|
 | 
						|
      // Volume Down check
 | 
						|
      if (options.volumeDownKey(e, player)) {
 | 
						|
        return cVolumeDown;
 | 
						|
      }
 | 
						|
 | 
						|
      // Mute check
 | 
						|
      if (options.muteKey(e, player)) {
 | 
						|
        return cMute;
 | 
						|
      }
 | 
						|
 | 
						|
      // Fullscreen check
 | 
						|
      if (options.fullscreenKey(e, player)) {
 | 
						|
        return cFullscreen;
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
    function playPauseKey(e) {
 | 
						|
      // Space bar or MediaPlayPause
 | 
						|
      return (e.which === 32 || e.which === 179);
 | 
						|
    }
 | 
						|
 | 
						|
    function rewindKey(e) {
 | 
						|
      // Left Arrow or MediaRewind
 | 
						|
      return (e.which === 37 || e.which === 177);
 | 
						|
    }
 | 
						|
 | 
						|
    function forwardKey(e) {
 | 
						|
      // Right Arrow or MediaForward
 | 
						|
      return (e.which === 39 || e.which === 176);
 | 
						|
    }
 | 
						|
 | 
						|
    function volumeUpKey(e) {
 | 
						|
      // Up Arrow
 | 
						|
      return (e.which === 38);
 | 
						|
    }
 | 
						|
 | 
						|
    function volumeDownKey(e) {
 | 
						|
      // Down Arrow
 | 
						|
      return (e.which === 40);
 | 
						|
    }
 | 
						|
 | 
						|
    function muteKey(e) {
 | 
						|
      // M key
 | 
						|
      return (e.which === 77);
 | 
						|
    }
 | 
						|
 | 
						|
    function fullscreenKey(e) {
 | 
						|
      // F key
 | 
						|
      return (e.which === 70);
 | 
						|
    }
 | 
						|
 | 
						|
    function seekStepD(e) {
 | 
						|
      // SeekStep caller, returns an int, or a function returning an int
 | 
						|
      return (typeof seekStep === "function" ? seekStep(e) : seekStep);
 | 
						|
    }
 | 
						|
 | 
						|
    player.on('keydown', keyDown);
 | 
						|
    player.on('dblclick', doubleClick);
 | 
						|
    player.on('mousewheel', mouseScroll);
 | 
						|
    player.on("DOMMouseScroll", mouseScroll);
 | 
						|
 | 
						|
    return this;
 | 
						|
  };
 | 
						|
 | 
						|
  var registerPlugin = videojs.registerPlugin || videojs.plugin;
 | 
						|
  registerPlugin('hotkeys', hotkeys);
 | 
						|
}));
 |