Greasy Fork is available in English.
It shows SparkBars whitch represents Like/Dislike Rating ratio.
当前为
// ==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);
})();