참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.
- 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)
- 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)
- 인터넷 익스플로러 / 엣지: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.
- 오페라: Ctrl-F5를 입력.
/**
* MediaWiki 커스텀 펼치기/접기 애니메이션
*
* 지원 예:
*
* .mw-customtoggle-KSC_LEADER
* ↕
* .mw-customcollapsible-KSC_LEADER
*
* 식별자 이름은 자유롭게 사용 가능.
*/
( function () {
'use strict';
var DURATION = 300;
var ANIMATING_CLASS = 'mw-custom-collapse-animating';
/**
* 토글 요소에서 식별자 추출
*
* 예:
* mw-customtoggle-KSC_LEADER
* → KSC_LEADER
*/
function getToggleName( toggle ) {
var prefix = 'mw-customtoggle-';
var classes = toggle.classList;
var i;
for ( i = 0; i < classes.length; i++ ) {
if ( classes[ i ].indexOf( prefix ) === 0 ) {
return classes[ i ].substring( prefix.length );
}
}
return null;
}
/**
* CSS selector escape
*/
function escapeSelector( value ) {
if ( window.CSS && CSS.escape ) {
return CSS.escape( value );
}
return value.replace(
/([!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~])/g,
'\\\\$1'
);
}
/**
* 식별자에 대응하는 collapsible 대상 찾기
*/
function getTarget( name ) {
if ( !name ) {
return null;
}
var target = document.querySelector(
'.mw-customcollapsible-' +
escapeSelector( name )
);
if ( target ) {
return target;
}
target = document.getElementById(
'mw-customcollapsible-' + name
);
return target;
}
/**
* 실제 애니메이션을 적용할 콘텐츠 찾기
*/
function getContent( target ) {
var content = target.querySelector(
'.mw-collapsible-content'
);
if ( content ) {
return content;
}
return target;
}
/**
* 요소 원래 display 타입 보존
*
* table 요소에 display:block을 강제하면
* 레이아웃이 깨질 수 있으므로 태그별 기본값 사용.
*/
function getNaturalDisplay( element ) {
switch ( element.tagName ) {
case 'TABLE':
return 'table';
case 'TBODY':
return 'table-row-group';
case 'THEAD':
return 'table-header-group';
case 'TFOOT':
return 'table-footer-group';
case 'TR':
return 'table-row';
case 'TD':
case 'TH':
return 'table-cell';
case 'COLGROUP':
return 'table-column-group';
case 'COL':
return 'table-column';
case 'CAPTION':
return 'table-caption';
case 'LI':
return 'list-item';
default:
return 'block';
}
}
/**
* 현재 접혀있는지 확인
*/
function isCollapsed( target, content ) {
if ( target.classList.contains( 'mw-collapsed' ) ) {
return true;
}
return window.getComputedStyle( content ).display === 'none';
}
/**
* 펼치기
*/
function expand( target, content, toggle ) {
if ( content.classList.contains( ANIMATING_CLASS ) ) {
return;
}
content.classList.add( ANIMATING_CLASS );
target.classList.remove( 'mw-collapsed' );
/*
* display:none 상태에서는 높이를 구할 수 없으므로
* 원래 요소 유형에 맞는 display로 임시 복원
*/
content.style.display = getNaturalDisplay( content );
content.style.height = 'auto';
content.style.overflow = 'hidden';
var targetHeight = content.scrollHeight;
/*
* 0 높이에서 시작
*/
content.style.height = '0px';
/*
* 강제 reflow
*/
content.offsetHeight;
var animation = content.animate(
[
{
height: '0px'
},
{
height: targetHeight + 'px'
}
],
{
duration: DURATION,
easing: 'ease',
fill: 'forwards'
}
);
animation.onfinish = function () {
content.classList.remove( ANIMATING_CLASS );
/*
* 원래 CSS가 다시 레이아웃을 결정하도록
* 인라인 스타일 제거
*/
content.style.display = '';
content.style.height = '';
content.style.overflow = '';
toggle.setAttribute(
'aria-expanded',
'true'
);
animation.cancel();
};
animation.oncancel = function () {
content.classList.remove( ANIMATING_CLASS );
};
}
/**
* 접기
*/
function collapse( target, content, toggle ) {
if ( content.classList.contains( ANIMATING_CLASS ) ) {
return;
}
content.classList.add( ANIMATING_CLASS );
/*
* 현재 높이 측정
*/
var startHeight =
content.getBoundingClientRect().height;
/*
* 애니메이션 동안 display 타입 유지
*/
content.style.display = getNaturalDisplay( content );
content.style.height = startHeight + 'px';
content.style.overflow = 'hidden';
/*
* 강제 reflow
*/
content.offsetHeight;
var animation = content.animate(
[
{
height: startHeight + 'px'
},
{
height: '0px'
}
],
{
duration: DURATION,
easing: 'ease',
fill: 'forwards'
}
);
animation.onfinish = function () {
target.classList.add( 'mw-collapsed' );
content.classList.remove( ANIMATING_CLASS );
/*
* 접힌 상태 유지
*/
content.style.display = 'none';
/*
* height와 overflow만 제거
*/
content.style.height = '';
content.style.overflow = '';
toggle.setAttribute(
'aria-expanded',
'false'
);
animation.cancel();
};
animation.oncancel = function () {
content.classList.remove( ANIMATING_CLASS );
};
}
/**
* 실제 토글 처리
*/
function toggleCollapsible( toggle ) {
var name = getToggleName( toggle );
if ( !name ) {
return false;
}
var target = getTarget( name );
if ( !target ) {
return false;
}
var content = getContent( target );
if ( !content ) {
return false;
}
if ( isCollapsed( target, content ) ) {
expand(
target,
content,
toggle
);
} else {
collapse(
target,
content,
toggle
);
}
return true;
}
/**
* 마우스 클릭
*
* MediaWiki 기본 customtoggle보다 먼저 실행하기 위해
* capture=true 사용
*/
document.addEventListener(
'click',
function ( event ) {
var toggle = event.target.closest(
'.mw-customtoggle'
);
if ( !toggle ) {
return;
}
if ( !getToggleName( toggle ) ) {
return;
}
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
toggleCollapsible( toggle );
},
true
);
/**
* Enter / Space 키 지원
*/
document.addEventListener(
'keydown',
function ( event ) {
if (
event.key !== 'Enter' &&
event.key !== ' '
) {
return;
}
var toggle = event.target.closest(
'.mw-customtoggle'
);
if ( !toggle ) {
return;
}
if ( !getToggleName( toggle ) ) {
return;
}
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
toggleCollapsible( toggle );
},
true
);
}() );