ニコニコ生放送の検索結果と「放送中の番組」ページにおいて、ページ送りボタンを上部にも表示 / Also shows the pagination on the top of Nico Live search result and Lives by Category page.
当前为
// ==UserScript==
// @name Clone Turning Page Button in nicovideo
// @namespace http://pc12.2ch.net/test/read.cgi/streaming/1275642556/
// @version 3.3.0
// @description ニコニコ生放送の検索結果と「放送中の番組」ページにおいて、ページ送りボタンを上部にも表示 / Also shows the pagination on the top of Nico Live search result and Lives by Category page.
// @match http://live.nicovideo.jp/search?*
// @match http://live.nicovideo.jp/recent
// @match http://live.nicovideo.jp/recent?*
// @match http://live.nicovideo.jp/recent#*
// @match http://watch.live.nicovideo.jp/search?*
// @match http://watch.live.nicovideo.jp/recent
// @match http://watch.live.nicovideo.jp/recent?*
// @match http://watch.live.nicovideo.jp/recent#*
// @run-at document-start
// @grant dummy
// @icon data:image/vnd.microsoft.icon;base64,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
// @author 100の人
// @homepage https://gf.qytechs.cn/ja/scripts/275-clone-turning-page-button-in-nicovideo
// @license Creative Commons Attribution 4.0 International Public License; http://creativecommons.org/licenses/by/4.0/
// ==/UserScript==
(function () {
'use strict';
switch (location.pathname) {
case '/search':
// ニコニコ生放送 検索結果
startScript(function () {
var pager = document.getElementsByClassName('pager')[0];
if (pager) {
// 41件以上ヒットしていれば
// スタイルシートの設定
document.head.insertAdjacentHTML('beforeend', '<style> \
.result_list { \
border-top: 1px solid #888888; \
} \
</style>');
// 数字リンクの複製
var ref = document.getElementsByClassName('result_list')[0];
ref.parentElement.insertBefore(pager.cloneNode(true), ref);
}
},
function (parent) { return parent.classList.contains('container'); },
function (target) { return target.id === 'search_right'; },
function () { return document.getElementById('search_right'); });
break;
case '/recent':
// ニコニコ生放送 放送中の番組
startScript(function () {
var parent = document.getElementById('onair_stream_list');
clonePager();
var observer = new MutationObserver(function (mutations) {
if (mutations[0].addedNodes.length > 1) {
// 数字リンクの複製でなければ
clonePager();
}
});
observer.observe(parent, {
childList: true,
});
function clonePager() {
parent.insertBefore(document.getElementById('pagerFrame').cloneNode(true), document.getElementById('userFrame'));
}
},
function (parent) { return parent.id === 'left'; },
function (target) { return target.id === 'pickupFrame'; },
function () { return document.getElementById('pickupFrame'); });
break;
}
/**
* 挿入された節の親節が、目印となる節の親節か否かを返すコールバック関数。
* @callback isTargetParent
* @param {(Document|Element)} parent
* @returns {boolean}
*/
/**
* 挿入された節が、目印となる節か否かを返すコールバック関数。
* @callback isTarget
* @param {(DocumentType|Element)} target
* @returns {boolean}
*/
/**
* 目印となる節が文書に存在するか否かを返すコールバック関数。
* @callback existsTarget
* @returns {boolean}
*/
/**
* 目印となる節が挿入された直後に関数を実行する。
* @param {Function} main - 実行する関数。
* @param {isTargetParent} isTargetParent
* @param {isTarget} isTarget
* @param {existsTarget} existsTarget
* @param {Object} [callbacksForFirefox]
* @param {isTargetParent} [callbacksForFirefox.isTargetParent] - Firefoxにおける{@link isTargetParent}。
* @param {isTarget} [callbacksForFirefox.isTarget] - Firefoxにおける{@link isTarget}。
* @param {boolean} [timeoutSinceStopParsingDocument=0] - DOM構築完了後に監視を続けるミリ秒数。
* @version 2014-07-06
*/
function startScript(main, isTargetParent, isTarget, existsTarget) {
/**
* {@link checkExistingTarget}で{@link startMain}を実行する間隔(ミリ秒)。
* @constant {number}
*/
var INTERVAL = 10;
/**
* {@link checkExistingTarget}で{@link startMain}を実行する回数。
* @constant {number}
*/
var LIMIT = 500;
/**
* 実行済みなら真。
* @type {boolean}
*/
var alreadyCalled = false;
// 指定した節が既に存在していれば、即実行
startMain();
if (alreadyCalled) {
return;
}
// FirefoxのMutationObserverは、HTMLのDOM構築に関して要素をまとめて挿入したと見なすため、isTargetParent、isTargetを変更
var callbacksForFirefox = arguments[4];
if (callbacksForFirefox && typeof sidebar !== 'undefined') {
if (callbacksForFirefox.isTargetParent) {
isTargetParent = callbacksForFirefox.isTargetParent;
}
if (callbacksForFirefox.isTarget) {
isTarget = callbacksForFirefox.isTarget;
}
}
var observer = new MutationObserver(mutationCallback);
observer.observe(document, {
childList: true,
subtree: true,
});
var timeoutSinceStopParsingDocument = arguments[5] || 0;
if (document.readyState === 'complete') {
// DOMの構築が完了していれば
onDOMContentLoaded();
} else {
document.addEventListener('DOMContentLoaded', onDOMContentLoaded);
}
/**
* {@link startMain}を実行し、スクリプトが開始されていなければさらに{@link timeoutSinceStopParsingDocument}ミリ秒待機し、
* スクリプトが開始されていなければ{@link stopObserving}を実行する。
*/
function onDOMContentLoaded() {
startMain();
if (timeoutSinceStopParsingDocument === 0) {
if (!alreadyCalled) {
stopObserving();
}
} else {
window.setTimeout(function () {
if (!alreadyCalled) {
stopObserving();
}
}, timeoutSinceStopParsingDocument);
}
}
/**
* 目印となる節が挿入されたら、監視を停止し、{@link checkExistingTarget}を実行する。
* @param {MutationRecord[]} mutations - A list of MutationRecord objects.
* @param {MutationObserver} observer - The constructed MutationObserver object.
*/
function mutationCallback(mutations, observer) {
var mutation, target, nodeType, addedNodes, addedNode, i, j, l, l2;
for (i = 0, l = mutations.length; i < l; i++) {
mutation = mutations[i];
target = mutation.target;
nodeType = target.nodeType;
if ((nodeType === Node.ELEMENT_NODE) && isTargetParent(target)) {
// 子が追加された節が要素節で、かつその節についてisTargetParentが真を返せば
addedNodes = Array.prototype.slice.call(mutation.addedNodes);
for (j = 0, l2 = addedNodes.length; j < l2; j++) {
addedNode = addedNodes[j];
nodeType = addedNode.nodeType;
if ((nodeType === Node.ELEMENT_NODE) && isTarget(addedNode)) {
// 追加された子が要素節で、かつその節についてisTargetが真を返せば
observer.disconnect();
checkExistingTarget(0);
return;
}
}
}
}
}
/**
* {@link startMain}を実行し、スクリプトが開始されていなければ再度実行。
* @param {number} count - {@link startMain}を実行した回数。
*/
function checkExistingTarget(count) {
startMain();
if (!alreadyCalled && count < LIMIT) {
window.setTimeout(checkExistingTarget, INTERVAL, count + 1);
}
}
/**
* 指定した節が存在するか確認し、存在すれば{@link stopObserving}を実行しスクリプトを開始。
*/
function startMain() {
if (!alreadyCalled && existsTarget()) {
stopObserving();
main();
}
}
/**
* 監視を停止する。
*/
function stopObserving() {
alreadyCalled = true;
if (observer) {
observer.disconnect();
}
document.removeEventListener('DOMContentLoaded', onDOMContentLoaded);
}
}
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址