Greasy Fork is available in English.

YouTube SparkBars (Like/Dislike Rating)

It shows SparkBars whitch represents Like/Dislike Rating ratio.

Mint 2017.07.13.. Lásd a legutóbbi verzió

// ==UserScript==
// @name        YouTube SparkBars (Like/Dislike Rating)
// @namespace   knoa.jp
// @description It shows SparkBars whitch represents Like/Dislike Rating ratio.
// @description 動画へのリンクに「高く評価」された比率を示すバーを表示します。
// @include     https://www.youtube.com/*
// @version     2.0.0
// @grant       none
// en:
// API limits 1M queries/day. (approximately 100 views by 10,000 users.)
// You can use your own APIKEY to support this script.
// https://console.developers.google.com/apis/
// It doesn't support Ajax additional videos yet.
// ja:
// APIの制限は1日あたり100万クエリ(1万ユーザーなら1人あたり100ビュー)です。
// 各自でAPIKEYを書き換えてくれるとスクリプトの寿命が延びます。
// https://console.developers.google.com/apis/
// Ajax追加要素への対応は保留。

// ==/UserScript==

(function () {
  const SCRIPTNAME = 'YouTubeSparkBars';
  const DEBUG = true;
  console.time(SCRIPTNAME);
  const MAXRESULTS = 24;/* API limits 50 videos per request */
  const APIKEY = 'AIzaSyAyOgssM7s_vvOUDV0ZTRvk6LrTwr_1f5k';
  const API = 'https://www.googleapis.com/youtube/v3/videos?id={VIDEOIDS}&part=statistics&fields=items(id,statistics)&maxResults=' + MAXRESULTS + '&key=' + APIKEY;
  const VIEWS = {/* querySelectors on each views */
    example: ['items', 'anchor[href]', 'insertParent', 'insertAfter'],
    home: ['#feed ul > li.yt-shelf-grid-item', 'a', 'div.yt-lockup-content', 'div.yt-lockup-meta'],
    results: ['ol.item-section > li', 'div.yt-lockup-video a.yt-uix-tile-link[href]', 'div.yt-lockup-meta', 'ul.yt-lockup-meta-info'],
    watch: ['li.video-list-item', 'a.content-link[href]', 'a.content-link', 'span.view-count'],
  };
  const SPARKBARS = '<div class="video-extras-sparkbars"><div class="video-extras-sparkbar-likes" style="width: {LIKES}%"></div><div class="video-extras-sparkbar-dislikes" style="width: {DISLIKES}%"></div></div>';/* SparkBar in video pages */
  let view;
  let core = {
    initialize: function(){
      window.addEventListener('load', core.getSparkBars);
      window.addEventListener('spfdone', core.getSparkBars);
    },
    getSparkBars: function(){
      switch(true){
        case(location.href === 'https://www.youtube.com/'):
          view = VIEWS.home;
          break;
        case(location.href.startsWith('https://www.youtube.com/results?')):
          view = VIEWS.results;
          break;
        case(location.href.startsWith('https://www.youtube.com/watch?')):
          view = VIEWS.watch;
          break;
        default:
          return;
      }
      let items = document.querySelectorAll(view[0]);
      if(items === null || items.length === 0) return;
      let videoids = [];
      for(let i = 0; items[i]; i++){
        try{
          let id = items[i].querySelector(view[1]).href.match(/\?v=([^&]+)/)[1];
          videoids.push(id);
          items[i].dataset.videoid = id;
        }catch(e){
          continue;
        }
      }
      videoids.length = Math.min(videoids.length, MAXRESULTS);
      let xhr = new XMLHttpRequest();
      xhr.responseType = 'json';
      xhr.open('GET', API.replace('{VIDEOIDS}', videoids.join()));
      xhr.onreadystatechange = function () {
        if(xhr.readyState !== 4 || xhr.status !== 200) return;
        if(!xhr.response.items) return;
        let bars = {};
        for(let i = 0; xhr.response.items[i]; i++){
          let v = xhr.response.items[i], s = v.statistics;
          if(!s.likeCount && !s.dislikeCount) continue;
          bars[v.id] = SPARKBARS;
          bars[v.id] = bars[v.id].replace('{LIKES}', (100 * parseInt(s.likeCount)) / (parseInt(s.likeCount) + parseInt(s.dislikeCount)));
          bars[v.id] = bars[v.id].replace('{DISLIKES}', (100 * parseInt(s.dislikeCount)) / (parseInt(s.likeCount) + parseInt(s.dislikeCount)));
        }
        for(let i = 0; items[i]; i++){
          if(!bars[items[i].dataset.videoid]) continue;
          let div = document.createElement('div');
          div.innerHTML = bars[items[i].dataset.videoid];
          items[i].querySelector(view[2]).insertBefore(div, items[i].querySelector(view[3]).nextElementSibling);
        }
      };
      xhr.send();
    },
  };
  let log = (DEBUG) ? function(){
    let l = log.last = log.now || new Date(), n = log.now = new Date();
    console.log.bind(null,
      SCRIPTNAME + ':',
      /* 00:00:00.000 */ n.toLocaleTimeString() + '.' + n.getTime().toString().slice(-3),
      /* +0.000s      */ '+' + ((n-l)/1000).toFixed(3) + 's',
      /* :00          */ ':' + new Error().stack.match(/:[0-9]+:[0-9]+/g)[1].split(':')[1],/*LINE*/
      /* caller       */ log.caller ? log.caller.name : '',
    ).apply(null, arguments);
  } : function(){};
  core.initialize();
  console.timeEnd(SCRIPTNAME);
})();