YouTube SparkBars(Like/Dislike)

動画へのリンクに「高く評価」された比率を示すバーを表示します。

当前为 2017-06-02 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        YouTube SparkBars(Like/Dislike)
// @namespace   knoa.jp
// @description 動画へのリンクに「高く評価」された比率を示すバーを表示します。
// @include     https://www.youtube.com/*
// @version     1
// @grant       none
// 多くが時間の無駄となる評価の低い動画を避ける手段を提供しないYouTubeのUIが悪い。
// とはいえYouTubeに過度な負荷は与えないように、動作させるページは必要最低限に。(homeは対象が多くて重い)
// Ajax追加要素への対応は保留。
// ==/UserScript==

(function () {
  const SCRIPTNAME = 'SparkBars';
  const DELAY = 1000;/*動画情報を読みに行く間隔(ms)(短すぎるとYouTubeに弾かれやすくなる)*/
  const VIEWS = {/*要素定義*/
    example: ['items', 'anchor', 'insertParent', 'insertAfter'],
    home: ['#feed ul > li.yt-shelf-grid-item', 'a', 'div.yt-lockup-content', 'div.yt-lockup-meta'],
    results: ['#results ol.item-section > li', 'div.yt-lockup-video a.yt-uix-tile-link', 'div.yt-lockup-meta', 'ul.yt-lockup-meta-info'],
    watch: ['#watch7-sidebar li.video-list-item', 'a.content-link', 'a.content-link', 'span.view-count'],
  };
  const SPARKBARS = 'div.video-extras-sparkbars';/*動画ページ内のSparkBar*/
  let href, view, items;
  let core = {
    initialize: function(){
      console.log(SCRIPTNAME, 'initialize...');
      window.setInterval(function(){
        if(href === location.href) return;/*URLが変わっていなければ何もしない*/
        href = location.href;
        /* URLに応じた定義で処理実施 */
        switch(true){
          case(href.match(/^https:\/\/www\.youtube\.com\/$/)!==null):
            view = VIEWS.home;
            break;
          case(href.match(/^https:\/\/www\.youtube\.com\/results\?/)!==null):
            view = VIEWS.results;
            break;
          case(href.match(/^https:\/\/www\.youtube\.com\/watch\?/)!==null):
            view = VIEWS.watch;
            break;
          default:
            return;
        }
        core.getSparkBars(10);
      }, 1000);
    },
    getSparkBars: function(retry){
      //console.log(SCRIPTNAME, 'getSparkBars...', view, href);
      /* 各動画リンクに対してひとつずつ処理 */
      items = document.querySelectorAll(view[0]);
      if((items === null || items.length === 0) && retry){/*動画が取得できなければリトライ*/
        window.setTimeout(function(){
          core.getSparkBars(retry--);
        }, 1000);
        return;
      }
      /*(delay)msずつずらして動画ページを読みに行く*/
      for(let i = 0, delay = 0; items[i]; i++){
        core.getSparkBar(items[i], delay += DELAY, href);
      }
    },
    getSparkBar: function(item, delay, href){
      //console.log(SCRIPTNAME, 'getSparkBar...', item);
      let a = item.querySelector(view[1]);
      if(a === null) return;/*動画へのリンクがなければ処理しない*/
      window.setTimeout(function(){
        if(href !== location.href) return;/*URLが変わっていれば処理は中止*/
        let xhr = new XMLHttpRequest();
        xhr.responseType = 'document';
        xhr.open('GET', a.href);
        xhr.onreadystatechange = function () {
          if (xhr.readyState == 4 && xhr.status == 200) {
            if(href !== location.href) return;/*URLが変わっていれば処理は中止*/
            let sparkbars = xhr.response.querySelector(SPARKBARS);
            if(sparkbars === null) return;/*コメントなしの動画は評価もなし*/
            item.querySelector(view[2]).insertBefore(sparkbars, item.querySelector(view[3]).nextElementSibling);
          }
        };
        xhr.send();
      }, delay);
    },
  };
  core.initialize();
}) ();