注意: 保存後、変更を確認するにはブラウザーのキャッシュを消去する必要がある場合があります。
- 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();
} );
} );