미디어위키:Common.js

신사 (토론 | 기여)님의 2026년 8월 20일 (목) 13:03 판

참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.

  • 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)
  • 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)
  • 인터넷 익스플로러 / 엣지: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.
  • 오페라: Ctrl-F5를 입력.
/**
 * MediaWiki 사이트 전체 펼치기/접기 애니메이션
 *
 * 대상:
 * .mw-collapsible
 * .mw-collapsible-toggle
 * .mw-collapsible-content
 */

( function () {
	'use strict';

	var DURATION = 250;

	function getContent( collapsible ) {
		var children = collapsible.children;
		var i;

		for ( i = 0; i < children.length; i++ ) {
			if (
				children[ i ].classList &&
				children[ i ].classList.contains( 'mw-collapsible-content' )
			) {
				return children[ i ];
			}
		}

		/* 직접 자식이 아닌 구조도 대응 */
		return collapsible.querySelector( '.mw-collapsible-content' );
	}

	function updateToggle( toggle, collapsed ) {
		if ( !toggle ) {
			return;
		}

		toggle.classList.toggle(
			'mw-collapsible-toggle-collapsed',
			collapsed
		);

		toggle.classList.toggle(
			'mw-collapsible-toggle-expanded',
			!collapsed
		);

		toggle.setAttribute(
			'aria-expanded',
			collapsed ? 'false' : 'true'
		);

		var text = toggle.querySelector( '.mw-collapsible-text' );

		if ( text ) {
			text.textContent = collapsed ? '펼치기' : '접기';
		}
	}

	function openCollapsible( collapsible, content, toggle ) {
		if ( content.classList.contains( 'mw-collapse-animating' ) ) {
			return;
		}

		collapsible.classList.remove( 'mw-collapsed' );

		content.style.display = 'block';
		content.style.height = 'auto';

		var targetHeight = content.scrollHeight;

		content.style.height = '0px';
		content.style.opacity = '0';

		content.classList.add( 'mw-collapse-animating' );

		/* 강제 reflow */
		content.offsetHeight;

		var animation = content.animate(
			[
				{
					height: '0px',
					opacity: 0
				},
				{
					height: targetHeight + 'px',
					opacity: 1
				}
			],
			{
				duration: DURATION,
				easing: 'ease',
				fill: 'forwards'
			}
		);

		animation.onfinish = function () {
			content.classList.remove( 'mw-collapse-animating' );

			content.style.display = '';
			content.style.height = '';
			content.style.opacity = '';

			animation.cancel();

			updateToggle( toggle, false );
		};
	}

	function closeCollapsible( collapsible, content, toggle ) {
		if ( content.classList.contains( 'mw-collapse-animating' ) ) {
			return;
		}

		var startHeight = content.getBoundingClientRect().height;

		content.style.display = 'block';
		content.classList.add( 'mw-collapse-animating' );

		var animation = content.animate(
			[
				{
					height: startHeight + 'px',
					opacity: 1
				},
				{
					height: '0px',
					opacity: 0
				}
			],
			{
				duration: DURATION,
				easing: 'ease',
				fill: 'forwards'
			}
		);

		animation.onfinish = function () {
			collapsible.classList.add( 'mw-collapsed' );

			content.classList.remove( 'mw-collapse-animating' );

			content.style.display = 'none';
			content.style.height = '';
			content.style.opacity = '';

			animation.cancel();

			updateToggle( toggle, true );
		};
	}

	/*
	 * capture 단계에서 MediaWiki 기본 즉시 열기/닫기를 막고
	 * 우리가 애니메이션을 처리함.
	 */
	document.addEventListener(
		'click',
		function ( event ) {
			var toggle = event.target.closest(
				'.mw-collapsible-toggle'
			);

			if ( !toggle ) {
				return;
			}

			var collapsible = toggle.closest(
				'.mw-collapsible'
			);

			if ( !collapsible ) {
				return;
			}

			var content = getContent( collapsible );

			if ( !content ) {
				return;
			}

			event.preventDefault();
			event.stopPropagation();

			var collapsed =
				collapsible.classList.contains(
					'mw-collapsed'
				) ||
				window.getComputedStyle( content ).display === 'none';

			if ( collapsed ) {
				openCollapsible(
					collapsible,
					content,
					toggle
				);
			} else {
				closeCollapsible(
					collapsible,
					content,
					toggle
				);
			}
		},
		true
	);

}() );