「MediaWiki:Common.js」の版間の差分

 
編集の要約なし
 
120行目: 120行目:
updateButtons();
updateButtons();
});
});
});
/* =========================================================
* Infobox 画像スライダー
* ========================================================= */
mw.hook('wikipage.content').add(function ($content) {
$content.find('.ts-infobox-slider').each(function () {
var slider = this;
/* 二重初期化を防止 */
if (slider.dataset.infoboxSliderReady === '1') {
return;
}
slider.dataset.infoboxSliderReady = '1';
var track =
slider.querySelector('.ts-infobox-slider__track');
if (!track) {
return;
}
var slides =
track.querySelectorAll('.ts-infobox-slider__slide');
if (!slides.length) {
return;
}
/*
* 1枚だけなら矢印を作らない
*/
if (slides.length === 1) {
slider.classList.add(
'ts-infobox-slider--single'
);
return;
}
/* -----------------------------------------
  戻るボタン
  ----------------------------------------- */
var prev =
document.createElement('button');
prev.type = 'button';
prev.className =
'ts-infobox-slider__nav ' +
'ts-infobox-slider__prev';
prev.innerHTML = '‹';
prev.setAttribute(
'aria-label',
'前の画像'
);
/* -----------------------------------------
  次へボタン
  ----------------------------------------- */
var next =
document.createElement('button');
next.type = 'button';
next.className =
'ts-infobox-slider__nav ' +
'ts-infobox-slider__next';
next.innerHTML = '›';
next.setAttribute(
'aria-label',
'次の画像'
);
slider.appendChild(prev);
slider.appendChild(next);
/* -----------------------------------------
  ボタン状態
  ----------------------------------------- */
function updateButtons() {
var max =
track.scrollWidth -
track.clientWidth;
prev.disabled =
track.scrollLeft <= 3;
next.disabled =
track.scrollLeft >= max - 3;
}
/* -----------------------------------------
  1枚分移動
  ----------------------------------------- */
function move(direction) {
track.scrollBy({
left:
direction *
track.clientWidth,
behavior: 'smooth'
});
}
prev.addEventListener(
'click',
function () {
move(-1);
}
);
next.addEventListener(
'click',
function () {
move(1);
}
);
track.addEventListener(
'scroll',
function () {
window.requestAnimationFrame(
updateButtons
);
},
{
passive: true
}
);
window.addEventListener(
'resize',
updateButtons
);
updateButtons();
});
});
});

2026年9月2日 (水) 10:18時点における最新版

/* ここにあるすべてのJavaScriptは、すべてのページ読み込みですべての利用者に対して読み込まれます */
/* =========================================================
 * 外部画像ギャラリー
 * ========================================================= */

