main.js
/**
* モーダル管理クラス
*/
class StaffModal {
// 設定(文言やクラス名など)
static CONFIG = {
activeClass: 'is-active',
labels: {
prev: '← PREV',
next: 'NEXT →',
toLast: '← TO LAST',
toFirst: 'TO FIRST →'
}
};
constructor() {
this.initElements();
if (!this.modal) return;
this.currentIndex = 0;
this.total = this.openButtons.length;
this.bindEvents();
}
/**
* 必要なDOM要素を初期化
*/
initElements() {
this.modal = document.getElementById('modal-container');
this.openButtons = Array.from(document.querySelectorAll('.js-modal-open'));
this.closeButtons = document.querySelectorAll('.js-modal-close');
// モーダル内の各パーツ
this.ui = {
img: document.getElementById('modal-img'),
name: document.getElementById('modal-name'),
ruby: document.getElementById('modal-ruby'),
pos: document.getElementById('modal-pos'),
desc1: document.getElementById('modal-desc1'),
desc2: document.getElementById('modal-desc2'),
btnPrev: document.getElementById('modal-prev'),
btnNext: document.getElementById('modal-next')
};
}
/**
* イベントリスナーの登録
*/
bindEvents() {
// 開くボタン
this.openButtons.forEach((btn, index) => {
btn.addEventListener('click', (e) => {
e.preventDefault();
this.open(index);
});
});
// 閉じるボタン
this.closeButtons.forEach(btn => {
btn.addEventListener('click', (e) => {
e.preventDefault();
this.close();
});
});
// ナビゲーション
this.ui.btnPrev.addEventListener('click', (e) => {
e.preventDefault();
this.navigate(-1);
});
this.ui.btnNext.addEventListener('click', (e) => {
e.preventDefault();
this.navigate(1);
});
}
/**
* モーダルを開く
*/
open(index) {
this.update(index);
this.modal.classList.add(StaffModal.CONFIG.activeClass);
}
/**
* モーダルを閉じる
*/
close() {
this.modal.classList.remove(StaffModal.CONFIG.activeClass);
}
/**
* 前後への移動処理(ループ対応)
*/
navigate(direction) {
const newIndex = (this.currentIndex + direction + this.total) % this.total;
this.update(newIndex);
}
/**
* モーダル内の表示内容を更新
*/
update(index) {
const target = this.openButtons[index];
if (!target) return;
const data = target.dataset;
this.currentIndex = index;
// 基本情報の反映
this.ui.img.src = data.img || '';
this.ui.name.textContent = data.name || '';
this.ui.ruby.textContent = data.ruby || '';
this.ui.pos.textContent = data.pos || '';
// HTMLを含む説明文の反映
this.ui.desc1.innerHTML = data.desc1 || '';
this.ui.desc2.innerHTML = data.desc2 || '';
this.updateNavLabels();
}
/**
* ナビゲーションボタンのテキストを更新
*/
updateNavLabels() {
const { labels } = StaffModal.CONFIG;
// PREVボタン: 最初の要素なら TO LAST
this.ui.btnPrev.textContent = (this.currentIndex === 0)
? labels.toLast
: labels.prev;
// NEXTボタン: 最後の要素なら TO FIRST
this.ui.btnNext.textContent = (this.currentIndex === this.total - 1)
? labels.toFirst
: labels.next;
}
}
// DOM読み込み完了後に初期化
document.addEventListener('DOMContentLoaded', () => {
new StaffModal();
});