小説家になろう(厳密には小説を読もう)ランキングでのNGフィルタリング機能を提供
// ==UserScript==// @name Narou Ranking NG// @namespace https://greasyfork.org/ja/users/17828-amaicoffee// @version 1.7// @description 小説家になろう(厳密には小説を読もう)ランキングでのNGフィルタリング機能を提供// @author amaicoffee// @license MIT license// @match https://yomou.syosetu.com/rank/genrelist/type/*// @match https://yomou.syosetu.com/rank/list/type/*// @grant GM_addStyle// @grant GM_deleteValue// @grant GM_getValue// @grant GM_listValues// @grant GM_setValue// ==/UserScript==/*更新履歴v1.7予定している新機能追加に向け、機能そのままに手直し。v1.6ノードの設定ミスで正しく非表示にできていない問題の修正ver 1.5GM_addStyleを使って短く。可読性向上(順序入れ替え、注釈など)ver 1.4スクリプトの名前をNarou ranking ngからNarou Ranking NGに変更ver 1.3メニュー作成を目指してとりあえずNGセーブデータのエクスポート機能を実装。NGセーブデータボタン横にエクスポートボタンを追加。なおこれは暫定的な配置です。良くない配置のUIなのでメニュー実装までのつなぎです。エクスポートボタンを押すとコンソールにNGセーブデータが表示されます。コンソールはF12を押すことで見られます。後は適宜保存するなどお願いします。*//*ユーザースクリプトの説明注意!このスクリプトはJavaScript練習を兼ねたものです!小説を読もう!の「ジャンル別ランキング」「総合ランキング」ページで動作するスクリプトで、ランキング内、小説タイトル横に追加する「表示/非表示」ボタンを押すと、その小説はNGに登録され説明文が折りたたまれます。NG登録はGM setValueで保存され、ページ遷移に耐えます。登録したNGを消す方法は画面右下のフローティングボタン「delete ng data」を押して下さい。*/console.log(GM_listValues())// セーブデータ・読込キー// 現行const NAROU_NG_IDS_KEY = 'narou_ng_ids';/*// 下記に更新予定const NG_NOVEL_KEY = 'nrng_novel_ids;const NG_AUTHOR_KEY = 'nrng_author_ids;const NG_TAG_KEY = 'nrng_tags;*/// セーブデータ・ロード関数function load_savedata(key) {const DATA = GM_getValue(key);return DATA ? DATA.split(' ') : [];// 良くない書き方?}// セーブデータ・セーブ関数function save_savedata(key, array) {GM_setValue(key, array.join(' '));}function delete_savedata(key) {switch (key) {case NAROU_NG_IDS_KEY:if (window.confirm('NG小説IDを全削除しますか?')) {GM_deleteValue(key);window.alert('NG小説IDを全削除しました');}break;default:break;}}// ランキング内の小説をノードリストとして所得var ranking_list_nodelist = document.querySelectorAll('.ranking_list');// ランキング内小説ID配列とNG小説ID配列var ranked_id_arr = Array.from(document.querySelectorAll('.tl'), a => a.href.substring(26, 33));var ng_novel_ids_array = load_savedata(NAROU_NG_IDS_KEY)// スクリプトでNG小説を隠すのに使うCSS要素を作成して追加GM_addStyle('.censored { display: none; }')function toggle(num) {var target_classList = ranking_list_nodelist[num].childNodes[3].classList;var target_id = ranked_id_arr[num];if (target_classList.contains('censored')) {target_classList.remove('censored');ng_novel_ids_array = ng_novel_ids_array.filter(id => id != target_id);} else {target_classList.add('censored');ng_novel_ids_array.push(target_id);}console.log('NG小説ID一覧が更新されました。');console.log(ng_novel_ids_array);save_savedata(NAROU_NG_IDS_KEY, ng_novel_ids_array);}// NG登録ボタンを↑のリスト個数分つくって配列に追加var button_array = [];for (let i = 0; i < ranking_list_nodelist.length; i++) {button_array[i] = document.createElement('button');button_array[i].innerText = '非表示';button_array[i].addEventListener('click', function () { toggle(i); });// ループ内関数宣言は駄目らしい? 動いているが…ranking_list_nodelist[i].firstElementChild.appendChild(button_array[i]);}// メイン部分。ここどうにかならないものか// NG小説IDが見つかったときif (ng_novel_ids_array.length > 0) {console.log('保存されたNG小説IDが見つかりました。');console.log(ng_novel_ids_array.join(' '));let key_array = ng_novel_ids_array.slice();for (let i = 0; i < ranked_id_arr.length; i++) {for (let j = 0; j < key_array.length; j++) {let soeji = ranked_id_arr.indexOf(key_array[j]);if (soeji != -1) {ranking_list_nodelist[soeji].lastElementChild.classList.add('censored');key_array.splice(j, 1);}}}} else {console.log('保存されたNG小説IDは見つかりませんでした。');}// フロートNGメニューGM_addStyle('.floated { position: fixed; right: 0; bottom: 0; }')const FLOAT_NG_MENU = document.createElement('div');FLOAT_NG_MENU.classList.add('floated');document.body.appendChild(FLOAT_NG_MENU);const EXPORT_BUTTON = document.createElement('button');EXPORT_BUTTON.innerText = 'NGをエクスポート';EXPORT_BUTTON.addEventListener('click', function () {if (ng_novel_ids_array.length > 0) {console.log('下記がNG小説ID一覧です。')console.log(ng_novel_ids_array.join(' '));window.alert('NG小説ID一覧がエクスポートされました。')} else {window.alert('NG小説IDが見つかりません。')}});document.querySelector('.floated').appendChild(EXPORT_BUTTON);function hogehoge() {window.alert('hogehoge')}const DELETE_SAVE_DATA_BUTTON = document.createElement('button');DELETE_SAVE_DATA_BUTTON.innerText = 'NG全削除';DELETE_SAVE_DATA_BUTTON.addEventListener('click', function () { delete_savedata(NAROU_NG_IDS_KEY); });document.querySelector('.floated').appendChild(DELETE_SAVE_DATA_BUTTON);