편집 요약 없음 |
편집 요약 없음 |
||
| 1번째 줄: | 1번째 줄: | ||
/** | |||
* MediaWiki 커스텀 펼치기 / 접기 애니메이션 | |||
* | |||
* 지원 구조: | |||
* | |||
* 1. | |||
* .mw-customtoggle-XXX | |||
* #mw-customcollapsible-XXX | |||
* └─ .mw-collapsible-content | |||
* | |||
* 2. | |||
* .mw-customtoggle-XXX | |||
* #mw-customcollapsible-XXX | |||
* ├─ .mw-customtoggle-XXX | |||
* └─ table / .sakura-table-wrapper / 기타 콘텐츠 | |||
* | |||
* 동일한 mw-customcollapsible-* ID가 여러 개 존재하는 | |||
* 둘러보기 틀 형태도 지원. | |||
*/ | |||
( function ( $, mw ) { | |||
'use strict'; | |||
var DURATION = 300; | |||
var EASING = 'swing'; | |||
var DATA_TARGET = | |||
'mwAnimatedCollapseTarget'; | |||
var DATA_DISPLAY = | |||
'mwAnimatedNaturalDisplay'; | |||
/** | |||
* 토글 클래스에서 이름 추출 | |||
* | |||
* 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; | |||
} | |||
/** | |||
* CSS attribute selector escape | |||
*/ | |||
function escapeAttribute( value ) { | |||
return String( value ) | |||
.replace( /\\/g, '\\\\' ) | |||
.replace( /"/g, '\\"' ); | |||
} | |||
/** | |||
* 해당 요소의 직계 mw-collapsible-content 찾기 | |||
* | |||
* 중첩된 collapsible을 잘못 잡지 않도록 | |||
* querySelector가 아니라 children 검사 | |||
*/ | |||
function getDirectCollapsibleContent( 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; | |||
} | |||
/** | |||
* 실제로 펼치고 접을 요소 결정 | |||
* | |||
* .mw-collapsible-content가 있으면 그것을 사용. | |||
* | |||
* 없으면 target 자체가 display:none 되는 구조이므로 | |||
* target 자체를 애니메이션. | |||
*/ | |||
function getAnimatedElement( target ) { | |||
var content = | |||
getDirectCollapsibleContent( target ); | |||
if ( content ) { | |||
return content; | |||
} | |||
return target; | |||
} | |||
/** | |||
* candidate가 단순한 버튼 wrapper인지 판단 | |||
*/ | |||
function isToggleOnlyWrapper( candidate ) { | |||
var children = candidate.children; | |||
if ( children.length !== 1 ) { | |||
return false; | |||
} | |||
return !!getToggleName( | |||
children[ 0 ] | |||
); | |||
} | |||
/** | |||
* 동일한 ID가 여러 개 있어도 실제 펼침 영역 선택 | |||
*/ | |||
function findTarget( name ) { | |||
if ( !name ) { | |||
return null; | |||
} | |||
var id = | |||
'mw-customcollapsible-' + name; | |||
var candidates = | |||
document.querySelectorAll( | |||
'[id="' + | |||
escapeAttribute( id ) + | |||
'"]' | |||
); | |||
if ( !candidates.length ) { | |||
return null; | |||
} | |||
/* | |||
* 이전에 실제 target으로 판정한 요소 우선 | |||
*/ | |||
var i; | |||
for ( i = 0; i < candidates.length; i++ ) { | |||
if ( | |||
$( candidates[ i ] ).data( | |||
DATA_TARGET | |||
) | |||
) { | |||
return candidates[ i ]; | |||
} | |||
} | |||
if ( candidates.length === 1 ) { | |||
$( candidates[ 0 ] ).data( | |||
DATA_TARGET, | |||
true | |||
); | |||
return candidates[ 0 ]; | |||
} | |||
var best = null; | |||
var bestScore = -Infinity; | |||
for ( i = 0; i < candidates.length; i++ ) { | |||
var candidate = candidates[ i ]; | |||
var score = 0; | |||
/* | |||
* 초기 상태가 mw-collapsed라면 | |||
* 실제 내용 영역일 가능성이 매우 높음 | |||
*/ | |||
if ( | |||
candidate.classList.contains( | |||
'mw-collapsed' | |||
) | |||
) { | |||
score += 10000; | |||
} | |||
/* | |||
* MediaWiki 표준 content wrapper | |||
*/ | |||
if ( | |||
getDirectCollapsibleContent( | |||
candidate | |||
) | |||
) { | |||
score += 8000; | |||
} | |||
/* | |||
* Sakura 표 wrapper | |||
*/ | |||
if ( | |||
candidate.querySelector( | |||
':scope > .sakura-table-wrapper' | |||
) | |||
) { | |||
score += 6000; | |||
} | |||
/* | |||
* 실제 표 포함 | |||
*/ | |||
if ( | |||
candidate.querySelector( | |||
'table' | |||
) | |||
) { | |||
score += 3000; | |||
} | |||
}(jQuery)); | |||
if ( | |||
candidate.querySelector( | |||
'.wikitable' | |||
) | |||
) { | |||
score += 1000; | |||
} | |||
/* | |||
* 버튼 하나만 들어간 wrapper는 감점 | |||
*/ | |||
if ( | |||
isToggleOnlyWrapper( | |||
candidate | |||
) | |||
) { | |||
score -= 10000; | |||
} | |||
/* | |||
* 내부 콘텐츠가 많을수록 가산 | |||
*/ | |||
score += | |||
candidate.querySelectorAll( '*' ) | |||
.length; | |||
if ( score > bestScore ) { | |||
bestScore = score; | |||
best = candidate; | |||
} | |||
} | |||
if ( best ) { | |||
$( best ).data( | |||
DATA_TARGET, | |||
true | |||
); | |||
} | |||
return best; | |||
} | |||
/** | |||
* 자연스러운 display 값 계산 | |||
* | |||
* 현재 display:none인 경우 직접 태그별 기본값 사용 | |||
*/ | |||
function getNaturalDisplay( element ) { | |||
var saved = | |||
$( element ).data( | |||
DATA_DISPLAY | |||
); | |||
if ( saved ) { | |||
return saved; | |||
} | |||
var display = | |||
window.getComputedStyle( | |||
element | |||
).display; | |||
if ( | |||
display && | |||
display !== 'none' | |||
) { | |||
$( element ).data( | |||
DATA_DISPLAY, | |||
display | |||
); | |||
return display; | |||
} | |||
switch ( element.tagName ) { | |||
case 'TABLE': | |||
display = 'table'; | |||
break; | |||
case 'TBODY': | |||
display = 'table-row-group'; | |||
break; | |||
case 'THEAD': | |||
display = 'table-header-group'; | |||
break; | |||
case 'TFOOT': | |||
display = 'table-footer-group'; | |||
break; | |||
case 'TR': | |||
display = 'table-row'; | |||
break; | |||
case 'TD': | |||
case 'TH': | |||
display = 'table-cell'; | |||
break; | |||
case 'LI': | |||
display = 'list-item'; | |||
break; | |||
default: | |||
/* | |||
* 인라인 스타일상 inline-block인 | |||
* collapsible도 많으므로 먼저 확인 | |||
*/ | |||
if ( | |||
element.style.display && | |||
element.style.display !== 'none' | |||
) { | |||
display = | |||
element.style.display; | |||
} else { | |||
display = 'block'; | |||
} | |||
break; | |||
} | |||
$( element ).data( | |||
DATA_DISPLAY, | |||
display | |||
); | |||
return display; | |||
} | |||
/** | |||
* 현재 접힘 상태 | |||
*/ | |||
function isCollapsed( | |||
target, | |||
animatedElement | |||
) { | |||
if ( | |||
target.classList.contains( | |||
'mw-collapsed' | |||
) | |||
) { | |||
return true; | |||
} | |||
return ( | |||
window.getComputedStyle( | |||
animatedElement | |||
).display === 'none' | |||
); | |||
} | |||
/** | |||
* 같은 name을 가진 모든 toggle의 aria-expanded 변경 | |||
*/ | |||
function updateToggleState( | |||
name, | |||
expanded | |||
) { | |||
var prefix = | |||
'mw-customtoggle-' + name; | |||
var toggles = | |||
document.getElementsByClassName( | |||
prefix | |||
); | |||
var i; | |||
for ( | |||
i = 0; | |||
i < toggles.length; | |||
i++ | |||
) { | |||
toggles[ i ].setAttribute( | |||
'aria-expanded', | |||
expanded ? 'true' : 'false' | |||
); | |||
} | |||
} | |||
/** | |||
* 펼치기 | |||
*/ | |||
function expand( | |||
name, | |||
target, | |||
animatedElement | |||
) { | |||
var $element = | |||
$( animatedElement ); | |||
/* | |||
* 기존 애니메이션 즉시 중단 | |||
*/ | |||
$element.stop( | |||
true, | |||
false | |||
); | |||
target.classList.remove( | |||
'mw-collapsed' | |||
); | |||
/* | |||
* target 자체가 애니메이션 대상인 경우 | |||
* | |||
* 기존 inline style="display:none"을 | |||
* slideDown이 처리할 수 있도록 복구 | |||
*/ | |||
if ( | |||
animatedElement === target | |||
) { | |||
var naturalDisplay = | |||
getNaturalDisplay( | |||
target | |||
); | |||
/* | |||
* jQuery slideDown은 inline-block 같은 | |||
* display 복원에서 상황에 따라 문제가 있으므로 | |||
* display를 직접 설정한 다음 height를 애니메이션 | |||
*/ | |||
$element.css( | |||
'display', | |||
naturalDisplay | |||
); | |||
$element.css( | |||
{ | |||
overflow: 'hidden', | |||
height: 0, | |||
opacity: 0 | |||
} | |||
); | |||
var targetHeight = | |||
animatedElement.scrollHeight; | |||
$element.animate( | |||
{ | |||
height: | |||
targetHeight, | |||
opacity: 1 | |||
}, | |||
{ | |||
duration: | |||
DURATION, | |||
easing: | |||
EASING, | |||
complete: | |||
function () { | |||
$element.css( | |||
{ | |||
height: '', | |||
overflow: '', | |||
opacity: '' | |||
} | |||
); | |||
updateToggleState( | |||
name, | |||
true | |||
); | |||
} | |||
} | |||
); | |||
} else { | |||
/* | |||
* 표준 MediaWiki 구조 | |||
* | |||
* mw-collapsible-content만 펼침 | |||
*/ | |||
$element | |||
.stop( true, true ) | |||
.slideDown( | |||
DURATION, | |||
function () { | |||
$element.css( | |||
{ | |||
height: '', | |||
overflow: '' | |||
} | |||
); | |||
updateToggleState( | |||
name, | |||
true | |||
); | |||
} | |||
); | |||
} | |||
} | |||
/** | |||
* 접기 | |||
*/ | |||
function collapse( | |||
name, | |||
target, | |||
animatedElement | |||
) { | |||
var $element = | |||
$( animatedElement ); | |||
$element.stop( | |||
true, | |||
false | |||
); | |||
/* | |||
* target 자체가 display:none 되는 구조 | |||
*/ | |||
if ( | |||
animatedElement === target | |||
) { | |||
var startHeight = | |||
animatedElement | |||
.getBoundingClientRect() | |||
.height; | |||
$element.css( | |||
{ | |||
height: | |||
startHeight, | |||
overflow: | |||
'hidden', | |||
opacity: | |||
1 | |||
} | |||
); | |||
$element.animate( | |||
{ | |||
height: 0, | |||
opacity: 0 | |||
}, | |||
{ | |||
duration: | |||
DURATION, | |||
easing: | |||
EASING, | |||
complete: | |||
function () { | |||
target.classList.add( | |||
'mw-collapsed' | |||
); | |||
$element.css( | |||
{ | |||
display: | |||
'none', | |||
height: | |||
'', | |||
overflow: | |||
'', | |||
opacity: | |||
'' | |||
} | |||
); | |||
updateToggleState( | |||
name, | |||
false | |||
); | |||
} | |||
} | |||
); | |||
} else { | |||
/* | |||
* 표준 mw-collapsible-content | |||
*/ | |||
$element.slideUp( | |||
DURATION, | |||
function () { | |||
target.classList.add( | |||
'mw-collapsed' | |||
); | |||
updateToggleState( | |||
name, | |||
false | |||
); | |||
} | |||
); | |||
} | |||
} | |||
/** | |||
* 토글 실행 | |||
*/ | |||
function toggleCollapsible( | |||
toggle | |||
) { | |||
var name = | |||
getToggleName( | |||
toggle | |||
); | |||
if ( !name ) { | |||
return false; | |||
} | |||
var target = | |||
findTarget( | |||
name | |||
); | |||
if ( !target ) { | |||
return false; | |||
} | |||
var animatedElement = | |||
getAnimatedElement( | |||
target | |||
); | |||
if ( | |||
isCollapsed( | |||
target, | |||
animatedElement | |||
) | |||
) { | |||
expand( | |||
name, | |||
target, | |||
animatedElement | |||
); | |||
} else { | |||
collapse( | |||
name, | |||
target, | |||
animatedElement | |||
); | |||
} | |||
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(); | |||
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 | |||
); | |||
}( jQuery, mediaWiki ) ); | |||
2026년 8월 20일 (목) 14:06 판
/**
* MediaWiki 커스텀 펼치기 / 접기 애니메이션
*
* 지원 구조:
*
* 1.
* .mw-customtoggle-XXX
* #mw-customcollapsible-XXX
* └─ .mw-collapsible-content
*
* 2.
* .mw-customtoggle-XXX
* #mw-customcollapsible-XXX
* ├─ .mw-customtoggle-XXX
* └─ table / .sakura-table-wrapper / 기타 콘텐츠
*
* 동일한 mw-customcollapsible-* ID가 여러 개 존재하는
* 둘러보기 틀 형태도 지원.
*/
( function ( $, mw ) {
'use strict';
var DURATION = 300;
var EASING = 'swing';
var DATA_TARGET =
'mwAnimatedCollapseTarget';
var DATA_DISPLAY =
'mwAnimatedNaturalDisplay';
/**
* 토글 클래스에서 이름 추출
*
* 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;
}
/**
* CSS attribute selector escape
*/
function escapeAttribute( value ) {
return String( value )
.replace( /\\/g, '\\\\' )
.replace( /"/g, '\\"' );
}
/**
* 해당 요소의 직계 mw-collapsible-content 찾기
*
* 중첩된 collapsible을 잘못 잡지 않도록
* querySelector가 아니라 children 검사
*/
function getDirectCollapsibleContent( 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;
}
/**
* 실제로 펼치고 접을 요소 결정
*
* .mw-collapsible-content가 있으면 그것을 사용.
*
* 없으면 target 자체가 display:none 되는 구조이므로
* target 자체를 애니메이션.
*/
function getAnimatedElement( target ) {
var content =
getDirectCollapsibleContent( target );
if ( content ) {
return content;
}
return target;
}
/**
* candidate가 단순한 버튼 wrapper인지 판단
*/
function isToggleOnlyWrapper( candidate ) {
var children = candidate.children;
if ( children.length !== 1 ) {
return false;
}
return !!getToggleName(
children[ 0 ]
);
}
/**
* 동일한 ID가 여러 개 있어도 실제 펼침 영역 선택
*/
function findTarget( name ) {
if ( !name ) {
return null;
}
var id =
'mw-customcollapsible-' + name;
var candidates =
document.querySelectorAll(
'[id="' +
escapeAttribute( id ) +
'"]'
);
if ( !candidates.length ) {
return null;
}
/*
* 이전에 실제 target으로 판정한 요소 우선
*/
var i;
for ( i = 0; i < candidates.length; i++ ) {
if (
$( candidates[ i ] ).data(
DATA_TARGET
)
) {
return candidates[ i ];
}
}
if ( candidates.length === 1 ) {
$( candidates[ 0 ] ).data(
DATA_TARGET,
true
);
return candidates[ 0 ];
}
var best = null;
var bestScore = -Infinity;
for ( i = 0; i < candidates.length; i++ ) {
var candidate = candidates[ i ];
var score = 0;
/*
* 초기 상태가 mw-collapsed라면
* 실제 내용 영역일 가능성이 매우 높음
*/
if (
candidate.classList.contains(
'mw-collapsed'
)
) {
score += 10000;
}
/*
* MediaWiki 표준 content wrapper
*/
if (
getDirectCollapsibleContent(
candidate
)
) {
score += 8000;
}
/*
* Sakura 표 wrapper
*/
if (
candidate.querySelector(
':scope > .sakura-table-wrapper'
)
) {
score += 6000;
}
/*
* 실제 표 포함
*/
if (
candidate.querySelector(
'table'
)
) {
score += 3000;
}
if (
candidate.querySelector(
'.wikitable'
)
) {
score += 1000;
}
/*
* 버튼 하나만 들어간 wrapper는 감점
*/
if (
isToggleOnlyWrapper(
candidate
)
) {
score -= 10000;
}
/*
* 내부 콘텐츠가 많을수록 가산
*/
score +=
candidate.querySelectorAll( '*' )
.length;
if ( score > bestScore ) {
bestScore = score;
best = candidate;
}
}
if ( best ) {
$( best ).data(
DATA_TARGET,
true
);
}
return best;
}
/**
* 자연스러운 display 값 계산
*
* 현재 display:none인 경우 직접 태그별 기본값 사용
*/
function getNaturalDisplay( element ) {
var saved =
$( element ).data(
DATA_DISPLAY
);
if ( saved ) {
return saved;
}
var display =
window.getComputedStyle(
element
).display;
if (
display &&
display !== 'none'
) {
$( element ).data(
DATA_DISPLAY,
display
);
return display;
}
switch ( element.tagName ) {
case 'TABLE':
display = 'table';
break;
case 'TBODY':
display = 'table-row-group';
break;
case 'THEAD':
display = 'table-header-group';
break;
case 'TFOOT':
display = 'table-footer-group';
break;
case 'TR':
display = 'table-row';
break;
case 'TD':
case 'TH':
display = 'table-cell';
break;
case 'LI':
display = 'list-item';
break;
default:
/*
* 인라인 스타일상 inline-block인
* collapsible도 많으므로 먼저 확인
*/
if (
element.style.display &&
element.style.display !== 'none'
) {
display =
element.style.display;
} else {
display = 'block';
}
break;
}
$( element ).data(
DATA_DISPLAY,
display
);
return display;
}
/**
* 현재 접힘 상태
*/
function isCollapsed(
target,
animatedElement
) {
if (
target.classList.contains(
'mw-collapsed'
)
) {
return true;
}
return (
window.getComputedStyle(
animatedElement
).display === 'none'
);
}
/**
* 같은 name을 가진 모든 toggle의 aria-expanded 변경
*/
function updateToggleState(
name,
expanded
) {
var prefix =
'mw-customtoggle-' + name;
var toggles =
document.getElementsByClassName(
prefix
);
var i;
for (
i = 0;
i < toggles.length;
i++
) {
toggles[ i ].setAttribute(
'aria-expanded',
expanded ? 'true' : 'false'
);
}
}
/**
* 펼치기
*/
function expand(
name,
target,
animatedElement
) {
var $element =
$( animatedElement );
/*
* 기존 애니메이션 즉시 중단
*/
$element.stop(
true,
false
);
target.classList.remove(
'mw-collapsed'
);
/*
* target 자체가 애니메이션 대상인 경우
*
* 기존 inline style="display:none"을
* slideDown이 처리할 수 있도록 복구
*/
if (
animatedElement === target
) {
var naturalDisplay =
getNaturalDisplay(
target
);
/*
* jQuery slideDown은 inline-block 같은
* display 복원에서 상황에 따라 문제가 있으므로
* display를 직접 설정한 다음 height를 애니메이션
*/
$element.css(
'display',
naturalDisplay
);
$element.css(
{
overflow: 'hidden',
height: 0,
opacity: 0
}
);
var targetHeight =
animatedElement.scrollHeight;
$element.animate(
{
height:
targetHeight,
opacity: 1
},
{
duration:
DURATION,
easing:
EASING,
complete:
function () {
$element.css(
{
height: '',
overflow: '',
opacity: ''
}
);
updateToggleState(
name,
true
);
}
}
);
} else {
/*
* 표준 MediaWiki 구조
*
* mw-collapsible-content만 펼침
*/
$element
.stop( true, true )
.slideDown(
DURATION,
function () {
$element.css(
{
height: '',
overflow: ''
}
);
updateToggleState(
name,
true
);
}
);
}
}
/**
* 접기
*/
function collapse(
name,
target,
animatedElement
) {
var $element =
$( animatedElement );
$element.stop(
true,
false
);
/*
* target 자체가 display:none 되는 구조
*/
if (
animatedElement === target
) {
var startHeight =
animatedElement
.getBoundingClientRect()
.height;
$element.css(
{
height:
startHeight,
overflow:
'hidden',
opacity:
1
}
);
$element.animate(
{
height: 0,
opacity: 0
},
{
duration:
DURATION,
easing:
EASING,
complete:
function () {
target.classList.add(
'mw-collapsed'
);
$element.css(
{
display:
'none',
height:
'',
overflow:
'',
opacity:
''
}
);
updateToggleState(
name,
false
);
}
}
);
} else {
/*
* 표준 mw-collapsible-content
*/
$element.slideUp(
DURATION,
function () {
target.classList.add(
'mw-collapsed'
);
updateToggleState(
name,
false
);
}
);
}
}
/**
* 토글 실행
*/
function toggleCollapsible(
toggle
) {
var name =
getToggleName(
toggle
);
if ( !name ) {
return false;
}
var target =
findTarget(
name
);
if ( !target ) {
return false;
}
var animatedElement =
getAnimatedElement(
target
);
if (
isCollapsed(
target,
animatedElement
)
) {
expand(
name,
target,
animatedElement
);
} else {
collapse(
name,
target,
animatedElement
);
}
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();
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
);
}( jQuery, mediaWiki ) );