123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- /*
- * 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.27" };
- }
- 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: false,
- enableFullscreen: true,
- enableNumbers: true,
- enableJogStyle: false,
- alwaysCaptureHotkeys: false,
- captureDocumentHotkeys: false,
- documentHotkeysFocusElementFilter: function () { return 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,
- captureDocumentHotkeys = options.captureDocumentHotkeys,
- documentHotkeysFocusElementFilter = options.documentHotkeysFocusElementFilter,
- enableModifiersForNumbers = options.enableModifiersForNumbers,
- enableInactiveFocus = options.enableInactiveFocus,
- skipInitialFocus = options.skipInitialFocus;
- var videojsVer = videojs.VERSION;
- // 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.bind(event);
- 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 ||
- (captureDocumentHotkeys && documentHotkeysFocusElementFilter(activeEl)) ||
- 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 || captureDocumentHotkeys) {
- // Prevent control activation with space
- event.stopPropagation();
- }
- if (player.paused()) {
- silencePromise(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) {
- silencePromise(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) {
- silencePromise(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) {
- // Video.js added double-click fullscreen in 7.1.0
- if (videojsVer != null && videojsVer <= "7.1.0") {
- // 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');
- if (volumeSelector != null) {
- 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);
- }
- function silencePromise(value) {
- if (value != null && typeof value.then === 'function') {
- value.then(null, function(e) {});
- }
- }
- player.on('keydown', keyDown);
- player.on('dblclick', doubleClick);
- player.on('mousewheel', mouseScroll);
- player.on("DOMMouseScroll", mouseScroll);
- if (captureDocumentHotkeys) {
- document.addEventListener('keydown', function (event) { keyDown(event) });
- }
- return this;
- };
- var registerPlugin = videojs.registerPlugin || videojs.plugin;
- registerPlugin('hotkeys', hotkeys);
- }));
|