AtCoder Copy Contest ID

Add a button to copy the contest ID to the clipboard in AtCoder contest pages

Устаревшая версия за 27.04.2023. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name               AtCoder Copy Contest ID
// @name:ja            AtCoder Copy Contest ID
// @namespace          https://github.com/xe-o
// @version            0.4
// @description        Add a button to copy the contest ID to the clipboard in AtCoder contest pages
// @description:ja     AtCoderコンテストページのナビゲーションバーへ、コンテストIDをコピーするためのボタンを追加します
// @author             XERO
// @license            MIT
// @match              https://atcoder.jp/*
// @grant              GM_setClipboard
// @run-at             document-idle
// ==/UserScript==

const INIT_LABEL = "Copy Contest ID";
const COPIED_LABEL = "Copied!";
const FAILED_LABEL = "Failed to copy";
const ICONS = {
  COPY: "glyphicon-copy",
  OK: "glyphicon-ok",
  REMOVE: "glyphicon-remove",
};

const copyContestId = () => {
  const $ = (selector, baseElement = document) =>
    baseElement.querySelector(selector);
  const getContestId = () => window.location.pathname.split("/")[2];
  const navbar = $(".navbar-nav");
  const style = document.createElement("style");
  style.innerHTML = `
    @media (max-width: 991px) {
      .contest-title {
        width: auto;
      }
    }
    @media (max-width: 1150px) {
      .contest-title {
        width: auto;
        max-width: 580px;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
      #copy-button-text {
        display: none;
      }
    }
    @media (max-width: 1000px) {
      .contest-title {
        width: auto;
        max-width: 300px;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    }
  `;

  const addCopyButton = () => {
    if (!navbar) {
      console.error("Failed to find navbar element.");
      return;
    }
    navbar.insertAdjacentHTML(
      "beforeend",
      `
      <li>
        <a id="copy-contest-id-button" style="cursor: pointer; font-size: 12px">
          <span class="glyphicon ${ICONS.COPY}" style="margin-right: 2px" aria-hidden="true"></span>
          <span id="copy-button-text">${INIT_LABEL}</span>
        </a>
      </li>
    `
    );
  };

  const setupCopyButton = () => {
    const button = $("#copy-contest-id-button");
    const icon = $(".glyphicon", button);
    const label = $("#copy-button-text");
    let isCopying = false;

    const resetButton = () => {
      icon.classList.replace(ICONS.OK, ICONS.COPY, ICONS.REMOVE);
      label.textContent = INIT_LABEL;
      isCopying = false;
    };

    const copyToClipboard = async () => {
      if (isCopying) return;
      isCopying = true;

      try {
        await GM_setClipboard(getContestId(), {
          type: "text",
          mimetype: "text/plain",
        });
        icon.classList.replace(ICONS.COPY, ICONS.OK);
        label.textContent = COPIED_LABEL;
      } catch (error) {
        console.error(`Failed to copy contest ID: ${error}`);
        icon.classList.replace(ICONS.COPY, ICONS.REMOVE);
        label.textContent = FAILED_LABEL;
      } finally {
        setTimeout(resetButton, 1800);
      }
    };

    button.addEventListener("click", copyToClipboard);
  };

  document.head.appendChild(style);
  addCopyButton();
  setupCopyButton();
};

copyContestId();