UNPKG

rajeo

Version:

A modern video player for html5 videos

279 lines (250 loc) 8.08 kB
/**! * * © 2021 Rajaniraiyn * * LICENCE: https://raw.githubusercontent.com/Rajaniraiyn/rajeo/main/LICENSE * */ "use strict"; ((_) => { "use strict"; let videoElements = [...document.getElementsByTagName("video")]; /** * * HTML template to inject * * @param {string} src URL of the Video * @param {string} id Unique ID for scripts * @param {string} title for the top bar * @param {boolean | string} autoplay * @returns {string} */ const template = (src, id, title, autoplay) => { if (!title) { title = src.split("/"); title = title[title.length - 1].split(".")[0]; } return ` <div class="rajeo-player" id="${id}" > <link rel="stylesheet" href="https://unpkg.com/rajeo@latest/dist/style.css"> <a class="rajeo-overlay"> <div class="rajeo-animation"></div> </a> <div class="rajeo-top"> <img src="https://avatar.statically.workers.dev/avatar/${title.toUpperCase()}/?shape=circle&s=20" /> <span class="rajeo-title" title=${title}>${title}</span> </div> <video src="${src}" autoplay=${autoplay} style="max-height: 90vh; width: 95vw;"></video> <div class="rajeo-bottom"> <div class="rajeo-controls"> <div class="rajeo-buttons-left"> <div class="rajeo-pause-play"> <img src="https://fonts.gstatic.com/s/i/materialiconsround/play_arrow/v15/24px.svg" class="rajeo-play" title="play"> <img src="https://fonts.gstatic.com/s/i/materialiconsround/pause/v15/24px.svg" class="rajeo-pause" style="display: none;" title="pause"> </div> <img src="https://fonts.gstatic.com/s/i/materialiconsround/volume_up/v13/24px.svg" class="rajeo-sound"> </div> <div class="rajeo-progress"> <div class="rajeo-load-progress"></div> <input type="range" class="rajeo-progress-toggle" min="0" max="100" step="0.01" value="0"> </div> <div class="rajeo-buttons-right"> <img src="https://fonts.gstatic.com/s/i/materialiconsround/picture_in_picture_alt/v12/24px.svg" class="rajeo-pip" title="Toggle picture in picture"> <div class="rajeo-fullscreen"> <img src="https://fonts.gstatic.com/s/i/materialicons/fullscreen/v12/24px.svg" class="rajeo-full" title="Toggle fullscreen"> </div> <img src="https://fonts.gstatic.com/s/i/materialiconsround/more_vert/v18/24px.svg" class="rajeo-more" title="More"> </div> </div> </div> </div> `; }; /** * * REVERSED FOR LOOP * * Most efficient loop method * * @param {array} array * @param {Function} callback */ function forEach(array, callback) { for (var i = 0, len = array.length; i < len; i++) { callback(array[i], i); } } forEach(videoElements, (videoElem, id) => { injectPlayer(videoElem, id); }); /** * * Injects Template to DOM and attaches scripts * * @param {HTMLVideoElement} videoElem * @param {string | number} id */ function injectPlayer(videoElem, id) { var id = "rajeo-" + (id || Date.now()); videoElem.insertAdjacentHTML( "beforebegin", template(videoElem.src, id, videoElem.title, videoElem.autoplay) ); videoElem.remove(); setTimeout((_) => { addFunctions(id); }, 0.1e3); } /** * * Attaches all necessary functions * * @param {string} id */ function addFunctions(id) { const player = document.getElementById(id), video = player.getElementsByTagName("video")[0], overlay = player.getElementsByClassName("rajeo-overlay")[0], pause_play_div = player.getElementsByClassName("rajeo-pause-play")[0], pause_icon = player.getElementsByClassName("rajeo-pause")[0], play_icon = player.getElementsByClassName("rajeo-play")[0], slider = player.getElementsByClassName("rajeo-progress-toggle")[0], loadProgress = player.getElementsByClassName("rajeo-load-progress")[0], full = player.getElementsByClassName("rajeo-full")[0], pip = player.getElementsByClassName("rajeo-pip")[0], sound = player.getElementsByClassName("rajeo-sound")[0]; pause_play_div.onmousedown = pause_play; overlay.onclick = pause_play; /** * Toggles Pause and Play */ function pause_play() { if (video.paused || video.ended) { play(); } else { pause(); } } /** * Play the video */ function play() { play_icon.style.display = "none"; pause_icon.style.display = "block"; video.play(); } /** * Pauses the Video */ function pause() { play_icon.style.display = "block"; pause_icon.style.display = "none"; video.pause(); } video.onplay = play; video.onpause = pause; /** * Toggles Mute and Unmute */ sound.onclick = mute_unmute; function mute_unmute() { if (video.muted === true) { video.muted = false; } else if (video.muted === false) { video.muted = true; } } /** * * Updates the slider to specific value * * @param {string | number} value in percentage without `%` i.e. less than 100 * * @example updateSlider("50") or updateSlider(50) */ function updateSlider(value) { slider.value = value; slider.style.setProperty( "--track-color", `linear-gradient(90deg, red ${value}%, transparent ${value}%)` ); } video.ontimeupdate = (e) => { updateSlider( ((e.target.currentTime / e.target.duration) * 100).toString() ); if (e.target.currentTime === e.target.duration) { pause(); } loadProgress.style.width = (e.target.buffered.end(0) / e.target.duration) * 100 + "%"; }; slider.oninput = (e) => { updateSlider(e.target.value); video.currentTime = (parseInt(e.target.value) / 100) * video.duration; }; /** * * Toggles fullscreen * * @param {HTMLElement} element */ function toggleFullscreen(element) { const is_fullscreen = !( window.innerWidth == screen.width && window.innerHeight == screen.height ); if (is_fullscreen) { const requestFullScreen = element.requestFullscreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullScreen; requestFullScreen.call(element); full.src = full.src.replace("fullscreen", "fullscreen_exit"); } else { const cancelFullScreen = document.exitFullscreen || document.mozCancelFullScreen || document.webkitExitFullscreen || document.msExitFullscreen; cancelFullScreen.call(document); full.src = full.src.replace("fullscreen_exit", "fullscreen"); } } /** * Toggles Picture-in-Picture aka PiP */ function togglePiP() { if (document.pictureInPictureEnabled && !video.disablePictureInPicture) { try { if (document.pictureInPictureElement) { document.exitPictureInPicture(); } else video.requestPictureInPicture(); } catch (err) { console.error(err); } } else video.remove(); } /** * * @param {number} value */ function updateVolume(value) { video.volume = value; } full.onmousedown = (_) => { toggleFullscreen(player); }; overlay.ondblclick = (_) => { toggleFullscreen(player); }; pip.onmousedown = togglePiP; setTimeout((_) => { loadProgress.style.width = (video.buffered.end(0) / video.duration) * 100 + "%"; }, 1e3); } })();