// ==UserScript== // @name Bunpro Custom Layout For Vocab Reading Reviews // @namespace bunpro-custom-layout-vocab-reading // @match https://bunpro.jp/* // @grant none // @version 1.2 // @author - // @description 11/28/2024, 6:43:44 AM // @run-at document-idle // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // Handle navigation to this page window.onload = observeUrlChange(setup); // Handle direct loading of the page setup(); })(); function observeUrlChange(onChange) { // Whole purpose of this function is to run setup() when we navigate to the review page let oldHref = document.location.href; const body = document.querySelector("body"); const observer = new MutationObserver(mutations => { mutations.forEach(() => { if (oldHref !== document.location.href && document.location.href.toLowerCase().startsWith("https://bunpro.jp/reviews")) { oldHref = document.location.href; onChange(); } }); }); observer.observe(body, { childList: true, subtree: true }); } function showFuriganaOnReview(showFurigana) { const rt = document.querySelector("#js-tour-quiz-question > div.bp-quiz-question > span.text-primary-accent > span > ruby > rt"); if (!rt) return; if (showFurigana) { rt.classList.add('bp-js-hide-furi'); } else { rt.classList.remove('bp-js-hide-furi'); } } function setup() { console.log("Setup called"); // Setup an observer to determine whether the english sentence is hidden const body = document.querySelector("body"); const observer = new MutationObserver(() => { // console.log("Changed"); // Look for page elements const metadata = document.querySelector("#quiz-metadata-element"); const engSentenceDivs = document.querySelectorAll("#js-tour-quiz-question > div.bp-quiz-trans-wrap > div"); const displayLocation = document.querySelector("#js-tour-quiz-question"); // Return immediately if we can't find our elements if (metadata == null || engSentenceDivs == null || displayLocation == null) { // console.log(`metadata: ${metadata}\nengSentenceDivs: ${engSentenceDivs}\ndisplayLocation: ${displayLocation}\nitemToAddOrig: ${itemToAddOrig}`) return; } // TODO: Make sure that we are doing vocab reviews in reading mode // Use the metadata somehow // Decide whether the english sentence is visible or not let visible = false; for (const engSentenceDiv of engSentenceDivs) { if (!engSentenceDiv.className.includes("invisible")) { visible = true; break; } } // Do something if the english sentence is visible/invisible if (visible) { // console.log("Visible!"); showFuriganaOnReview(true); // Copy the definition and pitch to the area above the good/hard buttons if (document.querySelector("#bunpro-custom-layout-vocab-reading") != null) { // console.log("Already added.") return; } const itemToAddOrig = document.querySelector("#js-struct-details"); if (itemToAddOrig != null) { const itemToAdd = itemToAddOrig.cloneNode(true); itemToAdd.id = "bunpro-custom-layout-vocab-reading"; displayLocation.insertAdjacentElement('afterend', itemToAdd); } } else { // console.log("Not Visible!"); showFuriganaOnReview(false); // Clean Up - Remove objects that we added const itemAdded = document.querySelector("#bunpro-custom-layout-vocab-reading"); if (itemAdded != null) { itemAdded.remove(); } } }); observer.observe(body, { childList: true, subtree: true }); }