mw.hook('wikipage.content').add(function ($content) {

	$content.find('.ts-gallery').each(function () {

		var gallery = this;

		/* 二重初期化防止 */
		if (gallery.dataset.galleryReady === '1') {
			return;
		}

		gallery.dataset.galleryReady = '1';

		var track = gallery.querySelector('.ts-gallery__track');

		if (!track) {
			return;
		}

		/* 戻るボタン */
		var prev = document.createElement('button');
		prev.type = 'button';
		prev.className = 'ts-gallery__nav ts-gallery__prev';
		prev.innerHTML = '&#8249;';
		prev.setAttribute('aria-label', '前の画像');

		/* 進むボタン */
		var next = document.createElement('button');
		next.type = 'button';
		next.className = 'ts-gallery__nav ts-gallery__next';
		next.innerHTML = '&#8250;';
		next.setAttribute('aria-label', '次の画像');

		gallery.appendChild(prev);
		gallery.appendChild(next);

		/* 1回に移動する距離 */
		function getStep() {

			var item = track.querySelector('.ts-gallery__item');

			if (!item) {
				return track.clientWidth * 0.85;
			}

			var style = window.getComputedStyle(track);
			var gap = parseFloat(style.columnGap || style.gap) || 0;

			return item.getBoundingClientRect().width + gap;
		}

		/* ボタン状態更新 */
		function updateButtons() {

			var maxScroll =
				track.scrollWidth - track.clientWidth;

			var scrollable = maxScroll > 5;

			gallery.classList.toggle(
				'ts-gallery--scrollable',
				scrollable
			);

			prev.disabled =
				!scrollable ||
				track.scrollLeft <= 5;

			next.disabled =
				!scrollable ||
				track.scrollLeft >= maxScroll - 5;
		}

		prev.addEventListener('click', function () {

			track.scrollBy({
				left: -getStep(),
				behavior: 'smooth'
			});
		});

		next.addEventListener('click', function () {

			track.scrollBy({
				left: getStep(),
				behavior: 'smooth'
			});
		});

		var ticking = false;

		track.addEventListener('scroll', function () {

			if (!ticking) {

				window.requestAnimationFrame(function () {
					updateButtons();
					ticking = false;
				});

				ticking = true;
			}

		}, { passive: true });

		window.addEventListener('resize', updateButtons);

		/* 画像読み込み後にも判定 */
		var images = track.querySelectorAll('img');

		images.forEach(function (image) {
			image.addEventListener('load', updateButtons);
		});

		updateButtons();
	});
});

/* =========================================================
 * Infobox 画像スライダー
 * ========================================================= */

mw.hook('wikipage.content').add(function ($content) {

	$content.find('.ts-infobox-slider').each(function () {

		var slider = this;

		/* 二重初期化を防止 */
		if (slider.dataset.infoboxSliderReady === '1') {
			return;
		}

		slider.dataset.infoboxSliderReady = '1';

		var track =
			slider.querySelector('.ts-infobox-slider__track');

		if (!track) {
			return;
		}

		var slides =
			track.querySelectorAll('.ts-infobox-slider__slide');

		if (!slides.length) {
			return;
		}

		/*
		 * 1枚だけなら矢印を作らない
		 */
		if (slides.length === 1) {
			slider.classList.add(
				'ts-infobox-slider--single'
			);
			return;
		}


		/* -----------------------------------------
		   戻るボタン
		   ----------------------------------------- */

		var prev =
			document.createElement('button');

		prev.type = 'button';

		prev.className =
			'ts-infobox-slider__nav ' +
			'ts-infobox-slider__prev';

		prev.innerHTML = '&#8249;';

		prev.setAttribute(
			'aria-label',
			'前の画像'
		);


		/* -----------------------------------------
		   次へボタン
		   ----------------------------------------- */

		var next =
			document.createElement('button');

		next.type = 'button';

		next.className =
			'ts-infobox-slider__nav ' +
			'ts-infobox-slider__next';

		next.innerHTML = '&#8250;';

		next.setAttribute(
			'aria-label',
			'次の画像'
		);


		slider.appendChild(prev);
		slider.appendChild(next);


		/* -----------------------------------------
		   ボタン状態
		   ----------------------------------------- */

		function updateButtons() {

			var max =
				track.scrollWidth -
				track.clientWidth;

			prev.disabled =
				track.scrollLeft <= 3;

			next.disabled =
				track.scrollLeft >= max - 3;
		}


		/* -----------------------------------------
		   1枚分移動
		   ----------------------------------------- */

		function move(direction) {

			track.scrollBy({
				left:
					direction *
					track.clientWidth,

				behavior: 'smooth'
			});
		}


		prev.addEventListener(
			'click',
			function () {
				move(-1);
			}
		);


		next.addEventListener(
			'click',
			function () {
				move(1);
			}
		);


		track.addEventListener(
			'scroll',
			function () {
				window.requestAnimationFrame(
					updateButtons
				);
			},
			{
				passive: true
			}
		);


		window.addEventListener(
			'resize',
			updateButtons
		);


		updateButtons();

	});

});