From 28de864295f128ec22a485eac57430289e23cb25 Mon Sep 17 00:00:00 2001 From: Korbs Date: Mon, 26 Feb 2024 20:59:47 -0500 Subject: [PATCH] Add shortcuts and autohide controls --- src/functions/AutoToggleControls.js | 46 ++++++++++++++++ src/functions/Fullscreen.js | 5 +- src/functions/KeyboardShortcuts.js | 82 +++++++++++++++++++++++++++++ src/functions/Seek.js | 1 - src/get.js | 1 + src/index.js | 4 ++ src/themes/default.js | 11 ++-- test/index.html | 4 +- test/js/zorn.js | 31 +++++------ 9 files changed, 159 insertions(+), 26 deletions(-) create mode 100644 src/functions/AutoToggleControls.js create mode 100644 src/functions/KeyboardShortcuts.js diff --git a/src/functions/AutoToggleControls.js b/src/functions/AutoToggleControls.js new file mode 100644 index 0000000..39ad80f --- /dev/null +++ b/src/functions/AutoToggleControls.js @@ -0,0 +1,46 @@ +import { VideoContainer, VideoControls, ZornVideoPlayer } from '../get' + + +export function AutoToggleControls() { + function Hide_Controls() { + var ZornTitleArea = document.querySelector(".video-container > h2") + if (ZornVideoPlayer.paused) { + return + } else { + document.querySelector('.zorn-player-controls').classList.add('hide') + ZornTitleArea.classList.add('hide') + } + } + + // Show_Controls displays the video controls + function Show_Controls() { + var ZornTitleArea = document.querySelector(".video-container > h2") + document.querySelector('.zorn-player-controls').classList.remove('hide') + ZornTitleArea.classList.remove('hide') + } + ZornVideoPlayer.addEventListener('mouseenter', Show_Controls) + ZornVideoPlayer.addEventListener('mouseleave', Hide_Controls) + document.querySelector('.zorn-player-controls').addEventListener('mouseenter', Show_Controls) + document.querySelector('.zorn-player-controls').addEventListener('mouseleave', Hide_Controls) + + var mouseTimer = null, cursorVisible = true + + function Hide_Cursor() { + mouseTimer = null + VideoContainer.style.cursor = "none" + cursorVisible = false + Hide_Controls() + } + + document.onmousemove = function() { + if (mouseTimer) { + window.clearTimeout(mouseTimer) + Show_Controls() + } + if (!cursorVisible) { + VideoContainer.style.cursor = "default" + cursorVisible = true + } + mouseTimer = window.setTimeout(Hide_Cursor, 3200) + } +} \ No newline at end of file diff --git a/src/functions/Fullscreen.js b/src/functions/Fullscreen.js index 2f51e3b..d4f7141 100644 --- a/src/functions/Fullscreen.js +++ b/src/functions/Fullscreen.js @@ -1,4 +1,4 @@ -import { VideoContainer } from '../get' +import { VideoContainer, ZornVideoPlayer } from '../get' export function Fullscreen() { @@ -14,12 +14,11 @@ export function Fullscreen() { function Update_FullscreenButton() { if (document.fullscreenElement) { Button_Fullscreen.setAttribute('data-title', 'Exit full screen (f)') - Button_Fullscreen.innerHTML = `` } else { Button_Fullscreen.setAttribute('data-title', 'Full screen (f)') - Button_Fullscreen.innerHTML = `` } } VideoContainer.addEventListener('fullscreenchange', Update_FullscreenButton) + ZornVideoPlayer.addEventListener('dblclick', () => {Toggle_Fullscreen()}) } \ No newline at end of file diff --git a/src/functions/KeyboardShortcuts.js b/src/functions/KeyboardShortcuts.js new file mode 100644 index 0000000..b9c184b --- /dev/null +++ b/src/functions/KeyboardShortcuts.js @@ -0,0 +1,82 @@ +import { ZornVideoPlayer, VideoContainer } from "../get" + +export function KeyboardShortcuts(events) { + /// Grab custom ones, if any + if (ZornVideoPlayer.hasAttribute('keyboard-shortcut-fullscreen')) { + var Fullscreen_KeyboardShortcut = ZornVideoPlayer.getAttribute('keyboard-shortcut-fullscreen') + } + else { + var Fullscreen_KeyboardShortcut = 'f' + } + + if (ZornVideoPlayer.hasAttribute('keyboard-shortcut-mute')) { + var Mute_KeyboardShortcut = ZornVideoPlayer.getAttribute('keyboard-shortcut-mute') + } + else { + var Mute_KeyboardShortcut = 'm' + } + + if (ZornVideoPlayer.hasAttribute('keyboard-shortcut-playpause')) { + var PlayPause_KeyboardShortcut = ZornVideoPlayer.getAttribute('keyboard-shortcut-playpause') + } + else { + var PlayPause_KeyboardShortcut = 'k' + } + + if (ZornVideoPlayer.hasAttribute('keyboard-shortcut-skipback')) { + var SkipBack_KeyboardShortcut = ZornVideoPlayer.getAttribute('keyboard-shortcut-skipback') + } + else { + var SkipBack_KeyboardShortcut = 'j' + } + + if (ZornVideoPlayer.hasAttribute('keyboard-shortcut-skipforth')) { + var SkipForth_KeyboardShortcut = ZornVideoPlayer.getAttribute('keyboard-shortcut-skipforth') + } + else { + var SkipForth_KeyboardShortcut = 'l' + } + + /// Defaults + function keyboardShortcuts(event) { + const { key } = event + if (key === PlayPause_KeyboardShortcut) { + if (ZornVideoPlayer.paused || ZornVideoPlayer.ended) { + ZornVideoPlayer.play() + } + else { + ZornVideoPlayer.pause() + } + if (ZornVideoPlayer.paused) { + Show_Controls() + } else { + setTimeout(() => { + Hide_Controls() + }, 1200) + } + } + else if (key === Mute_KeyboardShortcut) { + ZornVideoPlayer.muted = !ZornVideoPlayer.muted + + if (ZornVideoPlayer.muted) { + volume.setAttribute('data-volume', volume.value) + volume.value = 0 + } else { + volume.value = volume.dataset.volume + } + } + else if (key === Fullscreen_KeyboardShortcut) { + if (document.fullscreenElement) {document.exitFullscreen()} + else if (document.webkitFullscreenElement) {document.webkitExitFullscreen()} + else if (VideoContainer.webkitRequestFullscreen) {VideoContainer.webkitRequestFullscreen()} + else {VideoContainer.requestFullscreen()} + } + else if (key === SkipBack_KeyboardShortcut) { + ZornVideoPlayer.currentTime += (-10) + } + else if (key === SkipForth_KeyboardShortcut) { + ZornVideoPlayer.currentTime += (10) + } + } + document.addEventListener('keyup', keyboardShortcuts) +} \ No newline at end of file diff --git a/src/functions/Seek.js b/src/functions/Seek.js index 92e1cb9..d026d77 100644 --- a/src/functions/Seek.js +++ b/src/functions/Seek.js @@ -1,6 +1,5 @@ import { ZornVideoPlayer } from '../get' - export function Seek() { // Duration and Length of Video const timeElapsed = document.getElementById('time-elapsed'); diff --git a/src/get.js b/src/get.js index 9e51c5f..dba0d17 100644 --- a/src/get.js +++ b/src/get.js @@ -1,6 +1,7 @@ // Set Variables for required video container and video player export var ZornVideoPlayer = document.querySelector('.zorn-player') export var VideoContainer = document.querySelector('.video-container') +export var VideoControls = document.querySelector('.zorn-player-controls') // Icons - Iconoir.com /// Get Icons diff --git a/src/index.js b/src/index.js index 300af4b..97adbb2 100644 --- a/src/index.js +++ b/src/index.js @@ -10,6 +10,8 @@ import { Subtitles } from "./functions/Subtitles" import { Volume } from "./functions/Volume" import { Seek } from "./functions/Seek" import { BufferDialog } from "./dialogs/Buffering" +import { AutoToggleControls } from "./functions/AutoToggleControls" +import { KeyboardShortcuts } from "./functions/KeyboardShortcuts" // Apply Controls ZornVideoPlayer.insertAdjacentHTML("afterend", Controls) @@ -17,7 +19,9 @@ ZornVideoPlayer.insertAdjacentHTML("afterend", BufferDialog) // Init Functions Events() +KeyboardShortcuts() PlayPause() +AutoToggleControls() // Broken SkipAround() Fullscreen() Subtitles() diff --git a/src/themes/default.js b/src/themes/default.js index 2477d69..8b6b739 100644 --- a/src/themes/default.js +++ b/src/themes/default.js @@ -136,11 +136,12 @@ export var Controls = ` display: none; position: absolute; right: 60px; - bottom: 50px; + bottom: 70px; background: #000 9; list-style: none; padding: 6px; border-radius: 6px; + background: rgb(0 0 0 / 50%); } .video-container .subtitles-menu button { background-color: transparent; @@ -196,9 +197,9 @@ export var Controls = ` border: none; margin: 0px 6px; } -.video-container .zorn-player-controls button:hover { - background: rgba(44, 44, 44, 0.6); - border-radius: 6px; +.volume-controls { + display: flex; + align-items: center; } .video-container .zorn-player-controls .volume-controls:hover > #volume { opacity: 1; @@ -209,7 +210,7 @@ export var Controls = ` .video-container .zorn-player-controls #volume { opacity: 0; transition: 0.3s opacity, 0.3s width; - margin: 0px -6px; + margin: 0px 12px 0px -6px; width: 0px; } .video-container .zorn-player-controls #volume-button svg { diff --git a/test/index.html b/test/index.html index 8eaa04c..e6d54aa 100644 --- a/test/index.html +++ b/test/index.html @@ -6,7 +6,7 @@
-
- + \ No newline at end of file diff --git a/test/js/zorn.js b/test/js/zorn.js index 351e1d2..fd3ec6c 100644 --- a/test/js/zorn.js +++ b/test/js/zorn.js @@ -1,4 +1,4 @@ -(()=>{var x='';var b='';var y='';var w='';var C='';var z='';var M='';var V='';var L='';var T='';var e=document.querySelector(".zorn-player"),p=document.querySelector(".video-container"),g=x,E=b,B=y,I=w,S=C,H=z,h=M,F=V,P=L,$=T;var j=` +(()=>{var y='';var b='';var x='';var w='';var C='';var z='';var V='';var L='';var M='';var T='';var e=document.querySelector(".zorn-player"),d=document.querySelector(".video-container"),he=document.querySelector(".zorn-player-controls"),h=y,S=b,E=x,A=w,F=C,B=z,v=V,I=L,H=M,P=T;var j=`

@@ -11,7 +11,7 @@
- +
@@ -21,13 +21,13 @@
- - - + + +
- - + +
@@ -126,11 +126,12 @@ display: none; position: absolute; right: 60px; - bottom: 50px; + bottom: 70px; background: #000 9; list-style: none; padding: 6px; border-radius: 6px; + background: rgb(0 0 0 / 50%); } .video-container .subtitles-menu button { background-color: transparent; @@ -186,9 +187,9 @@ border: none; margin: 0px 6px; } -.video-container .zorn-player-controls button:hover { - background: rgba(44, 44, 44, 0.6); - border-radius: 6px; +.volume-controls { + display: flex; + align-items: center; } .video-container .zorn-player-controls .volume-controls:hover > #volume { opacity: 1; @@ -199,7 +200,7 @@ .video-container .zorn-player-controls #volume { opacity: 0; transition: 0.3s opacity, 0.3s width; - margin: 0px -6px; + margin: 0px 12px 0px -6px; width: 0px; } .video-container .zorn-player-controls #volume-button svg { @@ -352,8 +353,8 @@ div#buffering { } } -`;function A(){e.addEventListener("error",function(t){document.querySelector("#invalid-src").style.display="inherit",document.querySelector(".zorn-player-controls").style.display="none",videoContainer.style.backgroundColor="#101010",setTimeout(()=>{e.style.opacity="0.10",document.querySelector("#buffering").style.display="none"},168)},!0),e.onwaiting=t=>{document.querySelector("#buffering").style.display="inherit",e.style.transition="5s opacity",e.style.opacity="0.25"},e.oncanplaythrough=t=>{document.querySelector("#buffering").style.display="none",e.style.transition="0.3s opacity",e.style.opacity="1"}}function U(){let t=document.querySelector(".zorn-player-controls #play-pause");t.addEventListener("click",r),e.addEventListener("click",r),e.addEventListener("play",i),e.addEventListener("pause",i);function r(){e.paused||e.ended?e.play():e.pause()}function i(){e.paused?(t.setAttribute("data-title","Play (K)"),t.innerHTML=`${g}`):(t.setAttribute("data-title","Pause (K)"),t.innerHTML=`${E}`)}}function Z(){let t=document.querySelector(".zorn-player-controls #skip-back"),r=document.querySelector(".zorn-player-controls #skip-forth");t.addEventListener("click",i),r.addEventListener("click",a);function i(){d(-10)}function a(){d(10)}function d(s){e.currentTime+=s}}function _(){let t=document.getElementById("fullscreen");function r(){document.fullscreenElement?document.exitFullscreen():document.webkitFullscreenElement?document.webkitExitFullscreen():p.webkitRequestFullscreen?p.webkitRequestFullscreen():p.requestFullscreen()}t.onclick=r;function i(){document.fullscreenElement?(t.setAttribute("data-title","Exit full screen (f)"),t.innerHTML=''):(t.setAttribute("data-title","Full screen (f)"),t.innerHTML='')}p.addEventListener("fullscreenchange",i)}function q(){var t=document.querySelector(".zorn-player-controls #subtitles"),r=[],i=function(c,k,u){var m=document.createElement("li"),l=m.appendChild(document.createElement("button"));return l.setAttribute("id",c),l.className="subtitles-button",k.length>0&&l.setAttribute("lang",k),l.value=u,l.setAttribute("data-state","inactive"),l.appendChild(document.createTextNode(u)),l.addEventListener("click",function(o){r.map(function(v,O,oe){r[O].setAttribute("data-state","inactive")});for(var n=this.getAttribute("lang"),f=0;f0&&e.volume<=.5?t.innerHTML=`${F}`:t.innerHTML=`${h}`}e.addEventListener("volumechange",a);function d(){e.muted=!e.muted,e.muted?(r.setAttribute("data-volume",r.value),r.value=0):r.value=r.dataset.volume}t.addEventListener("click",d)}function D(){let t=document.getElementById("time-elapsed"),r=document.getElementById("duration");function i(o){let n=new Date(o*1e3).toISOString().substr(11,8);return{minutes:n.substr(3,2),seconds:n.substr(6,2)}}e.addEventListener("loadedmetadata",c);function a(){let o=i(Math.round(e.currentTime));t.innerText=`${o.minutes}:${o.seconds}`,t.setAttribute("datetime",`${o.minutes}m ${o.seconds}s`)}e.addEventListener("timeupdate",a);let d=document.getElementById("progress-bar"),s=document.getElementById("seek");function c(){let o=Math.round(e.duration);s.setAttribute("max",o),d.setAttribute("max",o);let n=i(o);r.innerText=`${n.minutes}:${n.seconds}`,r.setAttribute("datetime",`${n.minutes}m ${n.seconds}s`)}function k(){s.value=Math.floor(e.currentTime),d.value=Math.floor(e.currentTime)}e.addEventListener("timeupdate",k);let u=document.getElementById("seek-tooltip");function m(o){let n=Math.round(o.offsetX/o.target.clientWidth*parseInt(o.target.getAttribute("max"),10));s.setAttribute("data-seek",n);let f=i(n);u.textContent=`${f.minutes}:${f.seconds}`;let v=e.getBoundingClientRect();u.style.left=`${o.pageX-v.left}px`}s.addEventListener("mousemove",m);function l(o){let n=o.target.dataset.seek?o.target.dataset.seek:o.target.value;e.currentTime=n,d.value=n,s.value=n}s.addEventListener("input",l),c()}var R=` +`;function $(){e.addEventListener("error",function(t){document.querySelector("#invalid-src").style.display="inherit",document.querySelector(".zorn-player-controls").style.display="none",videoContainer.style.backgroundColor="#101010",setTimeout(()=>{e.style.opacity="0.10",document.querySelector("#buffering").style.display="none"},168)},!0),e.onwaiting=t=>{document.querySelector("#buffering").style.display="inherit",e.style.transition="5s opacity",e.style.opacity="0.25"},e.oncanplaythrough=t=>{document.querySelector("#buffering").style.display="none",e.style.transition="0.3s opacity",e.style.opacity="1"}}function _(){let t=document.querySelector(".zorn-player-controls #play-pause");t.addEventListener("click",r),e.addEventListener("click",r),e.addEventListener("play",o),e.addEventListener("pause",o);function r(){e.paused||e.ended?e.play():e.pause()}function o(){e.paused?(t.setAttribute("data-title","Play (K)"),t.innerHTML=`${h}`):(t.setAttribute("data-title","Pause (K)"),t.innerHTML=`${S}`)}}function q(){let t=document.querySelector(".zorn-player-controls #skip-back"),r=document.querySelector(".zorn-player-controls #skip-forth");t.addEventListener("click",o),r.addEventListener("click",n);function o(){l(-10)}function n(){l(10)}function l(a){e.currentTime+=a}}function Z(){let t=document.getElementById("fullscreen");function r(){document.fullscreenElement?document.exitFullscreen():document.webkitFullscreenElement?document.webkitExitFullscreen():d.webkitRequestFullscreen?d.webkitRequestFullscreen():d.requestFullscreen()}t.onclick=r;function o(){document.fullscreenElement?t.setAttribute("data-title","Exit full screen (f)"):t.setAttribute("data-title","Full screen (f)")}d.addEventListener("fullscreenchange",o),e.addEventListener("dblclick",()=>{r()})}function U(){var t=document.querySelector(".zorn-player-controls #subtitles"),r=[],o=function(p,m,f){var k=document.createElement("li"),u=k.appendChild(document.createElement("button"));return u.setAttribute("id",p),u.className="subtitles-button",m.length>0&&u.setAttribute("lang",m),u.value=f,u.setAttribute("data-state","inactive"),u.appendChild(document.createTextNode(f)),u.addEventListener("click",function(i){r.map(function(g,N,ie){r[N].setAttribute("data-state","inactive")});for(var s=this.getAttribute("lang"),c=0;c0&&e.volume<=.5?t.innerHTML=`${I}`:t.innerHTML=`${v}`}e.addEventListener("volumechange",n);function l(){e.muted=!e.muted,e.muted?(r.setAttribute("data-volume",r.value),r.value=0):r.value=r.dataset.volume}t.addEventListener("click",l)}function K(){let t=document.getElementById("time-elapsed"),r=document.getElementById("duration");function o(i){let s=new Date(i*1e3).toISOString().substr(11,8);return{minutes:s.substr(3,2),seconds:s.substr(6,2)}}e.addEventListener("loadedmetadata",p);function n(){let i=o(Math.round(e.currentTime));t.innerText=`${i.minutes}:${i.seconds}`,t.setAttribute("datetime",`${i.minutes}m ${i.seconds}s`)}e.addEventListener("timeupdate",n);let l=document.getElementById("progress-bar"),a=document.getElementById("seek");function p(){let i=Math.round(e.duration);a.setAttribute("max",i),l.setAttribute("max",i);let s=o(i);r.innerText=`${s.minutes}:${s.seconds}`,r.setAttribute("datetime",`${s.minutes}m ${s.seconds}s`)}function m(){a.value=Math.floor(e.currentTime),l.value=Math.floor(e.currentTime)}e.addEventListener("timeupdate",m);let f=document.getElementById("seek-tooltip");function k(i){let s=Math.round(i.offsetX/i.target.clientWidth*parseInt(i.target.getAttribute("max"),10));a.setAttribute("data-seek",s);let c=o(s);f.textContent=`${c.minutes}:${c.seconds}`;let g=e.getBoundingClientRect();f.style.left=`${i.pageX-g.left}px`}a.addEventListener("mousemove",k);function u(i){let s=i.target.dataset.seek?i.target.dataset.seek:i.target.value;e.currentTime=s,l.value=s,a.value=s}a.addEventListener("input",u),p()}var R=`
- ${$} + ${P}
-`;e.insertAdjacentHTML("afterend",j);e.insertAdjacentHTML("afterend",R);A();U();Z();_();q();G();D();Buffering();})(); +`;function D(){function t(){var a=document.querySelector(".video-container > h2");e.paused||(document.querySelector(".zorn-player-controls").classList.add("hide"),a.classList.add("hide"))}function r(){var a=document.querySelector(".video-container > h2");document.querySelector(".zorn-player-controls").classList.remove("hide"),a.classList.remove("hide")}e.addEventListener("mouseenter",r),e.addEventListener("mouseleave",t),document.querySelector(".zorn-player-controls").addEventListener("mouseenter",r),document.querySelector(".zorn-player-controls").addEventListener("mouseleave",t);var o=null,n=!0;function l(){o=null,d.style.cursor="none",n=!1,t()}document.onmousemove=function(){o&&(window.clearTimeout(o),r()),n||(d.style.cursor="default",n=!0),o=window.setTimeout(l,3200)}}function O(t){if(e.hasAttribute("keyboard-shortcut-fullscreen"))var r=e.getAttribute("keyboard-shortcut-fullscreen");else var r="f";if(e.hasAttribute("keyboard-shortcut-mute"))var o=e.getAttribute("keyboard-shortcut-mute");else var o="m";if(e.hasAttribute("keyboard-shortcut-playpause"))var n=e.getAttribute("keyboard-shortcut-playpause");else var n="k";if(e.hasAttribute("keyboard-shortcut-skipback"))var l=e.getAttribute("keyboard-shortcut-skipback");else var l="j";if(e.hasAttribute("keyboard-shortcut-skipforth"))var a=e.getAttribute("keyboard-shortcut-skipforth");else var a="l";function p(m){let{key:f}=m;f===n?(e.paused||e.ended?e.play():e.pause(),e.paused?Show_Controls():setTimeout(()=>{Hide_Controls()},1200)):f===o?(e.muted=!e.muted,e.muted?(volume.setAttribute("data-volume",volume.value),volume.value=0):volume.value=volume.dataset.volume):f===r?document.fullscreenElement?document.exitFullscreen():document.webkitFullscreenElement?document.webkitExitFullscreen():d.webkitRequestFullscreen?d.webkitRequestFullscreen():d.requestFullscreen():f===l?e.currentTime+=-10:f===a&&(e.currentTime+=10)}document.addEventListener("keyup",p)}e.insertAdjacentHTML("afterend",j);e.insertAdjacentHTML("afterend",R);$();O();_();D();q();Z();U();G();K();Buffering();})();