참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.
- 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)
- 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)
- 인터넷 익스플로러 / 엣지: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.
- 오페라: Ctrl-F5를 입력.
/**
* MediaWiki 커스텀 펼치기 / 접기 애니메이션
*
* 지원:
*
* 1. 일반 MediaWiki 구조
*
* .mw-customtoggle-XXX
* #mw-customcollapsible-XXX
* └─ .mw-collapsible-content
*
*
* 2. 동일 ID를 2개 사용하는 전환형 둘러보기 틀
*
* #mw-customcollapsible-XXX ← 처음 보이는 버튼
* └─ .mw-customtoggle-XXX
*
* #mw-customcollapsible-XXX ← 처음 숨겨진 실제 내용
* ├─ .mw-customtoggle-XXX
* └─ table / .sakura-table-wrapper
*
*
* 클릭 시 같은 XXX를 가진 모든 collapsible을
* 각각 현재 상태의 반대로 전환합니다.
*/
( function ( $, mw ) {
'use strict';
var DURATION = 300;
var EASING = 'swing';
/**
* 토글 이름 추출
*
* mw-customtoggle-Flora_LACTEA_01
* →
* Flora_LACTEA_01
*/
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;
}
/**
* attribute selector escape
*/
function escapeAttribute( value ) {
return String( value )
.replace( /\\/g, '\\\\' )
.replace( /"/g, '\\"' );
}
/**
* 동일한 이름을 사용하는
* 모든 collapsible 대상 가져오기
*/
function getTargets( name ) {
var id =
'mw-customcollapsible-' + name;
return document.querySelectorAll(
'[id="' +
escapeAttribute( id ) +
'"]'
);
}
/**
* 직계 .mw-collapsible-content 찾기
*
* 중첩 collapsible까지 잘못 선택하지 않도록
* children만 검사합니다.
*/
function getDirectContent( target ) {
var children = target.children;
var i;
for ( i = 0; i < children.length; i++ ) {
if (
children[ i ].classList.contains(
'mw-collapsible-content'
)
) {
return children[ i ];
}
}
return null;
}
/**
* 실제 애니메이션 대상
*
* MediaWiki 표준:
* .mw-collapsible-content
*
* 현재 LACTEA 구조:
* target 자체
*/
function getAnimatedElement( target ) {
var content =
getDirectContent( target );
if ( content ) {
return content;
}
return target;
}
/**
* 현재 접혀 있는지 확인
*/
function isCollapsed( target, element ) {
if (
target.classList.contains(
'mw-collapsed'
)
) {
return true;
}
return (
window.getComputedStyle(
element
).display === 'none'
);
}
/**
* 펼칠 때 사용할 display 계산
*/
function getOpenDisplay( element ) {
/*
* 이전에 저장된 display가 있으면 사용
*/
var stored =
$( element ).data(
'mwAnimatedDisplay'
);
if ( stored ) {
return stored;
}
var display =
window.getComputedStyle(
element
).display;
/*
* 현재 보이는 상태라면 저장
*/
if (
display &&
display !== 'none'
) {
$( element ).data(
'mwAnimatedDisplay',
display
);
return display;
}
/*
* mw-collapsible 자체를 펼치는 구조
*/
if (
element.classList.contains(
'mw-collapsible'
)
) {
/*
* width가 100%인 내용 영역은 block이
* 가장 자연스럽습니다.
*/
if (
element.style.width === '100%'
) {
return 'block';
}
return 'inline-block';
}
switch ( element.tagName ) {
case 'TABLE':
return 'table';
case 'TR':
return 'table-row';
case 'TD':
case 'TH':
return 'table-cell';
case 'LI':
return 'list-item';
default:
return 'block';
}
}
/**
* 현재 display 값을 기억
*
* 닫기 전에 호출해야 함
*/
function rememberDisplay( element ) {
var display =
window.getComputedStyle(
element
).display;
if (
display &&
display !== 'none'
) {
$( element ).data(
'mwAnimatedDisplay',
display
);
}
}
/**
* 같은 name의 모든 토글에
* aria-expanded 설정
*/
function updateToggleAria(
name,
expanded
) {
var className =
'mw-customtoggle-' + name;
var toggles =
document.getElementsByClassName(
className
);
var i;
for ( i = 0; i < toggles.length; i++ ) {
toggles[ i ].setAttribute(
'aria-expanded',
expanded ?
'true' :
'false'
);
}
}
/**
* 펼치기
*/
function expand(
target,
element
) {
var $element =
$( element );
$element.stop(
true,
false
);
target.classList.remove(
'mw-collapsed'
);
/*
* 표준 MediaWiki 방식
*
* target 안의
* .mw-collapsible-content만 처리
*/
if ( element !== target ) {
$element
.stop( true, false )
.slideDown(
DURATION
);
return;
}
/*
* LACTEA 같은 구조
*
* mw-collapsible 자체가 display:none이므로
* 직접 높이를 애니메이션
*/
var display =
getOpenDisplay(
element
);
$element.css(
{
display: display,
height: 'auto',
overflow: 'hidden'
}
);
var targetHeight =
element.scrollHeight;
$element.css(
{
height: 0,
opacity: 0
}
);
/*
* reflow
*/
void element.offsetHeight;
$element.animate(
{
height:
targetHeight,
opacity:
1
},
{
duration:
DURATION,
easing:
EASING,
complete:
function () {
$element.css(
{
height: '',
overflow: '',
opacity: ''
}
);
}
}
);
}
/**
* 접기
*/
function collapse(
target,
element
) {
var $element =
$( element );
$element.stop(
true,
false
);
/*
* 현재 display를 반드시 먼저 기억
*/
rememberDisplay(
element
);
/*
* 표준 MediaWiki 구조
*/
if ( element !== target ) {
$element.slideUp(
DURATION,
function () {
target.classList.add(
'mw-collapsed'
);
}
);
return;
}
/*
* mw-collapsible 자체가 접히는 구조
*/
var startHeight =
element
.getBoundingClientRect()
.height;
$element.css(
{
height:
startHeight,
overflow:
'hidden',
opacity:
1
}
);
/*
* reflow
*/
void element.offsetHeight;
$element.animate(
{
height: 0,
opacity: 0
},
{
duration:
DURATION,
easing:
EASING,
complete:
function () {
target.classList.add(
'mw-collapsed'
);
$element.css(
{
display:
'none',
height:
'',
overflow:
'',
opacity:
''
}
);
}
}
);
}
/**
* 하나의 name에 연결된 대상 전체 토글
*/
function toggleGroup( toggle ) {
var name =
getToggleName(
toggle
);
if ( !name ) {
return false;
}
var targets =
getTargets(
name
);
if ( !targets.length ) {
return false;
}
var i;
/*
* 핵심:
*
* 하나만 선택하지 않고
* 같은 이름을 가진 모든 target을
* 각자 반대 상태로 변경
*/
for (
i = 0;
i < targets.length;
i++
) {
var target =
targets[ i ];
var element =
getAnimatedElement(
target
);
if (
isCollapsed(
target,
element
)
) {
expand(
target,
element
);
} else {
collapse(
target,
element
);
}
}
/*
* 이 형태에서는 보이는 토글과 숨겨진 토글이
* 교대하므로 aria-expanded를 특정 하나에
* 일괄 적용하는 것은 생략합니다.
*/
return true;
}
/**
* 클릭
*
* MediaWiki 기본 customtoggle보다
* 먼저 실행
*/
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();
toggleGroup(
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();
toggleGroup(
toggle
);
},
true
);
}( jQuery, mediaWiki ) );