youtube HTML5 Auto Loop

youtubeHTML5プレイヤー再生時に自動ループする

Ekde 2017/09/30. Vidu La ĝisdata versio.

// ==UserScript==
// @name           youtube HTML5 Auto Loop
// @namespace      youtube HTML5 Auto Loop
// @grant          none
// @description    youtubeHTML5プレイヤー再生時に自動ループする
// @author         TNB
// @match          *://*.youtube.com/*
// @version        1.2
// ==/UserScript==

var loop_off = {
  when_enable_next_video_autoplay: false,
  when_playlist: false,
  with_embedded_video: false
};

var YoutubeHTML5AutoLoop = {
  loop: true,
  eventCache: {},
  timeout: 15,
  disconnect: function(timer, cnt) {
    if (cnt > this.timeout) {
      clearInterval(timer);
    }
  },
  isLoop: function() {
    var ele = {when_enable_next_video_autoplay:'#toggle[aria-pressed="true"]', when_playlist:'#playlist:not([hidden])', with_embedded_video:'html[dir]'};
    for (var i in loop_off) {
      var target = document.querySelector(ele[i]);
      if (loop_off[i]) {
        if (i == 'when_enable_next_video_autoplay') {
          var toggle = document.querySelector('#toggle[toggles]');
          if (toggle) toggle.addEventListener('click', this, false);
        }
        if (target) {
          return false;
        }
      }
    }
    return true;
  },
  init: function() {
    var timer,
        cnt = 0;
    timer = setInterval(() => {
      if (document.getElementById('items') || document.querySelector('html[dir]')) {
        this.loop = this.isLoop();
        this.loopOn();
        clearInterval(timer);
      }
      this.disconnect(timer, cnt);
      cnt++;
    }, 200);
    this.addListener();
  },
  loopOn: function() {
    var video = document.getElementsByTagName('video')[0];
    if (video) {
      if (this.loop) {
        video.setAttribute('loop', '');
      } else {
        video.removeAttribute('loop');
      }
    }
  },
  loopToggle: function() {
    this.loop = this.loop? false: true;
    this.loopOn();
  },
  loopDisplay: function() {
    var video = document.querySelector('video:hover');
    if (video) {
      var checkBox = document.querySelector('.ytp-contextmenu [aria-checked]');
      checkBox.setAttribute('aria-checked', this.loop);
      if (!this.eventCache.addLoopToggle) {
        checkBox.addEventListener('click', this, false);
        this.eventCache.addLoopToggle = true;
      }
    }
  },
  watchAjax: function() {
    var timer,
        cnt = 0;
    timer = setInterval(() => {
      var video = document.getElementsByTagName('video')[0];
      if (video) {
        var ev = new CustomEvent('completedRequest'),
            mo = new MutationObserver(function(){window.dispatchEvent(ev)});
        mo.observe(video, {attributes: true, attributeFilter: ['style', 'src']});
        clearInterval(timer);
      }
      this.disconnect(timer, cnt);
      cnt++;
    }, 200);
  },
  addListener: function() {
    if (!this.eventCache.loadEvent) {
      window.addEventListener('load', this, false);
      window.addEventListener('contextmenu', this, false);
      window.addEventListener('completedRequest', this, false);
      this.eventCache.loadEvent = true;
    }
  },
  handleEvent: function(e) {
    switch(e.type) {
      case 'load':
        this.watchAjax();
        break;
      case 'contextmenu':
        this.loopDisplay();
        break;
      case 'click':
        this.loopToggle();
        break;
      case 'completedRequest':
        this.init();
        break;
    }
  }
};

YoutubeHTML5AutoLoop.init();