您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds “Keyword”, “Tags”, “My List”, “Images” and “Live” search tabs to all of the Niconico search boxes.
当前为
- // ==UserScript==
- // @name Append Tag Searching Tub
- // @name:ja niconico タグ検索タブを追加
- // @description Adds “Keyword”, “Tags”, “My List”, “Images” and “Live” search tabs to all of the Niconico search boxes.
- // @description:ja 『niconico』各サービスの検索窓について、「キーワード」「タグ」「マイリスト」「静画」「生放送」検索タブが5つとも含まれるように補完します。
- // @namespace http://loda.jp/script/
- // @version 5.2.0
- // @match https://www.nicovideo.jp/
- // @match https://www.nicovideo.jp/?*
- // @match https://www.nicovideo.jp/#*
- // @match https://www.nicovideo.jp/tag/*
- // @match https://www.nicovideo.jp/related_tag/*
- // @match https://www.nicovideo.jp/mylist*
- // @match https://www.nicovideo.jp/search/*
- // @match *://seiga.nicovideo.jp/*
- // @match https://live.nicovideo.jp/*
- // @match https://com.nicovideo.jp/*
- // @match *://blog.nicovideo.jp/en_info/*
- // @match *://tw.blog.nicovideo.jp/*
- // @require https://gitcdn.xyz/cdn/greasemonkey/gm4-polyfill/a834d46afcc7d6f6297829876423f58bb14a0d97/gm4-polyfill.js
- // @require https://greasyfork.org/scripts/17895/code/polyfill.js?version=625392
- // @require https://greasyfork.org/scripts/19616/code/utilities.js?version=230651
- // @require https://greasyfork.org/scripts/17896/code/start-script.js?version=112958
- // @license MPL-2.0
- // @compatible Edge 非推奨 / Deprecated
- // @compatible Firefox
- // @compatible Opera
- // @compatible Chrome
- // @grant GM.setValue
- // @grant GM_setValue
- // @grant GM.getValue
- // @grant GM_getValue
- // @grant GM.deleteValue
- // @grant GM_deleteValue
- // @grant GM.xmlHttpRequest
- // @grant GM_xmlhttpRequest
- // @connect www.nicovideo.jp
- // @run-at document-start
- // @icon data:image/vnd.microsoft.icon;base64,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
- // @author 100の人
- // @homepageURL https://greasyfork.org/scripts/268
- // ==/UserScript==
- 'use strict';
- // L10N
- Gettext.setLocalizedTexts({
- /*eslint-disable quote-props, max-len */
- 'en': {
- 'キーワード': 'Keyword',
- '動画をキーワードで検索': 'Search Video by Keyword',
- 'タグ': 'Tags',
- '動画をタグで検索': 'Search Video by Tag',
- 'マイリスト': 'My List',
- 'マイリストを検索': 'Search My List',
- '静画': 'Images',
- '静画を検索': 'Search Images',
- '生放送': 'Live',
- '番組を探す': 'Search Live Program',
- 'マンガ': 'Comics',
- },
- 'zh': {
- 'キーワード': '關鍵字',
- '動画をキーワードで検索': '',
- 'タグ': '標籤',
- '動画をタグで検索': '',
- 'マイリスト': '我的清單',
- 'マイリストを検索': '搜尋我的清單',
- '静画': '靜畫',
- '静画を検索': '搜尋靜畫',
- '生放送': '生放送',
- '番組を探す': '搜尋節目',
- 'マンガ': '漫畫',
- },
- /*eslint-enable quote-props, max-len */
- });
- /**
- * 追加したタブバーから新しいタブで検索結果を開いたとき、選択中のタブを元に戻す遅延時間 (ミリ秒)。
- * @constant {number}
- */
- const CURRENT_TAB_RESTORATION_DELAY = 1000;
- /**
- * 表示しているページの種類。
- * @type {string}
- */
- let pageType;
- // ページの種類を取得
- switch (location.host) {
- case 'www.nicovideo.jp':
- if (location.pathname === '/') {
- // 総合トップページ
- pageType = 'top';
- } else if (location.pathname.startsWith('/search/')) {
- // 動画キーワード検索ページ
- pageType = 'videoSearch';
- } else if (location.pathname.startsWith('/mylist_search')) {
- // マイリスト検索ページ
- pageType = 'mylist';
- } else if (/^\/(?:(?:tag|related_tag)\/|(?:mylist|recent|newarrival|openlist|video_catalog)(?:\/|$))/
- .test(location.pathname)) {
- // 動画タグ検索ページと公開マイリスト等
- pageType = 'tag';
- } else if (location.pathname.startsWith('/user/')) {
- // ユーザーページ
- pageType = 'user';
- }
- break;
- case 'seiga.nicovideo.jp':
- pageType = location.pathname.startsWith('/search/')
- // 静画検索ページ
- ? 'imageSearch'
- // 静画ページ
- : 'image';
- break;
- case 'live.nicovideo.jp':
- pageType = location.pathname.startsWith('/search')
- // 生放送検索ページ
- ? 'liveSearch'
- // 生放送ページ
- : 'live';
- break;
- case 'blog.nicovideo.jp':
- // 英語版ニコニコインフォ
- pageType = 'info_en';
- break;
- case 'tw.blog.nicovideo.jp':
- // 台湾版ニコニコインフォ
- pageType = 'info_tw';
- break;
- }
- // 上部メニューが追加されるまで待機
- let targetParentIdFirefox, isTargetFirefox;
- switch (pageType) {
- case 'imageSearch':
- case 'image':
- isTargetFirefox = target => target.id === 'wrapper';
- break;
- case 'liveSearch':
- targetParentIdFirefox = 'body_header';
- break;
- case 'info_en':
- targetParentIdFirefox = 'container-inner';
- break;
- case 'info_tw':
- targetParentIdFirefox = 'header';
- break;
- }
- startScript(
- prepare,
- parent => parent.classList.contains('siteHeaderGlovalNavigation'),
- target => target.id === 'siteHeaderLeftMenu',
- () => document.getElementById('siteHeaderLeftMenu'),
- {
- isTargetParent: targetParentIdFirefox
- ? parent => parent.id === targetParentIdFirefox
- : parent => parent.localName === 'body',
- isTarget: isTargetFirefox || (target => target.id === 'siteHeader'),
- }
- );
- /**
- * ページの種類別に、実行する関数を切り替える。
- */
- function prepare()
- {
- Gettext.setLocale(pageType === 'community'
- ? document.getElementById('siteHeaderNotification').dataset.nicoLocale.replace('_', '-')
- : document.documentElement.lang);
- if (pageType.startsWith('info_')) {
- // 英語版、または台湾版のニコニコインフォなら
- // 生放送へのリンクを取得
- const itemLive = document.querySelector('#siteHeader [href*="://live.nicovideo.jp/"]').parentElement;
- // 生放送リンクの複製
- const item = itemLive.cloneNode(true);
- // リンク文字を変更
- item.getElementsByTagName('span')[0].textContent = _('静画');
- // アドレスを変更
- item.getElementsByTagName('a')[0].href = 'https://seiga.nicovideo.jp/';
- // ヘッダに静画へのリンクを追加
- itemLive.before(item);
- return;
- }
- switch (pageType) {
- case 'videoSearch':
- // 動画キーワード
- startScript(
- addTagSearchTabAboveSearchBox,
- parent => parent.classList.contains('formSearch'),
- target => target.id === 'search_united_form',
- () => document.getElementById('search_united_form'),
- {
- isTargetParent: parent => parent.localName === 'body',
- isTarget: target => target.localName === 'section',
- }
- );
- break;
- case 'mylist':
- // マイリスト
- startScript(
- addTagSearchTabAboveSearchBox,
- parent => parent.id === 'form_search',
- target => target.id === 'search_united_form',
- () => document.getElementById('search_united_form'),
- {
- isTargetParent: parent => parent.id === 'PAGEMAIN',
- isTarget: target => target.id === 'PAGEBODY',
- }
- );
- break;
- case 'top':
- // トップページ
- addTagSearchButtonToTopPage();
- break;
- case 'imageSearch':
- // 静画キーワード
- startScript(
- addTagSearchTabAboveSearchBox,
- parent => parent.id === 'usearch_form',
- target => target.id === 'usearch_form_input',
- () => document.getElementById('usearch_form_input'),
- {
- isTargetParent: parent => parent.id === 'wrapper',
- isTarget: target => target.id === 'main',
- }
- );
- break;
- case 'image':
- // 静画
- startScript(
- careteTabsBarToSearchBox,
- parent => parent.id === 'head_search_form',
- target => target.id === 'search_button',
- () => document.getElementById('search_button'),
- {
- isTargetParent: parent => parent.id === 'header_block',
- isTarget: () => true,
- }
- );
- break;
- case 'liveSearch':
- // 生放送キーワード
- startScript(
- addTagSearchTabAboveSearchBox,
- parent => parent.classList.contains('search-input-area'),
- target => target.classList.contains('search-form'),
- () => document.getElementsByClassName('search-form')[0]
- );
- break;
- case 'live':
- // 生放送
- startScript(
- careteTabsBarToSearchBox,
- parent => parent.classList.contains('search_program'),
- target => target.classList.contains('search_word'),
- () => document.getElementsByClassName('search_word')[0],
- {
- isTargetParent: parent => parent.localName === 'body',
- isTarget: target => target.id === 'page_header',
- });
- break;
- case 'tag':
- if (document.doctype.publicId) {
- // 公開マイリスト等
- startScript(
- addOtherServiceTabsAboveSearchBox,
- parent => parent.id === 'search_tab',
- target => target.id === 'target_m',
- () => document.getElementById('target_m'),
- {
- isTargetParent: parent => parent.id === 'PAGEMAIN',
- isTarget: target => target.id === 'PAGEBODY',
- }
- );
- } else {
- // 動画タグ
- startScript(
- addOtherServiceTabsAboveSearchBox,
- parent => parent.classList.contains('videoSearchOption'),
- target => target.classList.contains('optMylist'),
- () => document.getElementsByClassName('optMylist')[0],
- {
- isTargetParent: parent => parent.localName === 'body',
- isTarget: target => target.localName === 'header',
- }
- );
- }
- break;
- case 'user':
- // ユーザー
- startScript(
- addImageLinkToUserPageMenu,
- parent => parent.localName === 'body',
- target => target.classList.contains('optionOuter'),
- () => document.getElementsByClassName('optionOuter')[0]
- );
- break;
- }
- }
- /**
- * 各サービスのキーワード検索ページの検索窓に、動画の「タグ」検索タブを追加する。
- * また、静画検索タブのスキーマをhttpsに変更する。
- */
- function addTagSearchTabAboveSearchBox()
- {
- // マイリスト検索タブの取得
- const mylistTab = document.querySelector('.tab_table td:nth-of-type(2), #search_frm_a a:nth-of-type(2), .search_tab_list li:nth-of-type(2), .seachFormA a:nth-of-type(2), li:nth-of-type(2).search-tab-item');
- // マイリスト検索タブの複製
- const tagTab = mylistTab.cloneNode(true);
- // タブ名を変更
- const anchor = tagTab.tagName.toLowerCase() === 'a' ? tagTab : tagTab.getElementsByTagName('a')[0];
- let tabNameNode = anchor.getElementsByTagName('div');
- tabNameNode = (tabNameNode.length > 0 ? tabNameNode[0].firstChild : anchor.firstChild);
- tabNameNode.data = _('タグ') + (pageType === 'liveSearch' ? '' : ' ( ');
- // クラス名を変更・動画件数をリセット
- const searchCount = tagTab.querySelector('strong, span');
- switch (pageType) {
- case 'videoSearch':
- searchCount.classList.remove('more');
- break;
- case 'mylist':
- searchCount.style.removeProperty('color');
- break;
- case 'imageSearch':
- searchCount.classList.remove('search_value_em');
- searchCount.classList.add('search_value');
- break;
- }
- searchCount.textContent = '-';
- if (searchCount.id) {
- // 生放送
- searchCount.id = 'search_count_tag';
- }
- // 検索語句を取得
- const searchWordsPattern = /(?:\/(?:search|tag|mylist_search)\/|[?&]keyword=)([^?&#]+)/g;
- const result = location.href.match(searchWordsPattern);
- const searchWords
- = result ? searchWordsPattern.exec(result[pageType === 'liveSearch' ? result.length - 1 : 0])[1] : '';
- // タグが付いた動画件数を取得・表示
- if (searchWords && location.host !== 'www.live.nicovideo.jp') {
- GM.xmlHttpRequest({
- method: 'GET',
- url: 'https://www.nicovideo.jp/tag/' + searchWords,
- onload: function (response) {
- const responseDocument = new DOMParser().parseFromString(response.responseText, 'text/html');
- const total = responseDocument.querySelector('.tagCaption .dataValue .num').textContent;
- const trimmedThousandsSep = total.replace(/,/g, '');
- if (trimmedThousandsSep >= 100) {
- // 動画件数が100件を超えていれば
- switch (pageType) {
- case 'videoSearch':
- searchCount.classList.add('more');
- break;
- case 'mylist':
- searchCount.style.color = '#CC0000';
- break;
- case 'imageSearch':
- searchCount.classList.remove('search_value');
- searchCount.classList.add('search_value_em');
- break;
- case 'liveSearch':
- searchCount.classList.add('strong');
- break;
- }
- }
- switch (pageType) {
- case 'mylist':
- searchCount.textContent = ' ' + total + ' ';
- break;
- case 'videoSearch':
- case 'imageSearch':
- searchCount.textContent = total;
- break;
- case 'liveSearch':
- searchCount.textContent = trimmedThousandsSep;
- break;
- }
- },
- });
- }
- // 非アクティブタブを取得
- const inactiveTab = document.querySelector('.tab_0, .tab1, .search_tab_list a:not(.active), .search-tab-anchor');
- // クラス名を変更
- anchor.className = inactiveTab.className;
- // アドレスを変更
- anchor.href = 'https://www.nicovideo.jp/tag/' + searchWords + inactiveTab.search;
- // タグ検索タブを追加
- mylistTab.parentNode.insertBefore(tagTab, mylistTab);
- if (pageType === 'liveSearch') {
- mylistTab.parentNode.insertBefore(new Text(' '), mylistTab);
- } else if (inactiveTab.classList.contains('tab1')) {
- // GINZAバージョン
- mylistTab.parentNode.insertBefore(tagTab.previousSibling.cloneNode(true), mylistTab);
- }
- // 静画検索タブのスキーマをhttpsに変更
- for (const anchor of mylistTab.parentNode.querySelectorAll('[href^="http://"]')) {
- anchor.protocol = 'https';
- }
- }
- /**
- * ニコニコ動画の上部に表示されている検索窓に、「静画」「生放送」を検索するタブを追加する。
- */
- function addOtherServiceTabsAboveSearchBox()
- {
- // スタイルの設定
- document.head.insertAdjacentHTML('beforeend', `<style>
- :root {
- --max-search-box-width: 268px;
- }
- #PAGEHEADER > div {
- display: flex;
- }
- #head_search {
- max-width: var(--max-search-box-width);
- flex-grow: 1;
- }
- #search_input {
- width: 100%;
- display: flex;
- }
- #search_input .typeText {
- flex-grow: 1;
- }
- #head_ads {
- margin-right: -26px;
- }
- #search_input #bar_search {
- box-sizing: border-box;
- width: 100% !important;
- }
- /*====================================
- GINZAバージョン
- */
- .siteHeader > .inner {
- display: flex;
- }
- .videoSearch {
- max-width: var(--max-search-box-width);
- flex-grow: 1;
- padding-left: 4px;
- padding-right: 4px;
- }
- .videoSearchOption {
- display: flex;
- white-space: nowrap;
- }
- .videoSearch form {
- display: flex;
- }
- .videoSearch form .inputText {
- flex-grow: 1;
- }
- /*------------------------------------
- ×ボタン
- */
- .clear-button-inner-tag {
- left: initial;
- right: 3px;
- }
- </style>`);
- // タブリストの取得
- const mylistTab = document.querySelector('#target_t, .optMylist');
- // タブの複製・追加
- mylistTab.parentElement.append(...[
- {
- type: 'image',
- title: _('静画を検索'),
- url: 'https://seiga.nicovideo.jp/search',
- text: _('静画'),
- },
- {
- type: 'live',
- title: _('番組を探す'),
- url: 'https://live.nicovideo.jp/search',
- text: _('生放送'),
- },
- ].map(function (option) {
- const tab = mylistTab.cloneNode(true);
- if (mylistTab.classList.contains('optMylist')) {
- // GINZAバージョン
- tab.classList.remove('optMylist');
- tab.classList.add('opt' + option.type[0].toUpperCase() + option.type.slice(1));
- tab.dataset.type = option.type;
- tab.getElementsByTagName('a')[0].textContent = option.text;
- } else {
- // 公開マイリスト等
- tab.id = 'target_' + option.type[0];
- tab.title = option.title;
- tab.setAttribute('onclick', tab.getAttribute('onclick').replace(/'.+?'/, '\'' + option.url + '\''));
- tab.textContent = option.text;
- }
- return tab;
- }));
- GreasemonkeyUtils.executeOnUnsafeContext(/* global Nico */ function () {
- eval('Nico.Navigation.HeaderSearch.Controller.search = '
- + Nico.Navigation.HeaderSearch.Controller.search.toString().replace(/(switch.+?{[^}]+)/, `$1;
- break;
- case "image":
- d = "https://seiga.nicovideo.jp/search/" + e;
- break;
- case "live":
- d = "https://live.nicovideo.jp/search/" + e;
- break;
- `));
- });
- }
- /**
- * 静画・生放送の上部に表示されている検索窓に、「動画キーワード」「動画タグ」「マイリスト」「静画」「生放送」を検索するタブバーを設置する。
- */
- function careteTabsBarToSearchBox()
- {
- // スタイルの設定
- document.head.insertAdjacentHTML('beforeend', `<style>
- #sg_search_box {
- /* 静画 */
- margin-top: 0.2em;
- }
- #live_header div.score_search { /* 生放送マイページ向けに詳細度を大きくしている */
- /* 生放送 */
- top: initial;
- }
- /*------------------------------------
- タブバー
- */
- [action$="search"] > ul {
- display: flex;
- /* 生放送 */
- font-size: 12px;
- }
- /* 静画 */
- #head_search_form > ul {
- margin-left: 1.3em;
- /* マンガ・電子書籍 */
- line-height: 1.4em;
- }
- #head_search_form > ul:hover ~ .search_form_text {
- border-color: #999;
- }
- /*------------------------------------
- タブ
- */
- [action$="search"] > ul > li {
- margin-left: 0.2em;
- white-space: nowrap;
- }
- [action$="search"] > ul > li > a {
- background: lightgrey;
- padding: 0.2em 0.3em 0.1em;
- color: inherit;
- /* 生放送 */
- text-decoration: none;
- }
- #head_search_form > ul > li > a:hover {
- /* 静画 */
- text-decoration: none;
- }
- /*------------------------------------
- 選択中のタブ
- */
- [action$="search"] > ul > li.current > a {
- color: white;
- background: dimgray;
- }
- </style>`);
- /**
- * 静画検索のtargetパラメータの値。
- * @type {string}
- */
- let imageSearchParamValue = 'illust';
- const form = document.querySelector('[action$="search"]');
- const textField = form[pageType === 'image' ? 'q' : 'keyword'];
- if (pageType === 'image') {
- // 静画の場合
- const pathnameParts = document.querySelector('#logo > h1 > a').pathname.split('/');
- switch (pathnameParts[1]) {
- case 'manga':
- imageSearchParamValue = 'manga';
- break;
- case 'book':
- imageSearchParamValue = pathnameParts[2] === 'r18' ? 'book_r18' : 'book';
- break;
- }
- }
- form.insertAdjacentHTML('afterbegin', `<ul>
- <li>
- <a href="https://www.nicovideo.jp/search/" title="${h(_('動画をキーワードで検索'))}">${h(_('キーワード'))}</a>
- </li>
- <li>
- <a href="https://www.nicovideo.jp/tag/" title="${h(_('動画をタグで検索'))}">${h(_('タグ'))}</a>
- </li>
- <li>
- <a href="https://www.nicovideo.jp/mylist_search/" title="${h(_('マイリストを検索'))}">${h(_('マイリスト'))}</a>
- </li>
- <li${pageType === 'image' ? ' class="current"' : ''}>
- <a href="https://seiga.nicovideo.jp/search/?target=${imageSearchParamValue}"
- title="${h(textField.defaultValue)}">${h(_('静画'))}</a>
- </li>
- <li${pageType === 'live' ? ' class="current"' : ''}>
- <a href="https://live.nicovideo.jp/search/" title="' + h(_('番組を探す')) + '">${h(_('生放送'))}</a>
- </li>
- </ul>`);
- const defaultCurrentTabAnchor = form.querySelector('.current a');
- document.addEventListener('click', function (event) {
- if (event.button !== 2 && event.target.matches('[action$="search"] > ul > li > a')) {
- // タブが副ボタン以外でクリックされたとき
- let searchWord = textField.value.trim();
- if (pageType === 'image' && textField.value === textField.defaultValue) {
- // 静画の場合、検索窓の値が既定値と一致していれば空欄とみなす
- searchWord = '';
- }
- if (searchWord) {
- // 検索語句が入力されていれば
- switchTab(event.target);
- event.target.pathname = event.target.pathname.replace(/[^/]*$/, encodeURIComponent(searchWord));
- setTimeout(function () {
- // リンク先を新しいタブで開いたとき
- switchTab(defaultCurrentTabAnchor);
- }, CURRENT_TAB_RESTORATION_DELAY);
- } else {
- // 検索語句が未入力なら
- event.preventDefault();
- if (event.button === 0) {
- // 主ボタンでクリックされていれば
- switchTab(event.target);
- }
- }
- }
- });
- // TabSubmitをインストールしているとマウスボタンを取得できず、中クリック時にも同じタブで検索してしまうため分割
- form.addEventListener('click', function (event) {
- if (event.target.type === (pageType === 'image' ? 'image' : 'submit')) {
- // 送信ボタンをクリックしたとき
- const searchWord = textField.value !== textField.defaultValue && textField.value.trim();
- if (searchWord) {
- event.stopPropagation();
- event.preventDefault();
- const anchor = form.querySelector('.current a');
- anchor.pathname = anchor.pathname.replace(/[^/]*$/, encodeURIComponent(searchWord));
- location.assign(anchor.href);
- }
- }
- }, true);
- addEventListener('pageshow', function (event) {
- if (event.persisted) {
- // 履歴にキャッシュされたページを再表示したとき
- switchTab(defaultCurrentTabAnchor);
- }
- });
- /**
- * 選択しているタブを切り替える。
- * @param {HTMLAnchorElement} target - 切り替え先のタブのリンク。
- */
- function switchTab(target) {
- form.getElementsByClassName('current')[0].classList.remove('current');
- target.parentElement.classList.add('current');
- if (pageType === 'image') {
- // 静画
- if (textField.defaultValue === textField.value) {
- // 検索語句が未入力なら
- textField.defaultValue = textField.value = target.title;
- } else {
- // 検索語句が入力されていれば
- textField.defaultValue = target.title;
- }
- } else {
- // 生放送
- textField.placeholder = target.title;
- }
- }
- }
- /**
- * 総合トップページの検索窓に、動画「タブ」「マイリスト」検索ボタンを追加する。
- */
- function addTagSearchButtonToTopPage()
- {
- // スタイルの設定
- document.head.insertAdjacentHTML('beforeend', `<style>
- .CrossSearch {
- display: flex;
- margin-right: 1em;
- }
- .CrossSearch-services {
- display: flex;
- }
- .CrossSearch-service {
- width: unset;
- padding: 0 0.5em;
- white-space: nowrap;
- }
- .CrossSearch-form {
- width: unset;
- }
- </style>`);
- // 静画検索ボタンの取得
- const refItem = document.querySelector('.CrossSearch-service[data-service="seiga"]');
- refItem.dataset.baseUrl = refItem.dataset.baseUrl.replace('http://', 'https://');
- const tagItem = refItem.cloneNode(true);
- tagItem.textContent = _('タグ');
- tagItem.dataset.service = 'tag';
- tagItem.dataset.baseUrl = 'https://www.nicovideo.jp/tag/';
- refItem.before(tagItem);
- const mylist = refItem.cloneNode(true);
- mylist.textContent = _('マイリスト');
- mylist.dataset.service = 'mylist';
- mylist.dataset.baseUrl = 'https://www.nicovideo.jp/mylist_search/';
- refItem.before(mylist);
- }
- /**
- * ユーザーページ左側のメニューに、静画へのリンクを追加する。
- */
- function addImageLinkToUserPageMenu()
- {
- // スタイルの設定
- document.head.insertAdjacentHTML('beforeend', `<style>
- .sidebar ul li.imageTab a span {
- width: 22px;
- height: 20px;
- background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAUCAQAAAAjdQW7AAAA/ElEQVQoz9WRzU3EMBCFv3EibRN2CyDtLiJJIRSSQlIIhSQgscDWYDeBhGc4ZJf87YErzwdr5M9vnmbEmCvz2FudMQSG12a3eBWbgcdOKgt4wwBJxM/mJnzorNKAX3Y6y7wqL+iz1uZ1ATocS5UjmmtbeQqSXGT1nX2Xa/WKzQ5IcsNbs3LOWDW5yu/t4umJdYxjr0EnJElUNIjXxEal1mPbMVPBqYG7aOC/2K1gl9FZUuXQ3/dKRsNDt3G2xf7M6zW/F8+t0V1l5KlIbFKXJRldZ0OSG97bDVwMBPF5WgWSJPJybrfTEGPffft8mYhQQPpoC25JjL/L8f/gH1eMbYCeUydgAAAAAElFTkSuQmCC");
- }
- </style>`);
- const nextItem = document.getElementsByClassName('stampTab')[0];
- const item = nextItem.cloneNode(true);
- const classList = item.classList;
- classList.remove('stampTab', 'active');
- classList.add('imageTab');
- const anchor = item.getElementsByTagName('a')[0];
- anchor.href = 'https://seiga.nicovideo.jp/user/illust/' + /[0-9]+/.exec(anchor.pathname)[0];
- anchor.lastChild.data = _('静画');
- nextItem.prepend(item);
- }