ac-hide-official-rating-icon

AtCoder公式のレーティングアイコンを非表示にできるようにする拡張機能

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
// ==UserScript==
// @name         ac-hide-official-rating-icon
// @namespace    https://atcoder.jp/
// @version      1.02
// @description  AtCoder公式のレーティングアイコンを非表示にできるようにする拡張機能
// @author       konchanksu
// @license      MIT
// @match        https://atcoder.jp/*
// @grant        none
// ==/UserScript==

const SHOW_RATING_ICON_FG = 'showRatingIconFg';
const SHOW_RATING_ICON_STANDINGS_FG = 'showRatingIconProfileFg';
const CHECKBOX_STATE_KEY = 'ac-hide-rating-icon-config';
class LocalStorageController {
    constructor() {
        this.changeState = true;
        if (!localStorage.hasOwnProperty(CHECKBOX_STATE_KEY)) {
            this.saveRadioState({
                showRatingIconFg: false,
                showRatingIconProfileFg: false,
            });
        }
    }
    saveRadioState(flags) {
        this.changeState = true;
        localStorage.setItem(CHECKBOX_STATE_KEY, JSON.stringify(flags));
    }
    getRadioState() {
        if (this.changeState) {
            const jsonString = localStorage.getItem(CHECKBOX_STATE_KEY);
            const object = JSON.parse(jsonString);
            const needSave = !object.hasOwnProperty(SHOW_RATING_ICON_FG) ||
                !object.hasOwnProperty(SHOW_RATING_ICON_STANDINGS_FG);
            this.showRatingIconFg = object.hasOwnProperty(SHOW_RATING_ICON_FG)
                ? object[SHOW_RATING_ICON_FG]
                : true;
            this.showRatingIconProfileFg = object.hasOwnProperty(SHOW_RATING_ICON_STANDINGS_FG)
                ? object[SHOW_RATING_ICON_STANDINGS_FG]
                : true;
            if (needSave) {
                this.saveRadioState({
                    showRatingIconFg: this.showRatingIconFg,
                    showRatingIconProfileFg: this.showRatingIconProfileFg,
                });
                this.changeState = false;
            }
        }
        return {
            showRatingIconFg: this.showRatingIconFg,
            showRatingIconProfileFg: this.showRatingIconProfileFg,
        };
    }
}

const RATING_ICON_CLASSES = [
    'user-rating-stage-l',
    'user-rating-stage-m',
    'user-rating-stage-s',
];
const CURRENT_LANGUAGE = (() => {
    const dropdown_toggle = document.getElementsByClassName('dropdown-toggle');
    const isIncludeEn = Array.prototype.filter.call(dropdown_toggle, (element) => element.textContent.includes('English')).length !== 0;
    return isIncludeEn ? 'EN' : 'JA'; // default JA
})();
const IS_CURRENT_LANGUAGE_JA = CURRENT_LANGUAGE === 'JA';
const CONFIG_DROPDOWN_JA = {
    title: ' ac-hide-icon 設定',
    radio: [
        {
            title: 'レーティングアイコンを非表示にしない',
            id: 'any',
            showRatingIconFg: true,
            showRatingIconProfileFg: true,
        },
        {
            title: 'プロフィールページのみ非表示にする',
            id: 'only-not-standings',
            showRatingIconFg: true,
            showRatingIconProfileFg: false,
        },
        {
            title: 'レーティングアイコンを全て非表示にする',
            id: 'all',
            showRatingIconFg: false,
            showRatingIconProfileFg: false,
        },
    ],
};
const CONFIG_DROPDOWN_EN = {
    title: ' ac-hide-icon',
    radio: [
        {
            title: 'show the rating icon',
            id: 'any',
            showRatingIconFg: true,
            showRatingIconProfileFg: true,
        },
        {
            title: 'hide the rating icon only on the profile page',
            id: 'only-not-standings',
            showRatingIconFg: true,
            showRatingIconProfileFg: false,
        },
        {
            title: 'hide the rating icon',
            id: 'all',
            showRatingIconFg: false,
            showRatingIconProfileFg: false,
        },
    ],
};
const CONFIG_DROPDOWN = IS_CURRENT_LANGUAGE_JA
    ? CONFIG_DROPDOWN_JA
    : CONFIG_DROPDOWN_EN;
const MODAL_HTML_BASE = `<div id="modal-ac-hide-icon-settings" class="modal fade" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">×</span>
        </button>
        <h4 class="modal-title">
          ${CONFIG_DROPDOWN['title']}
        </h4>
      </div>
    <div class="modal-body">
      <div class="container-fluid">
        <div class="settings-row row" id="ac-hide-rating-icon-radio">
        </div>
      </div>
    </div>
    <div class="modal-footer">
      <button type="button" class="btn btn-default" data-dismiss="modal">close</button>
    </div>
  </div>
</div>`;
const RADIO_HTML_BASE = (text, id) => `<div class="radio">
    <label>\
      <input type="radio" name="ac-hide-rating-icon-config" id="ac-hide-rating-icon-${id}" required> ${text}
    </label>
  </div>`;
