iTutorProMax_JS

mec-itutorの演習画面を修正

Versione datata 05/11/2025. Vedi la nuova versione l'ultima versione.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name        iTutorProMax_JS
// @include     *://mec-itutor.jp/rpv/home/question/practice*
// @description mec-itutorの演習画面を修正
// @author      zom.u
// @version     1.3.4
// @namespace https://greasyfork.org/users/1534273
// ==/UserScript==

// GoogleアイコンCSSを追加(1回だけ)
if (!document.querySelector("link[href*='Material+Icons']")) {
  document.head.insertAdjacentHTML('beforeend', 
    '<link href="https://fonts.googleapis.com/css?family=Material+Icons|Material+Icons+Outlined|Material+Icons+Round|Material+Icons+Sharp|Material+Icons+Two+Tone" rel="stylesheet">'
  );
}

// 再適用処理
function applyCustomizations() {
  console.log("[iTutor] applyCustomizations on", location.href);
  // タイマー移動
  const timer = document.getElementById("timer");
  if (timer && !document.querySelector("#head_area .col-xs-3.text-right #timer")) {
    $("#timer").appendTo("#head_area .col-xs-3.text-right");
  }
    // 見出し移動
  const heading = document.querySelector(
    "#ctl00_cplPageContent_upd1 > div.container.pb70 > div.well.mec-bg-none.mt40 > p.h4"
  );
  if (heading) {
    // 古い見出しを消す
    $("#head_area > div.col-xs-3.text-left .h4").remove();
    // 新しい見出しを移動
    $(heading).appendTo("#head_area > div.col-xs-3.text-left");
  }
  // 本文テキストを中央へ
  const p = document.querySelector(
    "#ctl00_cplPageContent_upd1 > div.container.pb70 > div.well.mec-bg-none.mt40 > p"
  );
  if (p) {
    // 中央エリアを一度クリア
    $("#head_area > div.col-xs-6.text-center").empty();
    // p のテキストノードだけ抽出して移動
    $(p)
      .contents()
      .filter(function() {
        return this.nodeType === 3 && $.trim(this.nodeValue) !== "";
      })
      .appendTo("#head_area > div.col-xs-6.text-center");
  }

  // セレクト → ボタン化
  const select = document.getElementById("ctl00_cplPageContent_certaintyFactor");
  if (select && !select.nextElementSibling?.classList.contains("toggle-buttons")) {
    select.style.display = "none";

    const wrapper = document.createElement("div");
    wrapper.className = "toggle-buttons";

    Array.from(select.options).forEach(opt => {
      const btn = document.createElement("button");
      btn.type = "button";
      btn.textContent = opt.textContent;
      btn.dataset.value = opt.value;

      if (opt.selected) btn.classList.add("active");

      btn.addEventListener("click", () => {
        select.value = opt.value;

        wrapper.querySelectorAll("button").forEach(b => b.classList.remove("active"));
        btn.classList.add("active");

        select.dispatchEvent(new Event("change", { bubbles: true }));
      });

      wrapper.appendChild(btn);
    });

    select.parentNode.insertBefore(wrapper, select.nextSibling);

    // セレクトが外部から変更されたときにボタンを同期
    select.addEventListener("change", () => {
      const val = select.value;
      wrapper.querySelectorAll("button").forEach(b => {
        if (b.dataset.value === val) {
          b.classList.add("active");
        } else {
          b.classList.remove("active");
        }
      });
    });
  }
}
// 初回適用
applyCustomizations();
// ASP.NET の UpdatePanel 完了イベントにフック
if (window.Sys && Sys.WebForms && Sys.WebForms.PageRequestManager) {
  const prm = Sys.WebForms.PageRequestManager.getInstance();
  prm.add_endRequest(function() {
    console.log("[iTutor] async postback ended → reapply");
    applyCustomizations();
  });
}