// ==UserScript== // @name pixiv Tabs Restorer // @name:ja pixiv タブを復活 // @description Adds “All”, “Follow”, “My pixiv”, and “Tag Index” tabs to user pages etc. and “All” and “Ugoira” tabs to search result pages. // @description:ja ユーザーページなどに「すべて」「フォロー」「マイピク」「タグ一覧」タブを、検索結果に「すべて」「うごイラ」タブを補完します。 // @namespace https://greasyfork.org/users/137 // @version 2.0.0 // @match https://www.pixiv.net/* // @require https://greasyfork.org/scripts/19616/code/utilities.js?version=752462 // @require https://greasyfork.org/scripts/17896/code/start-script.js?version=112958 // @license MPL-2.0 // @contributionURL https://www.amazon.co.jp/registry/wishlist/E7PJ5C3K7AM2 // @compatible Edge 最新安定版 / Latest stable (非推奨 / Deprecated) // @compatible Firefox // @compatible Opera // @compatible Chrome // @grant dummy // @noframes // @run-at document-start // @icon data:image/png;base64,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 // @author 100の人 // @homepageURL https://greasyfork.org/scripts/373026 // @downloadURL none // ==/UserScript== // 当スクリプトはpixivが作成、配布しているアプリケーションではありません。 // 'use strict'; // L10N Gettext.setLocalizedTexts({ /*eslint-disable quote-props, max-len */ 'en': { 'すべて': 'All', 'フォロー': 'Follow', 'マイピク': 'My pixiv', 'タグ一覧': 'Tag Index', 'うごイラ': 'Ugoira', }, 'ko': { 'すべて': '전체', 'フォロー': '팔로우', 'マイピク': '마이픽', 'タグ一覧': '태그 목록', 'うごイラ': '움직이는 일러스트', }, 'zh': { 'すべて': '全部', 'フォロー': '关注', 'マイピク': '好P友', 'タグ一覧': '标签一览', 'うごイラ': '动图', }, 'zh-tw': { 'すべて': '全部', 'フォロー': '關注', 'マイピク': '好P友', 'タグ一覧': '標籤一覽', 'うごイラ': '動圖', }, /*eslint-enable quote-props, max-len */ }); class TabCompleter { /** * @access private * @constant {number} */ static get URLS_AND_LABLES() {return { search: [ { path: 'artworks', label: _('すべて'), position: 1 }, { path: 'illustrations', type: 'ugoira', label: _('うごイラ'), position: 4 }, ], user: [ { path: '/member_illust.php', label: _('すべて'), position: 1 }, { path: '/bookmark.php', type: 'user', label: _('フォロー') }, { path: '/mypixiv_all.php', label: _('マイピク') }, { path: '/member_tag_all.php', label: _('タグ一覧') }, ], };} constructor() { const root = document.getElementById('root'); if (!root) { return; } Gettext.setLocale(document.documentElement.lang); addEventListener('click', event => { const tab = event.target.closest('a'); if (!tab || !tab.matches('#root > :not(header) nav > a')) { return; } if (event.defaultPrevented) { // 既存のタブ this.markCurrentTab(); return; } if (tab.getAttribute('href').startsWith('/') || !location.pathname.startsWith('/tags/') || location.pathname.endsWith('/novels')) { // 別サービスへのタブ return; } // イラスト検索結果ページで「すべて」「うごイラ」タブをクリックした場合 event.preventDefault(); // 検索オプションボタンをクリック document.querySelector('[d^="M0 1C0 0.447754"]').closest('button').click(); new MutationObserver(function (mutations, observer) { let dialog; for (const mutation of mutations) { dialog = Array.from(mutation.addedNodes).find( node => node.nodeType === Node.ELEMENT_NODE && node.getAttribute('role') === 'presentation' ); if (dialog) { break; } } if (!dialog) { return; } observer.disconnect(); dialog.hidden = true; // 対象 const input = dialog.querySelector('[class$="-dummyInput"]'); // プルダウンメニューを開く input.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: ' ' })); new MutationObserver(function (mutations, observer) { let select, options; mutations: for (const mutation of mutations) { for (const node of mutation.addedNodes) { options = node.querySelectorAll('[role="option"]'); if (options.length === 0) { continue; } select = node; break mutations; } } if (!select) { return; } observer.disconnect(); // 項目を選択する options[tab.pathname.endsWith('/artworks') ? /* すべて */0 : /* うごイラ */4].click(); new MutationObserver(function (mutations, observer) { if (!mutations.some(mutation => Array.from(mutation.removedNodes).includes(select))) { return; } observer.disconnect(); setTimeout(function () { // 「適用する」ボタンを押す dialog.querySelector('[type="submit"]').click(); this.markCurrentTab(); }, 100); }).observe(select.parentElement, { childList: true }); }).observe(dialog, { subtree: true, childList: true }); }).observe(document.body, { childList: true }); }); new MutationObserver(mutations => { for (const mutation of mutations) { if (mutation.target.matches('#root > div[class]')) { // 検索結果ページ if (!Array.from(mutation.addedNodes).some( node => node.nodeType === Node.ELEMENT_NODE && node.querySelector('nav > a[href^="/tags/"]') )) { continue; } this.complete(); return; } let findChild; if (mutation.target.matches('#root > div[class] > div[class]')) { findChild = node => node.localName === 'div' && node.hasAttribute('class'); } else if (mutation.target.matches('#root > div[class] > div[class] > div[class]')) { findChild = node => node.localName === 'nav'; } if (!findChild) { continue; } const parent = Array.from(mutation.addedNodes).find(findChild); if (parent) { if (parent.querySelector('[href*="/mypixiv_all.php?"]')) { return; } this.complete(); return; } } }).observe(root, {childList: true, subtree: true}); } markCurrentTab() { const currentTab = this.list.querySelector('[aria-current][href^="/"]'); const tabs = this.list.children; for (const tab of tabs) { if (tab.href === location.href) { tab.setAttribute('aria-current', 'page'); tab.classList.add(...this.currentTabClasses); } else { tab.removeAttribute('aria-current'); tab.classList.remove(...this.currentTabClasses); } } if (!this.list.querySelector('[aria-current]')) { currentTab.setAttribute('aria-current', 'page'); currentTab.classList.add(...this.currentTabClasses); } } /** * タブを補完します。 * @returns {Promise.} */ async complete() { /** * 各タブの共通の親要素。 * @member {HTMLElement} */ this.list = document.querySelector('#root > :not(header) nav'); if (this.list.querySelector('[href*="type=ugoira"], [href*="/member_tag_all.php"]')) { // すでに補完済みなら this.markCurrentTab(); return; } const tabs = this.list.children; if (!this.currentTabClasses) { const currentTab = this.list.querySelector('[aria-current="page"]'); const noCurrentTabClassList = Array.from(Array.from(tabs).find(tab => tab !== currentTab).classList); /** * カレントタブに設定されるクラス。 * @member {string[]} */ this.currentTabClasses = Array.from(currentTab.classList).filter(token => !noCurrentTabClassList.includes(token)); } const pageType = location.pathname.startsWith('/tags/') ? 'search' : 'user'; // 挿入するタブのテンプレートを作成 const templateTab = tabs[pageType === 'search' ? 1 : 0].cloneNode(true); templateTab.removeAttribute('aria-current'); templateTab.classList.remove(...this.currentTabClasses); const param = new URLSearchParams(templateTab.search); for (const { path, type, label, position } of TabCompleter.URLS_AND_LABLES[pageType]) { let tab; if (path === '/member_illust.php') { tab = document.querySelector('[href^="/member_illust.php?id="]:not([href*="type="])'); if (tab) { tab.classList = templateTab.classList; } } if (!tab) { tab = templateTab.cloneNode(true); } switch (pageType) { case 'search': tab.pathname = tab.pathname.replace(/[^/]+$/, path); tab.firstElementChild.textContent = label; break; case 'user': tab.pathname = path; tab.text = label; break; } if (type) { param.set('type', type); tab.search = param; } if (position) { tabs[position].before(tab); } else { this.list.append(tab); } } this.markCurrentTab(); } } document.addEventListener('DOMContentLoaded', function () { new TabCompleter(); }, { passive: true, once: true });