const localStorageController = new LocalStorageController();
function isDropDownMenu() {
    return (document.getElementsByClassName('header-mypage_btn').length === 0 ||
        CURRENT_LANGUAGE === 'EN');
}
function createRadio() {
    const radioState = localStorageController.getRadioState();
    CONFIG_DROPDOWN['radio'].forEach((element) => {
        var _a;
        const { title, id, showRatingIconFg, showRatingIconProfileFg } = element;
        const radio = RADIO_HTML_BASE(title, id);
        (_a = document
            .querySelector('#ac-hide-rating-icon-radio')) === null || _a === void 0 ? void 0 : _a.insertAdjacentHTML('afterbegin', radio);
        const currentRadio = document.getElementById(`ac-hide-rating-icon-${id}`);
        currentRadio.addEventListener('click', () => {
            localStorageController.saveRadioState({
                showRatingIconFg,
                showRatingIconProfileFg,
            });
            currentRadio.checked = true;
            checkAndHideIcons();
        });
        if (radioState['showRatingIconFg'] === showRatingIconFg &&
            radioState['showRatingIconProfileFg'] === showRatingIconProfileFg) {
            currentRadio.checked = true;
        }
    });
}
function createModal() {
    var _a;
    (_a = document
        .querySelector('body')) === null || _a === void 0 ? void 0 : _a.insertAdjacentHTML('afterbegin', MODAL_HTML_BASE);
    createRadio();
}
function controlIcons(hideFg) {
    RATING_ICON_CLASSES.forEach((ratingIconClass) => {
        const ratingIcons = document.getElementsByClassName(ratingIconClass);
        Array.prototype.forEach.call(ratingIcons, (element) => {
            element.style.display = hideFg ? 'none' : 'unset';
        });
    });
}
function showHeaderSettingForDropDown() {
    const headerMyPageList = document.getElementsByClassName('dropdown-menu')[1];
    const newElement = createHeaderSettingElementForDropDown();
    const positionIndex = 6;
    if (positionIndex >= headerMyPageList.children.length) {
        headerMyPageList.appendChild(newElement);
    }
    else {
        headerMyPageList.insertBefore(newElement, headerMyPageList.children[positionIndex]);
    }
}
function showHeaderSetting() {
    const headerMyPageList = document.getElementsByClassName('header-mypage_list')[0];
    const newElement = createHeaderSettingElement();
    const positionIndex = 5;
    if (headerMyPageList) {
        if (positionIndex >= headerMyPageList.children.length) {
            headerMyPageList.appendChild(newElement);
        }
        else {
            headerMyPageList.insertBefore(newElement, headerMyPageList.children[positionIndex]);
        }
    }
}
function createGlyphicon() {
    const innerSpanTag = document.createElement('span');
    ['glyphicon', 'glyphicon-wrench'].forEach((tag) => innerSpanTag.classList.add(tag));
    return innerSpanTag;
}
function createIcon() {
    const innerITag = document.createElement('i');
    ['a-icon', 'a-icon-setting'].forEach((tag) => innerITag.classList.add(tag));
    return innerITag;
}
function createHeaderATag() {
    const aTag = document.createElement('a');
    const text = document.createTextNode(CONFIG_DROPDOWN['title']);
    aTag.appendChild(text);
    aTag.setAttribute('data-toggle', 'modal');
    aTag.setAttribute('data-target', '#modal-ac-hide-icon-settings');
    return aTag;
}
function createHeaderSettingElementForDropDown() {
    const element = document.createElement('li');
    const innerATag = createHeaderATag();
    const innerSpanTag = createGlyphicon();
    element.appendChild(innerATag);
    innerATag.insertBefore(innerSpanTag, innerATag.firstChild);
    return element;
}
function createHeaderSettingElement() {
    const element = document.createElement('li');
    const innerATag = createHeaderATag();
    const innerTag = IS_CURRENT_LANGUAGE_JA ? createIcon() : createGlyphicon();
    element.appendChild(innerATag);
    innerATag.insertBefore(innerTag, innerATag.firstChild);
    return element;
}
function observeLoadingHideClassForStandings(hide) {
    const target = document.getElementsByClassName('loading-hide');
    if (target) {
        const observer = new MutationObserver(() => {
            // 読み込み後は standings-tbody に順位情報が格納されるため、それを参照する
            observeStandings(hide);
            controlIcons(hide);
        });
        observer.observe(target[1], {
            childList: true,
        });
        observeStandings(hide);
    }
}
function observeStandings(hide) {
    const target = document.getElementById('standings-tbody');
    if (target) {
        const observer = new MutationObserver(() => {
            controlIcons(hide);
        });
        observer.observe(target, {
            childList: true,
        });
    }
}
function checkAndHideIcons() {
    const { showRatingIconFg, showRatingIconProfileFg } = localStorageController.getRadioState();
    const url = window.location.href;
    controlIcons(!showRatingIconFg ||
        (url.match(/.*users.*/) !== null && !showRatingIconProfileFg));
    if (url.match(/.*standings/g)) {
        observeLoadingHideClassForStandings(!showRatingIconFg);
    }
}
function main() {
    checkAndHideIcons();
    // 設定作る系
    createModal();
    if (isDropDownMenu()) {
        showHeaderSettingForDropDown();
    }
    else {
        showHeaderSetting();
    }
}
(function () {
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => main());
    }
    else {
        main();
    }
})();
//# sourceMappingURL=index.js.map