// ==UserScript==
// @name Bangumi 首页条目名中文化
// @namespace org.upsuper.bangumi
// @grant none
// @include http://bangumi.tv/
// @include http://bangumi.tv/?*
// @include http://bangumi.tv/timeline*
// @include http://bangumi.tv/subject/*
// @exclude http://bangumi.tv/subject/*/*
// @include http://bangumi.tv/user/*/timeline*
// @include http://bgm.tv/
// @include http://bgm.tv/?*
// @include http://bgm.tv/timeline*
// @include http://bgm.tv/subject/*
// @exclude http://bgm.tv/subject/*/*
// @include http://bgm.tv/user/*/timeline*
// @include https://bgm.tv/
// @include https://bgm.tv/?*
// @include https://bgm.tv/timeline*
// @include https://bgm.tv/subject/*
// @exclude https://bgm.tv/subject/*/*
// @include https://bgm.tv/user/*/timeline*
// @include http://chii.in/
// @include http://chii.in/?*
// @include http://chii.in/timeline*
// @include http://chii.in/subject/*
// @exclude http://chii.in/subject/*/*
// @include http://chii.in/user/*/timeline*
// @version 5.2.4
// ==/UserScript==
(function() {
var localStorage = window.localStorage,
localPrefix = 'ChineseName_',
// displayMode: 0 => Display Chinese
// : 1 => Show Chinese as tip
displayMode = parseInt(localStorage[localPrefix + 'mode']);
function $(q) { return document.querySelector(q); }
function $a(q) { return document.querySelectorAll(q); }
function $c(t) { return document.createElement(t); }
function $t(t) { return document.createTextNode(t); }
String.prototype.u$format = function () {
var args = arguments;
return this.replace(/{(\d+)}/g, function (match, i) {
return args[i] !== undefined ? args[i] : match;
});
};
function isSubjectPage(str) {
return /\/subject\/\d+$/.test(str);
}
function parseChineseName(text) {
var re = /
中文名: <\/span>(.+?)<\/li>/;
var result = re.exec(text);
return result ? result[1] : '';
}
function setChineseName(id, ch) {
localStorage[localPrefix + id] = ch;
var event = new CustomEvent('_uChinese', {
detail: {subject_id: id, chinese: ch}
});
window.dispatchEvent(event);
}
if (isSubjectPage(location)) {
var id = location.href.split('/').pop();
setChineseName(id, parseChineseName(document.body.innerHTML));
return;
}
var titles;
function displayChineseName($anchors, callback) {
if (!titles) titles = {};
function triggerDisplayCallback($anchor, ch) {
setTimeout(function () { $anchor.u$displayCh(ch); });
}
function displayAll(id, ch) {
var $anchors = titles[id];
delete titles[id];
setChineseName(id, ch);
for (var i = 0; i < $anchors.length; i++)
triggerDisplayCallback($anchors[i], ch);
}
function queryChineseName(id, url) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200)
displayAll(id, parseChineseName(xhr.responseText));
};
xhr.open('GET', url, true);
xhr.send(null);
}
for (var i = 0; i < $anchors.length; i++) {
var $anchor = $anchors[i];
if (!isSubjectPage($anchor.href))
continue;
var id = $anchor.href.split('/').pop();
var ch = localStorage[localPrefix + id];
$anchor.u$displayCh = callback;
if (ch !== undefined) {
triggerDisplayCallback($anchor, ch);
} else {
if (!titles[id]) {
titles[id] = [];
queryChineseName(id, $anchor.href);
}
titles[id].push($anchor);
}
}
}
function updateTimeline(side) {
var $anchors;
var tlSel = side ? '#home_tml' : '#timeline';
$anchors = $a(tlSel + ' .info_sub>a.tip[href*="/subject/"]');
displayChineseName($anchors, function (ch) {
var origin = this.innerHTML;
if (!ch) return;
if (displayMode) {
this.title = ch;
if (!side)
this.innerHTML += ' ' + ch + '';
} else {
this.title = this.textContent;
if (side)
this.innerHTML = ch;
else
this.innerHTML = ch + ' ' + origin + '';
}
});
$anchors = $a(tlSel + ' .info>a.l[href*="/subject/"], ' +
tlSel + ' .info_full>a.l[href*="/subject/"]');
var alist = [];
for (var i = 0; i < $anchors.length; i++) {
var $anchor = $anchors[i];
if ($anchor.href.indexOf('doujin') < 0)
alist.push($anchor);
}
displayChineseName(alist, function (ch) {
if (!ch) return;
if (displayMode) {
this.title = ch;
} else {
this.title = this.textContent;
this.innerHTML = ch;
}
});
}
function updateManager() {
var $anchors = $a('#prgSubjectList>li>a.title');
var pattern = '#subjectPanel_{0} .tinyHeader>a[href^="/subject/"]',
pattern2 = '#subjectPanel_{0} .headerInner>h3>a',
pattern3 = '#prgSubjectList a.subjectItem[subject_id="{0}"]';
displayChineseName($anchors, function (ch) {
if (!ch) return;
var $span = this.getElementsByTagName('span')[0];
var id = this.attributes.subject_id.value;
var $a1 = $(pattern.u$format(id)),
$a2 = $(pattern2.u$format(id)),
$a3 = $(pattern3.u$format(id));
if (displayMode) {
this.title = ch;
$a1.title = ch;
$a2.title = ch;
} else {
$span.innerHTML = ch;
$a1.innerHTML = ch;
$a2.title = $a2.textContent;
$a2.innerHTML = ch;
var orig = $a3.dataset.originalTitle;
$a3.dataset.originalTitle =
'{0} {1}'.u$format(ch, orig.split(' ').pop());
}
});
}
function updateTopics() {
var $anchors = $a('#home_subject_tpc .grey>a');
displayChineseName($anchors, function (ch) {
if (!ch) return;
if (displayMode) {
this.title = ch;
} else {
this.title = this.textContent;
this.innerHTML = ch;
}
});
}
// insert style
var $style = $c('style');
$style.textContent = '\
#timeline .info_sub>a.tip>small { color: #aaa; } \
#timeline .info_sub>a.tip>small::before { content: "「"; } \
#timeline .info_sub>a.tip>small::after { content: "」"; }';
document.body.appendChild($style);
// create switcher
var $logout = $('#dock a[href*="/logout/"]'),
$dock = $logout.parentNode;
if ($logout) {
var $switcher = $c('a');
$switcher.href = '#';
$switcher.textContent = displayMode ? '◇' : '◆';
$switcher.addEventListener('click', function (e) {
e.preventDefault();
localStorage[localPrefix + 'mode'] = !displayMode ? 1 : 0;
location.href = location.href;
});
$dock.insertBefore($switcher, $logout);
$dock.insertBefore($t(' | '), $logout);
}
// update timeline
var $tmlContent = $('#tmlContent');
if ($tmlContent) {
$tmlContent.addEventListener('DOMSubtreeModified', function (e) {
if (e.target.id == 'tmlContent')
updateTimeline(false);
});
updateTimeline(false);
} else {
updateTimeline(true);
}
// update ep manager && topics
updateManager();
updateTopics();
})();