BetterExercises_JS

mec-itutorの演習画面を修正

当前为 2025-11-10 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        BetterExercises_JS
// @include     *://mec-itutor.jp/rpv/home/question/practice*
// @description mec-itutorの演習画面を修正
// @author      zom.u
// @version     1.3.5
// @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();
  });
}