注意: 保存後、変更を確認するにはブラウザーのキャッシュを消去する必要がある場合があります。

  • Firefox / Safari: Shift を押しながら 再読み込み をクリックするか、Ctrl-F5 または Ctrl-R を押してください (Mac では ⌘-R)
  • Google Chrome: Ctrl-Shift-R を押してください (Mac では ⌘-Shift-R)
  • Microsoft Edge: Ctrl を押しながら 最新の情報に更新 をクリックするか、Ctrl-F5 を押してください。
/* ここにあるすべてのJavaScriptは、すべてのページ読み込みですべての利用者に対して読み込まれます */
/* ========================================
 * 屋台比較
 * 最大4店舗を localStorage に保存
 * ======================================== */

mw.loader.using( 'mediawiki.storage' ).then( function () {

    'use strict';

    const STORAGE_KEY = 'matsuriWikiCompareStalls';
    const MAX_COMPARE = 4;

    /**
     * 比較候補を取得
     */
    function getCompareStalls() {
        const raw = mw.storage.get( STORAGE_KEY );

        if ( !raw ) {
            return [];
        }

        try {
            const ids = JSON.parse( raw );

            if ( !Array.isArray( ids ) ) {
                return [];
            }

            /*
             * stall_id は文字列に統一。
             * 重複も除去する。
             */
            return [ ...new Set(
                ids
                    .map( String )
                    .filter( function ( id ) {
                        return id !== '';
                    } )
            ) ].slice( 0, MAX_COMPARE );

        } catch ( e ) {
            return [];
        }
    }

    /**
     * 比較候補を保存
     */
    function saveCompareStalls( ids ) {
        mw.storage.set(
            STORAGE_KEY,
            JSON.stringify( ids )
        );
    }

    /**
     * メッセージ表示
     */
    function showMessage( control, message, isError ) {
        const messageElement =
            control.querySelector( '.stall-compare-message' );

        if ( !messageElement ) {
            return;
        }

        messageElement.textContent = message;

        messageElement.classList.toggle(
            'stall-compare-message-error',
            Boolean( isError )
        );
    }

    /**
     * ページ上の比較ボタン表示を更新
     */
    function updateCompareButtons() {
        const ids = getCompareStalls();

        document
            .querySelectorAll( '.stall-compare-button' )
            .forEach( function ( button ) {

                const stallId =
                    String( button.dataset.stallId || '' );

                const selected =
                    ids.includes( stallId );

                if ( selected ) {
                    button.textContent = '比較から外す';
                    button.classList.add(
                        'stall-compare-button-selected'
                    );
                    button.setAttribute(
                        'aria-pressed',
                        'true'
                    );
                } else {
                    button.textContent = '比較に追加';
                    button.classList.remove(
                        'stall-compare-button-selected'
                    );
                    button.setAttribute(
                        'aria-pressed',
                        'false'
                    );
                }
            } );
    }

    /**
     * 比較ボタン
     */
    document.addEventListener( 'click', function ( event ) {

        const button =
            event.target.closest( '.stall-compare-button' );

        if ( !button ) {
            return;
        }

        event.preventDefault();

        const stallId =
            String( button.dataset.stallId || '' );

        const control =
            button.closest( '.stall-compare-control' );

        if ( !stallId ) {
            if ( control ) {
                showMessage(
                    control,
                    '屋台IDを取得できませんでした。',
                    true
                );
            }

            return;
        }

        let ids = getCompareStalls();

        const index =
            ids.indexOf( stallId );

        /*
         * すでに登録済み
         * → 比較候補から削除
         */
        if ( index !== -1 ) {

            ids.splice( index, 1 );

            saveCompareStalls( ids );
            updateCompareButtons();

            if ( control ) {
                showMessage(
                    control,
                    '比較候補から外しました。',
                    false
                );
            }

            return;
        }

        /*
         * 最大4件
         */
        if ( ids.length >= MAX_COMPARE ) {

            if ( control ) {
                showMessage(
                    control,
                    '比較できる屋台は最大4店舗です。',
                    true
                );
            }

            return;
        }

        /*
         * 比較候補へ追加
         */
        ids.push( stallId );

        saveCompareStalls( ids );
        updateCompareButtons();

        if ( control ) {
            showMessage(
                control,
                '比較候補に追加しました(' +
                    ids.length +
                    '/4)。',
                false
            );
        }

    } );

    /*
     * 初期表示
     */
    updateCompareButtons();

    /*
     * MediaWikiでページ本文が再描画された場合にも対応
     */
    mw.hook( 'wikipage.content' ).add( function () {
        updateCompareButtons();
    } );

} );