Cosense Toolbox
userscript 一覧テーマ作成使い方パーサーGitHub ↗
modal-for-userscript
基盤#モーダル#ダイアログ#UI#module

modal-for-userscript

確認・入力ダイアログのUIを使い回せる汎用モーダルダイアログの部品です。自作スクリプトで「実行してよいか確認したい」「値を入力してもらいたい」といったときに、自前でダイアログを組まずに済みます。

デモ

デモ

インストール

設定ページの code:script.js に貼る
import { Modal } from "/api/code/cosense-toolbox/modal-for-userscript/module.js";
ソースコード全文を見る(JS)
export class Modal {
  isOpen = false;
  constructor({
    onClose = async () => {},
    onConfirm = async () => {},
    title = "modal",
    body = document.createElement("div"),
    footer = null,
    header = null,
    modalStyle = null,
    backdropClose = true,
  } = {}) {
    this.onClose = onClose;
    this.onConfirm = onConfirm;
    this.titleText = title;
    this.body = body;
    this.footer = footer;
    this.header = header;
    this.modalStyle = modalStyle;
    this.backdropClose = backdropClose;
  }

  open() {
    this.createElements();
    this.addEvents();
    document.body.appendChild(this.backdrop);
    this.isOpen = true;
  }

  createElements() {
    // create backdrop
    this.backdrop = document.createElement("div");
    Object.assign(this.backdrop.style, {
      position: "fixed",
      inset: 0,
      backgroundColor: "rgba(0, 0, 0, 0.6)",
      display: "flex",
      justifyContent: "center",
      alignItems: "center",
      zIndex: 999,
    });

    // modal container
    const modal = document.createElement("div");
    Object.assign(modal.style, {
      width: "80vw",
      maxHeight: "80vh",
      height: "100%",
      backgroundColor: "#1e1e1e",
      color: "#eee",
      borderRadius: "12px",
      display: "flex",
      flexDirection: "column",
      padding: "20px",
      boxShadow: "0 0 20px rgba(0,0,0,0.5)",
      overflow: "hidden",
      ...(this.modalStyle ?? {}),
    });

    // header
    if (!this.header) {
      this.header = document.createElement("div");
      Object.assign(this.header.style, {
        display: "flex",
        alignItems: "center",
        gap: "12px",
        marginBottom: "16px",
      });
    }

    const title = document.createElement("div");
    title.textContent = this.titleText;

    this.header.appendChild(title);

    if (!this.footer) {
      // footer
      this.footer = document.createElement("div");
      Object.assign(this.footer.style, {
        display: "flex",
        justifyContent: "flex-end",
        gap: "8px",
        marginTop: "16px",
      });

      const closeBtn = document.createElement("button");
      closeBtn.textContent = "閉じる";
      Object.assign(closeBtn.style, this.buttonStyle());
      closeBtn.addEventListener("click", () => this.close());

      const confirmBtn = document.createElement("button");
      confirmBtn.textContent = "確定";
      Object.assign(confirmBtn.style, this.buttonStyle());
      confirmBtn.addEventListener("click", async () => {
        const reuslt = await this.onConfirm();
        if (reuslt) {
          this.close();
        }
      });

      this.footer.appendChild(closeBtn);
      this.footer.appendChild(confirmBtn);
    }

    modal.appendChild(this.header);
    modal.appendChild(this.body);
    modal.appendChild(this.footer);
    this.backdrop.appendChild(modal);
  }

  buttonStyle() {
    return {
      backgroundColor: "#333",
      color: "#eee",
      border: "none",
      padding: "8px 16px",
      borderRadius: "6px",
      fontSize: "0.95rem",
      cursor: "pointer",
    };
  }

  addEvents() {
    if (this.backdropClose) {
      this.backdrop.addEventListener("click", (e) => {
        if (e.target === this.backdrop) {
          this.close();
        }
      });
    }
  }

  close() {
    this.backdrop.remove();
    this.onClose();
    this.isOpen = false;
  }

  toggle() {
    if (this.isOpen) {
      this.close();
    } else {
      this.open();
    }
  }
}
元のCosenseページを見る ↗

Cosense Toolbox / Cosense をもっと面白く、もっと強力に使うためのツール群

GitHub ↗

マイ・ツールボックス

    積んだ import を1つにまとめてコピー → 自分の設定ページ(ユーザー名ページ)に貼るだけ。