9gag show video control

add video controls to 9gag gif and video post. Add volume slider on chrome browser

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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);