iTutorProMax_JS

mec-itutorの演習画面を修正

Version au 05/11/2025. Voir la dernière version.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==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();
  });
}