add video controls to 9gag gif and video post. Add volume slider on chrome browser
// ==UserScript== // @name 9gag show video control // @namespace http://javalatte.xyz // @version 1.5.2 // @description add video controls to 9gag gif and video post. Add volume slider on chrome browser // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js // @author Akzn // @match https://9gag.com/* // ==/UserScript== 'use strict'; var timer; var isChrome = !!window.chrome && !!window.chrome.webstore; var isFirefox = (navigator.userAgent.indexOf("Firefox") != -1)? true : false; //--- CSS styles //--- Button autoplay GM_addStyle (".gmPersistentButton {background: var(--palette-primary);position: fixed;bottom: 1em;right: 1em;z-index: 6666;border-radius: 18px;}.gmPersistentButton button {cursor: pointer;background: var(--palette-primary);color: white;font-size: 14px;font-style: normal;font-weight: 700;line-height: 20px;letter-spacing: 0em;bottom: 1em;right: 1em;z-index: 6666;padding: 1em;border: var(--palette-primary);border-radius: 18px;opacity: 0.8;}.gmPersistentButton:hover, .gmPersistentButton button:hover {background-color: var(--palette-primary-hover);}"); // Slider for chrome if(isChrome==true){ GM_addStyle (".div-slider {opacity: 0;text-align: center;padding-top: 5px;width: 29px;height: 120px;position: absolute;bottom: 50px;right: 24px;cursor: pointer;z-index: 99999;border-radius: 15px;background-color: rgba(0, 0, 0, 0.8);}"); GM_addStyle(".volume-slider{-webkit-appearance: slider-vertical;width: 30px;height: 160px;position: absolute;top: 12px;right: 0px;cursor: pointer;z-index: 99999;height: 100px;width: 2px;margin: auto 13px;}"); } //--- Add the button. $("body").append ( '<div class="gmPersistentButton">' + '<button id="gmAutoplayVideoBtn">Init failed!</button></div>' ); //--- Define and init the matching control object: var btnControl = new PersistentButton ( "gmAutoplayVideoBtn", //-- HTML id "StopContinueBtn", //-- Storage label ["Autoplay Video : Off", "Autoplay Video : On"], //-- Text that the button cycles through [false, true] //-- Matching values for the button's states ); //--- Activate the button click-handler. $("#gmAutoplayVideoBtn").click ( function () { btnControl.SetNextValue (); var btnValue = this.value; keepgoing = btnValue _handlegmAutoplayVideoBtnClick(keepgoing) } ); //--- Button object function PersistentButton (htmlID, setValName, textArry, valueArry) { //--- Initialize the button to last stored value or default. var buttonValue = valueArry[0]; fetchValue (); storeValue (); //-- Store, in case it wasn't already. setButtonTextAndVal (); //--- DONE with init. Set click and keyboard listeners externally. //***** Public functions: this.Reset = function () { buttonValue = valueArry[0]; storeValue (); setButtonTextAndVal (); }; this.SetNextValue = function () { var numValues = valueArry.length; var valIndex = 0; for (var J = numValues - 1; J >= 0; --J) { if (buttonValue == valueArry[J]) { valIndex = J; break; } } valIndex++; if (valIndex >= numValues) valIndex = 0; buttonValue = valueArry[valIndex]; storeValue (); setButtonTextAndVal (); }; //***** Private functions: function fetchValue () { buttonValue = GM_getValue (setValName, buttonValue); } function storeValue () { GM_setValue (setValName, buttonValue); } function setButtonTextAndVal () { var buttonText = "*ERROR!*"; for (var J = valueArry.length - 1; J >= 0; --J) { if (buttonValue == valueArry[J]) { buttonText = textArry[J]; break; } } var theBtn = document.getElementById (htmlID); if (theBtn) { theBtn.textContent = buttonText; theBtn.setAttribute ("value", buttonValue); } else alert ('Missing persistent button with ID: ' + htmlID + '!'); } } //--- Video control function addVideoControl(){ var vids = document.getElementsByTagName('video'); for( var i = 0; i < vids.length; i++ ){ var elem = vids.item(i); elem.setAttribute("preload","none") if(!elem.hasAttribute("controls")){ //--- bind play button $(elem).bind('play', function (e) { isViewable = isElementXPercentInViewport(e.target,90) if (isViewable) { e.target.setAttribute('pause','false') } }); $(elem).bind('pause', function (e) { e.target.setAttribute('pause','true') }); elem.setAttribute("controls", ""); elem.volume = 0.5; setVideoPlay(elem) // console.log('video controls added'); //add volume slider to chrome video. Why tf chrome dev removed their dafault slider if((elem.parentNode.parentNode.getElementsByClassName('video-post').length>0) && (isChrome == true)){ var slider = document.createElement("div"); slider.setAttribute("class",'div-slider'); slider.innerHTML = '<input id="vol-control" class="volume-slider" type="range" min="0" max="1" step="0.1"></input>'; elem.parentNode.insertBefore(slider, elem.parentNode.parentNode.nextSibling); var nSlider = elem.parentNode.parentNode.parentNode.getElementsByTagName('input'); nSlider[0].addEventListener("input",setVolume,false); nSlider[0].addEventListener("change",setVolume,false); nSlider[0].elem = elem; nSlider[0].value = elem.volume; elem.slider = nSlider[0]; elem.addEventListener("mouseover",sliderIn,false); elem.addEventListener("mouseout",sliderOut,false); nSlider[0].slider = nSlider[0]; nSlider[0].addEventListener("mouseover",sliderIn,false); nSlider[0].addEventListener("mouseout",sliderOut,false); } } if ($("#gmAutoplayVideoBtn").val() == "false") { // to handle 9gag very own autoplay js if(elem.getAttribute("pause")=='true'){ elem.pause(); } } elem.addEventListener("click",handlePauseElem,false) if(elem.parentNode.querySelector('.presenting')){ elem.parentNode.querySelector('.presenting').addEventListener("click",handlePausePlayButton,false) } if(elem.parentNode.parentNode.querySelector('.video-post')){ elem.parentNode.parentNode.querySelector('.video-post').addEventListener("click",handlePauseBox,false) } if(elem.parentNode.parentNode.querySelector('.gif-post')){ elem.parentNode.parentNode.querySelector('.gif-post').addEventListener("click",handlePauseBox,false) } } } function sliderIn(evt){ evt.target.slider.parentNode.style.opacity = 1; } function sliderOut(evt){ evt.target.slider.parentNode.style.opacity = 0; } function setVolume(evt){ var elem = evt.target.elem; elem.volume = evt.target.value; elem.muted = false; } function handlePauseBox(evt){ var elem = evt.target; setVideoPlay(elem.getElementsByTagName('video')[0]) } function handlePausePlayButton(evt){ var elem = evt.target; setVideoPlay(elem.parentNode.parentNode.getElementsByTagName('video')[0]) } function handlePauseElem(evt){ var elem = evt.target; setVideoPlay(elem) } function setVideoPlay(elem,buttonStorageValue = null){ if (buttonStorageValue == null) { if ($("#gmAutoplayVideoBtn").val() == "true") { elem.setAttribute("pause", "false"); } else { if(elem.getAttribute("pause")=='true'){ elem.setAttribute("pause", "false"); } else { elem.setAttribute("pause", "true"); } } } else { if (buttonStorageValue == 'false') { elem.setAttribute("pause", "true"); elem.pause() } else if(buttonStorageValue == 'true'){ elem.setAttribute("pause", "false"); elem.play() } } } // TO check viewbility const isElementXPercentInViewport = function(el, percentVisible) { let rect = el.getBoundingClientRect(), windowHeight = (window.innerHeight || document.documentElement.clientHeight); return !( Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-rect.height) * 100)) < percentVisible || Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible ) }; // handle toggle autoplay function _handlegmAutoplayVideoBtnClick(value){ var vids = document.getElementsByTagName('video'); for( var i = 0; i < vids.length; i++ ){ var elem = vids.item(i); setVideoPlay(elem,value) } console.log('autoplay : '+value) } timer = setInterval(addVideoControl, 300);