Greasy Fork is available in English.

AtCoderLanguageButtons

Add buttons to select language.

Versione datata 13/02/2021. 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         AtCoderLanguageButtons
// @namespace    http://atcoder.jp/
// @version      0.1
// @description  Add buttons to select language.
// @author       magurofly
// @match        https://atcoder.jp/contests/*/tasks/*
// @match        https://atcoder.jp/contests/*/submit*
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function() {
    'use strict';

    const VERSION = "0.1";

    // 設定があればロード
    const config = (() => {
        let buttons = new Set();

        return {
            load() {
                const config_json = GM_getValue("config", "null");
                if (config_json) {
                    try {
                        const data = JSON.parse(config_json);
                        buttons = new Set(data.buttons);
                    } catch (e) {
                        console.error("AtCoderLanguageButtons: Invalid JSON", config_json);
                    }
                }
            },

            save() {
                const data = { buttons: [...buttons], };
                const config_json = JSON.stringify(data);
                GM_setValue("config", config_json);
                console.info("AtCoderLanguageButtons: saved");
            },

            isSet(lang) {
                return buttons.has(lang);
            },

            set(lang, flag) {
                if (flag) {
                    buttons.add(lang);
                } else {
                    buttons.delete(lang);
                }
            },
        };
    })();

    // 表示する
    const view = (() => {
        const modal = document.createElement("section");
        modal.className = "modal fade";
        modal.innerHTML = `
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
            <h4 class="modal-title">AtCoderLanguageButtons</h4>
        </div>
        <div class="modal-body">
            <p>ボタンを表示する言語を選択してください</p>
            <form id="atcoder-language-buttons-config">
                <div id="atcoder-language-buttons-config-languages"></div>
            </form>
        </div>
    </div>
</div>
`;

        const choices = new Map();
        const group = document.createElement("span");

        return {
            init() {
                this.initView();
                this.initConfigWindow();
                this.updateButtons();
            },

            initView() {
                const container = document.getElementById("select-lang");
                container.appendChild(group);

                const openButton = document.createElement("button");
                openButton.type = "button";
                openButton.className = "glyphicon glyphicon-cog";
                openButton.addEventListener("click", _e => {
                    this.showConfig();
                });
                container.appendChild(openButton);

                const select = $("#select-lang select[name='data.LanguageId']");
                select.on("change", _e => {
                    this.highlightButtons();
                });
            },

            initConfigWindow() {
                document.body.appendChild(modal);
                const langs = document.getElementById("atcoder-language-buttons-config-languages");
                for (const langOption of document.querySelectorAll("#select-lang option[value]")) {
                    const checkbox = document.createElement("input");
                    checkbox.type = "checkbox";
                    checkbox.value = langOption.value;
                    checkbox.addEventListener("change", _e => {
                        config.set(checkbox.value, checkbox.checked);
                        config.save();
                        this.updateButtons();
                    });
                    choices.set(langOption.value, {checkbox, label: langOption.textContent});

                    const checkboxLabel = document.createElement("label");
                    checkboxLabel.appendChild(checkbox);
                    checkboxLabel.appendChild(document.createTextNode(langOption.textContent));

                    const checkboxGroup = document.createElement("div");
                    checkboxGroup.className = "checkbox";
                    checkboxGroup.appendChild(checkboxLabel);

                    langs.appendChild(checkboxGroup);
                }
            },

            updateButtons() {
                $(group).empty();//for (const child of group.children) group.removeChild(child);

                for (const [languageId, {label}] of choices.entries()) {
                    if (!config.isSet(languageId)) continue;
                    const button = document.createElement("button");
                    button.type = "button";
                    button.className = "btn btn-default";
                    button.dataset.languageId = languageId;
                    button.textContent = label;
                    button.addEventListener("click", _e => {
                        //TODO: Set languageId
                        $("#select-lang select[name='data.LanguageId']").val(languageId).trigger("change");
                    });
                    group.appendChild(button);
                }

                this.highlightButtons();
            },

            highlightButtons() {
                const select = $("#select-lang select[name='data.LanguageId']");
                for (const button of group.children) {
                    button.classList.remove("btn-default", "btn-success");
                    if (select.val() == button.dataset.languageId) {
                        button.classList.add("btn-success");
                    } else {
                        button.classList.add("btn-default");
                    }
                }
            },

            showConfig() {
                for (const [languageId, {checkbox}] of choices.entries()) {
                    checkbox.checked = config.isSet(languageId);
                }
                $(modal).modal();
            },
        };
    })();

    // 初期化
    config.load();
    view.init();

    console.info(`AtCoderLanguageButtons v${VERSION}`);
})();