您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Hide item info on the Level and Item screens for self-study.
// ==UserScript== // @name Wanikani Self-Study Hide Info // @namespace rfindley // @description Hide item info on the Level and Item screens for self-study. // @version 1.1.2 // @match https://www.wanikani.com/level/* // @match https://www.wanikani.com/radicals* // @match https://www.wanikani.com/kanji* // @match https://www.wanikani.com/vocabulary* // @match https://preview.wanikani.com/level/* // @match https://preview.wanikani.com/radicals* // @match https://preview.wanikani.com/kanji* // @match https://preview.wanikani.com/vocabulary* // @copyright 2018-2023, Robin Findley // @license MIT; http://opensource.org/licenses/MIT // @run-at document-end // @grant none // ==/UserScript== window.ss_hideinfo = {}; (function(gobj) { /* globals wkof, ss_quiz */ //=================================================================== // Initialization of the Wanikani Open Framework. //------------------------------------------------------------------- var script_name = 'Self-Study Quiz'; var wkof_version_needed = '1.0.17'; if (!window.wkof) { if (confirm(script_name+' requires Wanikani Open Framework.\nDo you want to be forwarded to the installation instructions?')) { window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549'; } return; } if (wkof.version.compare_to(wkof_version_needed) === 'older') { if (confirm(script_name+' requires Wanikani Open Framework version '+wkof_version_needed+'.\nDo you want to be forwarded to the update page?')) { window.location.href = 'https://greasyfork.org/en/scripts/38582-wanikani-open-framework'; } return; } wkof.include('Settings'); wkof.ready('document, Settings') .then(load_settings) .then(install_interface); //======================================================================== var btnbar, sections; function install_interface() { var html = '<div class="ss_hideinfo">'+ ' <label>Self-study:</label>'+ ' <div class="btn-group">'+ ' <button class="btn enable" title="Enable/Disable self-study plugin"></button>'+ ' <button class="btn ssquiz hidden" title="Open the quiz window">Quiz</button>'+ ' <button class="btn shuffle" title="Shuffle the list of items below">Shuffle</button>'+ ' <select class="btn mode" title="Select a self-study preset">'+ ' <option value="jp2en">Japanese to English</option>'+ ' <option value="en2jp">English to Japanese</option>'+ ' </select>'+ ' <select class="btn lockburn" title="Select a self-study preset">'+ ' <option value="all">Show All Items</option>'+ ' <option value="hideunlocked">Show Locked Only</option>'+ ' <option value="hideunburned">Show Burned Only</option>'+ ' <option value="hidelocked">Hide Locked</option>'+ ' <option value="hideburned">Hide Burned</option>'+ ' <option value="hidelockedburned">Hide Locked and Burned</option>'+ ' </select>'+ ' </div>'+ '</div>'; var css = ` .ss_hideinfo {margin-left:20px; margin-bottom:10px; position:relative;} .ss_hideinfo label {display:inline; vertical-align:middle; padding-right:4px; color:#999; font-size:14px;font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif; text-shadow:0 1px 0 #fff;} .ss_hideinfo .btn-group {display:inline; vertical-align:middle; font-size:0px;} .ss_hideinfo select.btn {width:200px;} .ss_hideinfo .btn.enable {width:55px;} .ss_hideinfo .btn { display:inline-block; height:30px; padding: 4px 12px; margin-bottom: 0; font-size: 14px; line-height: 20px; text-align: center; vertical-align: middle; cursor: pointer; text-shadow: 0 1px 1px rgb(255 255 255 / 75%); font-family: "Ubuntu", Helvetica, Arial, sans-serif; background-color: #f0f0f0; background-image: linear-gradient(to bottom, #fff, #e6e6e6); background-repeat: repeat-x; border-color: rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25); border: 1px solid #ccc; border-left: 0; border-bottom-color: #b3b3b3; box-shadow: inset 0 1px 0 rgb(255 255 255 / 20%), 0 1px 2px rgb(0 0 0 / 5%); } .ss_hideinfo .btn:hover { color: #333; text-decoration: none; background-position: 0 -15px; transition: background-position 0.1s linear; } .ss_hideinfo .btn:first-child { border-left: 1px solid #ccc; border-radius: 4px 0 0 4px; } .ss_hideinfo .btn:last-child {border-radius: 0 4px 4px 0;} section.ss_active .ss_hideinfo button.enable {background-color:#b3e6b3; background-image:linear-gradient(to bottom, #ecf9ec, #b3e6b3);} section.ss_active .ss_hideinfo button.enable:after {content:"ON";} section:not(.ss_active) .ss_hideinfo button.enable:after {content:"OFF";} section.ss_active.ss_hidechar .subject-character .subject-character__characters {opacity:0; transition:opacity ease-in-out 0.15s} section.ss_active.ss_hideread .subject-character .subject-character__reading {opacity:0; transition:opacity ease-in-out 0.15s} section.ss_active.ss_hidemean .subject-character .subject-character__meaning {opacity:0; transition:opacity ease-in-out 0.15s} section.ss_active.ss_hideburned .ss_burned {display:none;} section.ss_active.ss_hidelocked .ss_locked {display:none;} section.ss_active.ss_hideunburned .subject-character-grid__item:not(.ss_burned) {display:none;} section.ss_active.ss_hideunlocked .subject-character-grid__item:not(.ss_locked) {display:none;} section.ss_active .subject-character:hover span.subject-character__characters {opacity: initial !important; transition:opacity ease-in-out 0.05s !important;} section.ss_active .subject-character:hover .subject-character__info span {opacity: initial !important; transition:opacity ease-in-out 0.05s !important;} `; let css_tag = document.createElement('style'); css_tag.textContent = css; document.head.prepend(css_tag); sections = document.querySelectorAll('section.character-grid'); sections.forEach((section) => { section.insertAdjacentHTML('afterbegin',html); btnbar = section.querySelector('.ss_hideinfo'); btnbar.querySelector('button.enable').addEventListener('click', toggle_enable); btnbar.querySelector('button.ssquiz').addEventListener('click', open_quiz); btnbar.querySelector('button.shuffle').addEventListener('click', shuffle); btnbar.querySelector('select.mode').addEventListener('change', mode_changed); btnbar.querySelector('select.lockburn').addEventListener('change', lockburn_changed); }); for (let item of document.querySelectorAll('section.character-grid .subject-character--locked')) { item.closest('.subject-character-grid__item').classList.add('ss_locked'); } for (let item of document.querySelectorAll('section.character-grid .subject-character--burned')) { item.closest('.subject-character-grid__item').classList.add('ss_burned'); } wkof.wait_state('ss_quiz', 'ready').then(function(){ if (typeof ss_quiz.open === 'function') { for (let bar of document.querySelectorAll('.ss_hideinfo button.ssquiz')) { bar.classList.remove('hidden'); }; } }); toggle_enable(null, true /* no_toggle */); mode_changed(); lockburn_changed(); if (settings.enabled) shuffle(); } //======================================================================== function deep_merge(...objects) { let merged = {}; function recursive_merge(dest, src) { for (let prop in src) { if (typeof src[prop] === "object" && src[prop] !== null ) { if (Array.isArray(src[prop])) { dest[prop] = src[prop].slice(); } else { dest[prop] = dest[prop] || {}; recursive_merge(dest[prop], src[prop]); } } else { dest[prop] = src[prop]; } } return dest; } for (let obj in objects) { recursive_merge(merged, objects[obj]); } return merged; } //======================================================================== var settings; function load_settings() { var default_settings = { enabled: false, mode: 'jp2en', lockburn: 'all', }; return wkof.Settings.load('ss_hideinfo') .then(function(){ settings = deep_merge(default_settings, wkof.settings.ss_hideinfo); settings = wkof.settings.ss_hideinfo; }); } //======================================================================== function save_settings() { wkof.Settings.save('ss_hideinfo'); } //======================================================================== function toggle_enable(e, no_toggle) { var enabled = settings.enabled; if (no_toggle !== true) enabled = !enabled; if (enabled) { sections.forEach((section) => section.classList.add('ss_active')); } else { sections.forEach((section) => section.classList.remove('ss_active')); } if (enabled !== settings.enabled) { settings.enabled = enabled; save_settings(); } } //======================================================================== function fisher_yates_shuffle(arr) { var i = arr.length, j, temp; if (i===0) return arr; while (--i) { j = Math.floor(Math.random()*(i+1)); temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } return arr; } //======================================================================== function shuffle(e) { if (e === undefined) { // Shuffle all for (let section of document.querySelectorAll('.subject-character-grid')) { let grid = section.querySelector('.subject-character-grid__items'); let items = fisher_yates_shuffle(Array.from(grid.children)); for (let item of items) grid.append(item); }; } else { // Shuffle specific group let section = e.currentTarget.closest('section.character-grid'); let grid = section.querySelector('.subject-character-grid__items'); let items = fisher_yates_shuffle(Array.from(grid.children)); for (let item of items) grid.append(item); } } //======================================================================== function mode_changed(e) { let value; if (e !== undefined) { value = e.target.value; settings.mode = value; save_settings(); } else { value = settings.mode; } for (let section of sections) { section.querySelector('select.mode').value = value; section.classList.remove('ss_hidechar', 'ss_hideread', 'ss_hidemean'); switch (value) { case 'jp2en': section.classList.add('ss_hidemean', 'ss_hideread'); break; case 'en2jp': section.classList.add('ss_hidechar', 'ss_hideread'); break; } } } //======================================================================== function lockburn_changed(e) { let value; if (e !== undefined) { value = e.target.value; settings.lockburn = value; save_settings(); } else { value = settings.lockburn; } for (let section of sections) { section.querySelector('select.lockburn').value = value; section.classList.remove('ss_hidelocked', 'ss_hideburned', 'ss_hideunlocked', 'ss_hideunburned'); switch (value) { case 'all': break; case 'hidelocked': section.classList.add('ss_hidelocked'); break; case 'hideburned': section.classList.add('ss_hideburned'); break; case 'hidelockedburned': section.classList.add('ss_hidelocked', 'ss_hideburned'); break; case 'hideunlocked': section.classList.add('ss_hideunlocked'); break; case 'hideunburned': section.classList.add('ss_hideunburned'); break; } } } //======================================================================== function open_quiz(e) { var btn = e.currentTarget; var sec = btn.closest('section.character-grid'); var level, item_type; var path = window.location.pathname.split('/'); var header = btn.closest('section').querySelector('header').textContent.trim(); if (path[1] === 'level') { level = path[2]; item_type = header.toLowerCase(); } else { level = header.split(' ')[1]; item_type = path[1]; } var item_type_text = item_type; item_type_text[0] = item_type_text[0].toUpperCase(); var title = 'Level '+level+' '+item_type_text; item_type = item_type.replace(/s$/g, ''); var custom_options = { ipreset: {name: title, content: { wk_items: {enabled: true, filters: { level: {enabled: true, value: level}, item_type: {enabled: true, value: item_type}, }}, }}, }; switch (settings.lockburn) { case 'all': break; case 'hidelocked': custom_options.ipreset.content.wk_items.filters.srs = {enabled:true,value:'1,2,3,4,5,6,7,8,9'}; break; case 'hideburned': custom_options.ipreset.content.wk_items.filters.srs = {enabled:true,value:'-1,0,1,2,3,4,5,6,7,8'}; break; case 'hidelockedburned': custom_options.ipreset.content.wk_items.filters.srs = {enabled:true,value:'1,2,3,4,5,6,7,8'}; break; case 'hideunlocked': custom_options.ipreset.content.wk_items.filters.srs = {enabled:true,value:'-1,0'}; break; case 'hideunburned': custom_options.ipreset.content.wk_items.filters.srs = {enabled:true,value:'9'}; break; } if (settings.mode === 'en2jp' && item_type === 'vocabulary') { custom_options.qpreset = { name: 'English to Japanese', content: { mean2read:true, } }; } else { custom_options.qpreset = { name: 'Japanese to English', content: { char2read:true, char2mean:true, } }; } ss_quiz.open(custom_options); } })(window.ss_hideinfo);