미디어위키:Common.js: 두 판 사이의 차이

편집 요약 없음
편집 요약 없음
 
(같은 사용자의 중간 판 34개는 보이지 않습니다)
1번째 줄: 1번째 줄:
/**
/* MediaWiki:Common.js */
* 이 스크립트는 위키백과 전체에 적용됩니다. 고칠 때는 주의해주세요.
mw.hook('wikipage.content').add(function ($content) {
* [[위키백과:위키프로젝트 시스템]] 참고
*
* 스크립트를 넣을 때는 충분한 설명, 출처를 넣어주세요! 이후 관리가 어려워집니다.
**/


mw.loader.using( ['mediawiki.util', 'mediawiki.notify', 'jquery.client'], function () {
    var initialized = {};
/* Begin of mw.loader.using callback */


/**
    $content.find('[class*="mw-customtoggle-"]').each(function () {
* Map addPortletLink to mw.util
        var classList = (this.className || '').split(/\s+/);
*
* @deprecated: Use mw.util.addPortletLink instead.
*/
mw.log.deprecate(
window,
'addPortletLink',
mw.util.addPortletLink,
'Use mw.util.addPortletLink instead'
);


/**
        classList.forEach(function (cls) {
* Extract a URL parameter from the current URL
            if (cls.indexOf('mw-customtoggle-') !== 0) {
*
                return;
* @deprecated: Use mw.util.getParamValue with proper escaping
            }
*/
mw.log.deprecate(
window,
'getURLParamValue',
mw.util.getParamValue,
'Use mw.util.getParamValue instead'
);


/**
            var suffix = cls.substring('mw-customtoggle-'.length);
* Test if an element has a certain class
*
* @deprecated: Use $(element).hasClass() instead.
*/
mw.log.deprecate(
window,
'hasClass',
function ( element, className ) {
return $( element ).hasClass( className );
},
'Use jQuery.hasClass() instead'
);


/**
            if (initialized[suffix]) {
* @source www.mediawiki.org/wiki/Snippets/Load_JS_and_CSS_by_URL
                return;
* @rev 5
            }
*/


// CSS
            initialized[suffix] = true;
var extraCSS = mw.util.getParamValue( 'withCSS' );


if ( extraCSS ) {
            var targetId = 'mw-customcollapsible-' + suffix;
if ( extraCSS.match( /^MediaWiki:[^&<>=%#]*\.css$/ ) ) {
importStylesheet( extraCSS );
} else {
mw.notify(
'Only pages from the MediaWiki namespace are allowed.',
{
title: 'Invalid withCSS value'
}
);
}
}


// JS
            /*
var extraJS = mw.util.getParamValue( 'withJS' );
            * 중복 ID가 있을 수 있으므로
            * #id 대신 attribute selector 사용
            */
            var $targets = $content.find('[id="' + targetId + '"]');


if ( extraJS ) {
            if (!$targets.length) {
if ( extraJS.match( /^MediaWiki:[^&<>=%#]*\.js$/ ) ) {
                return;
importScript( extraJS );
            }
} else {
mw.notify(
'Only pages from the MediaWiki namespace are allowed.',
{
title: 'Invalid withJS value'
}
);
}
}


/**
* Import more specific scripts if necessary
*/


if ( mw.config.get( 'wgNamespaceNumber' ) === 6 ) {
            /*
/* file description page scripts */
            * =====================================================
importScript( 'MediaWiki:Common.js/file.js' );
            * 특수형
}
            *
            * 아나운서 표처럼:
            *
            * [상단 버튼 wrapper]
            * [실제 내용 패널]
            *
            * 두 요소가 같은 ID를 공유하고,
            * 실제 패널 안에 wikitable이 있는 구조
            * =====================================================
            */
            var $specialPanel = $targets.filter(function () {
                return $(this).find('table.wikitable').length > 0;
            });


/* ([[위키백과:관리자 요청/2007년 5월#스크립트 추가 요청]]) */
            if ($targets.length > 1 && $specialPanel.length) {
/** Collapsible tables *******************************************************
                initStackedCollapsible(
*
                    $content,
* Description: Allows tables to be collapsed, showing only the header. See
                    cls,
*              [[:en:Wikipedia:NavFrame]].
                    $targets
* Maintainers: [[:en:User:R. Koot]]
                );
*/


var autoCollapse = 2;
                return;
var collapseCaption = '숨기기';
            }
var expandCaption = '보이기';


window.collapseTable = function ( tableIndex ) {
var Button = document.getElementById(
'collapseButton' + tableIndex
);


var Table = document.getElementById(
            /*
'collapsibleTable' + tableIndex
            * =====================================================
);
            * 일반 MediaWiki collapsible
            * =====================================================
            */
            initNormalCollapsible(
                $content,
                cls,
                $targets.first()
            );
        });
    });


if ( !Table || !Button ) {
return false;
}


var Rows = Table.rows;
var i;


if ( Button.firstChild.data === collapseCaption ) {
    /*
    * =============================================================
    * 일반 펼치기 · 접기
    * =============================================================
    */
    function initNormalCollapsible($content, cls, $target) {


for ( i = 1; i < Rows.length; i++ ) {
        var $toggles = $content.find('.' + cls);
Rows[ i ].style.display = 'none';
}


Button.firstChild.data = expandCaption;
        /*
        * 일반 MediaWiki 구조:
        *
        * .mw-collapsible
        *  └ .mw-collapsible-content
        *
        * content가 있으면 content만 애니메이션
        */
        var $contentTarget = $target.children('.mw-collapsible-content');


} else {
        if (!$contentTarget.length) {
            $contentTarget = $target.find('.mw-collapsible-content').first();
        }


for ( i = 1; i < Rows.length; i++ ) {
        var $animTarget = $contentTarget.length
Rows[ i ].style.display =
            ? $contentTarget
Rows[ 0 ].style.display;
            : $target;
}


Button.firstChild.data = collapseCaption;
}
};


function createCollapseButtons() {
        /*
var tableIndex = 0;
        * 현재 상태를 기준으로 초기 aria 설정
var NavigationBoxes = {};
        */
var Tables = document.getElementsByTagName( 'table' );
        var initiallyOpen = $animTarget.is(':visible');
var i;


function handleButtonLink( index, e ) {
        $toggles.attr(
window.collapseTable( index );
            'aria-expanded',
e.preventDefault();
            initiallyOpen ? 'true' : 'false'
}
        );


for ( i = 0; i < Tables.length; i++ ) {


if ( $( Tables[ i ] ).hasClass( 'collapsible' ) ) {
        $toggles
            .off('click.smoothSlide')
            .on('click.smoothSlide', function (e) {


/*
                e.preventDefault();
* only add button and increment count
                e.stopImmediatePropagation();
* if there is a header row to work with
*/
var HeaderRow =
Tables[ i ].getElementsByTagName( 'tr' )[ 0 ];


if ( !HeaderRow ) {
continue;
}


var Header =
                /*
HeaderRow.getElementsByTagName( 'th' )[ 0 ];
                * 애니메이션 중 재클릭 방지
                */
                if ($animTarget.is(':animated')) {
                    return false;
                }


if ( !Header ) {
continue;
}


NavigationBoxes[ tableIndex ] = Tables[ i ];
                var opening = !$animTarget.is(':visible');


Tables[ i ].setAttribute(
'id',
'collapsibleTable' + tableIndex
);


var Button =
                /*
document.createElement( 'span' );
                * -------------------------------------------------
                * 펼치기
                * -------------------------------------------------
                */
                if (opening) {


var ButtonLink =
                    /*
document.createElement( 'a' );
                    * MediaWiki collapsed 상태 제거
                    */
                    $target.removeClass('mw-collapsed');


var ButtonText =
document.createTextNode(
collapseCaption
);


/*
                    /*
* Styles are declared in Common.css
                    * 내용만 펼침
*/
                    */
Button.className = 'collapseButton';
                    $animTarget
                        .stop(true, true)
                        .hide()
                        .slideDown(250, function () {


ButtonLink.style.color =
                            /*
Header.style.color;
                            * jQuery 애니메이션 inline style 정리
                            */
                            $(this).css({
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });
                        });


ButtonLink.setAttribute(
'id',
'collapseButton' + tableIndex
);


ButtonLink.setAttribute(
                    $toggles.attr('aria-expanded', 'true');
'href',
                }
'#'
);


$( ButtonLink ).on(
'click',
$.proxy(
handleButtonLink,
ButtonLink,
tableIndex
)
);


ButtonLink.appendChild(
                /*
ButtonText
                * -------------------------------------------------
);
                * 접기
                * -------------------------------------------------
                */
                else {


Button.appendChild(
                    $animTarget
document.createTextNode( '[' )
                        .stop(true, true)
);
                        .slideUp(250, function () {


Button.appendChild(
                            /*
ButtonLink
                            * 애니메이션 종료 후 collapsed 복원
);
                            */
                            $target.addClass('mw-collapsed');


Button.appendChild(
                            $(this).css({
document.createTextNode( ']' )
                                display: 'none',
);
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });
                        });


Header.insertBefore(
Button,
Header.firstChild
);


tableIndex++;
                    $toggles.attr('aria-expanded', 'false');
}
                }
}


for ( i = 0; i < tableIndex; i++ ) {


if (
                return false;
$( NavigationBoxes[ i ] ).hasClass( 'collapsed' ) ||
            });
(
    }
tableIndex >= autoCollapse &&
$( NavigationBoxes[ i ] ).hasClass( 'autocollapse' )
)
) {


window.collapseTable( i );


} else if (
$( NavigationBoxes[ i ] ).hasClass( 'innercollapse' )
) {


var element =
    /*
NavigationBoxes[ i ];
    * =============================================================
    * 아나운서형 특수 펼치기 · 접기
    * =============================================================
    *
    * DOM 예:
    *
    * [남성 버튼 wrapper]
    * [남성 실제 패널]
    * [여성 버튼 wrapper]
    * [여성 실제 패널]
    *
    * 패널을 이동시키지 않고
    * 원래 DOM 위치에서 펼친다.
    *
    * 중요한 점:
    *
    * wrapper와 panel을 둘 다 애니메이션하지 않는다.
    *
    * 버튼 wrapper는 즉시 교체하고,
    * 실제 패널 하나만 slide 애니메이션한다.
    *
    * 따라서 이중 움직임이나
    * 중간 겹침 현상이 최소화된다.
    * =============================================================
    */
    function initStackedCollapsible($content, cls, $targets) {


while (
        /*
( element = element.parentNode )
        * wikitable이 들어 있는 요소를 실제 패널로 사용
) {
        */
        var $panel = $targets.filter(function () {
            return $(this).find('table.wikitable').length > 0;
        }).first();


if (
        if (!$panel.length) {
$( element ).hasClass( 'outercollapse' )
            return;
) {
        }


window.collapseTable( i );
break;
}
}
}
}
}


mw.hook( 'wikipage.content' ).add(
        /*
createCollapseButtons
        * 실제 패널이 아닌 동일 ID 요소 중
);
        * 해당 toggle을 포함하는 요소 = 상단 버튼 wrapper
        */
        var $topWrapper = $targets.not($panel).filter(function () {
            return $(this).find('.' + cls).length > 0;
        }).first();


/* ([[위키백과:관리자 요청/2007년 5월#스크립트 추가 요청]]) */
        if (!$topWrapper.length) {
/** Dynamic Navigation Bars (experimental) **********************************
            return;
*
        }
* Description: See [[:en:Wikipedia:NavFrame]].
* Maintainers: UNMAINTAINED
*/


/* set up the words in your language */
var NavigationBarHide =
'[' + collapseCaption + ']';


var NavigationBarShow =
        var $topToggle = $topWrapper.find('.' + cls).first();
'[' + expandCaption + ']';
        var $panelToggle = $panel.find('.' + cls).first();


/**
* Shows and hides content and picture
* (if available) of navigation bars
*
* Parameters:
* indexNavigationBar:
* the index of navigation bar to be toggled
*/
window.toggleNavigationBar =
function ( indexNavigationBar, event ) {


var NavToggle =
        if (!$topToggle.length || !$panelToggle.length) {
document.getElementById(
            return;
'NavToggle' + indexNavigationBar
        }
);


var NavFrame =
document.getElementById(
'NavFrame' + indexNavigationBar
);


var NavChild;


if ( !NavFrame || !NavToggle ) {
        /*
return false;
        * =========================================================
}
        * 최초 상태
        * =========================================================
        */
        $panel
            .stop(true, true)
            .addClass('mw-collapsed')
            .hide()
            .css({
                height: '',
                overflow: '',
                paddingTop: '',
                paddingBottom: '',
                marginTop: '',
                marginBottom: ''
            });


/*
* if shown now
*/
if (
NavToggle.firstChild.data ===
NavigationBarHide
) {


for (
        $topWrapper
NavChild = NavFrame.firstChild;
            .stop(true, true)
NavChild !== null;
            .show()
NavChild = NavChild.nextSibling
            .css({
) {
                height: '',
                overflow: '',
                paddingTop: '',
                paddingBottom: '',
                marginTop: '',
                marginBottom: ''
            });


if (
$( NavChild ).hasClass( 'NavContent' ) ||
$( NavChild ).hasClass( 'NavPic' )
) {


NavChild.style.display =
        $topToggle.attr('aria-expanded', 'false');
'none';
        $panelToggle.attr('aria-expanded', 'false');
}
}


NavToggle.firstChild.data =
NavigationBarShow;


/*
* if hidden now
*/
} else if (
NavToggle.firstChild.data ===
NavigationBarShow
) {


for (
        /*
NavChild = NavFrame.firstChild;
        * =========================================================
NavChild !== null;
        * 위쪽 버튼 클릭 → 펼치기
NavChild = NavChild.nextSibling
        * =========================================================
) {
        */
        $topToggle
            .off('click.smoothSlide')
            .on('click.smoothSlide', function (e) {


if (
                e.preventDefault();
$( NavChild ).hasClass( 'NavContent' ) ||
                e.stopImmediatePropagation();
$( NavChild ).hasClass( 'NavPic' )
) {


NavChild.style.display =
'block';
}
}


NavToggle.firstChild.data =
                /*
NavigationBarHide;
                * 애니메이션 중 재클릭 방지
}
                */
                if ($panel.is(':animated')) {
                    return false;
                }


event.preventDefault();
};


/*
                /*
* adds show/hide-button
                * 이미 열려 있으면 중단
* to navigation bars
                */
*/
                if ($panel.is(':visible')) {
function createNavigationBarToggleButton() {
                    return false;
var indexNavigationBar = 0;
                }
var NavFrame;
var NavChild;


/*
* iterate over all div-elements
*/
var divs =
document.getElementsByTagName( 'div' );


for (
                /*
var i = 0;
                * -------------------------------------------------
( NavFrame = divs[ i ] );
                * 상단 버튼 wrapper는 즉시 숨김
i++
                *
) {
                * wrapper 자체를 애니메이션하지 않으므로
                * 이중 움직임이 발생하지 않는다.
                * -------------------------------------------------
                */
                $topWrapper
                    .stop(true, true)
                    .hide();


/*
* if found a navigation bar
*/
if (
$( NavFrame ).hasClass( 'NavFrame' )
) {


indexNavigationBar++;
                /*
                * MediaWiki collapsed 상태 제거
                */
                $panel.removeClass('mw-collapsed');


var NavToggle =
document.createElement( 'a' );


NavToggle.className =
                /*
'NavToggle';
                * -------------------------------------------------
                * 실제 패널 하나만 부드럽게 펼침
                * -------------------------------------------------
                */
                $panel
                    .stop(true, true)
                    .hide()
                    .slideDown(260, function () {


NavToggle.setAttribute(
                        /*
'id',
                        * animation 종료 후
'NavToggle' + indexNavigationBar
                        * jQuery가 만든 inline style 정리
);
                        */
                        $(this).css({
                            height: '',
                            overflow: '',
                            paddingTop: '',
                            paddingBottom: '',
                            marginTop: '',
                            marginBottom: ''
                        });
                    });


NavToggle.setAttribute(
'href',
'#'
);


$( NavToggle ).on(
                /*
'click',
                * ARIA
$.proxy(
                */
window.toggleNavigationBar,
                $topToggle.attr('aria-expanded', 'true');
window,
                $panelToggle.attr('aria-expanded', 'true');
indexNavigationBar
)
);


var isCollapsed =
$( NavFrame ).hasClass(
'collapsed'
);


/**
                return false;
* Check if any children are already hidden.
            });
* This loop is here for backwards compatibility.
*/
for (
NavChild = NavFrame.firstChild;
NavChild != null &&
!isCollapsed;
NavChild = NavChild.nextSibling
) {


if (
$( NavChild ).hasClass( 'NavPic' ) ||
$( NavChild ).hasClass( 'NavContent' )
) {


if (
NavChild.style.display ===
'none'
) {


isCollapsed = true;
        /*
}
        * =========================================================
}
        * 패널 안쪽 버튼 클릭 → 접기
}
        * =========================================================
        */
        $panelToggle
            .off('click.smoothSlide')
            .on('click.smoothSlide', function (e) {


if ( isCollapsed ) {
                e.preventDefault();
                e.stopImmediatePropagation();


for (
NavChild = NavFrame.firstChild;
NavChild != null;
NavChild =
NavChild.nextSibling
) {


if (
                /*
$( NavChild ).hasClass( 'NavPic' ) ||
                * 애니메이션 중 재클릭 방지
$( NavChild ).hasClass( 'NavContent' )
                */
) {
                if ($panel.is(':animated')) {
                    return false;
                }


NavChild.style.display =
'none';
}
}
}


var NavToggleText =
                /*
document.createTextNode(
                * -------------------------------------------------
isCollapsed ?
                * 실제 패널 하나만 접음
NavigationBarShow :
                * -------------------------------------------------
NavigationBarHide
                */
);
                $panel
                    .stop(true, true)
                    .slideUp(260, function () {


NavToggle.appendChild(
                        /*
NavToggleText
                        * 패널을 완전히 닫은 뒤
);
                        * collapsed 상태 복원
                        */
                        $(this)
                            .addClass('mw-collapsed')
                            .css({
                                display: 'none',
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });


/*
* Find the NavHead and
* attach the toggle link
*/
for (
var j = 0;
j < NavFrame.childNodes.length;
j++
) {


if (
                        /*
$( NavFrame.childNodes[ j ] )
                        * -------------------------------------------------
.hasClass( 'NavHead' )
                        * 원래 상단 버튼 즉시 복귀
) {
                        *
                        * 별도 애니메이션을 하지 않기 때문에
                        * 닫힘 동작도 한 번의 움직임으로 보인다.
                        * -------------------------------------------------
                        */
                        $topWrapper
                            .stop(true, true)
                            .show()
                            .css({
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });
                    });


NavToggle.style.color =
NavFrame
.childNodes[ j ]
.style.color;


NavFrame
                /*
.childNodes[ j ]
                * ARIA
.appendChild(
                */
NavToggle
                $topToggle.attr('aria-expanded', 'false');
);
                $panelToggle.attr('aria-expanded', 'false');
}
}


NavFrame.setAttribute(
'id',
'NavFrame' +
indexNavigationBar
);
}
}
}


mw.hook( 'wikipage.content' ).add(
                return false;
createNavigationBarToggleButton
            });
);
    }


/***** 그림 정보 틀을 자동으로 불러옴 ********
});
* Adds a link to subpages of current page
* from commons.wikimedia.org
* Maintainers: [[User:Yonidebest]], [[User:Dschwen]]
* [[사용자:Kwj2772]]가 수정
* JSconfig items: bool 'loadAutoInformationTemplate'
*                    (true=enabled (default), false=disabled)
* JSConfig를 사용하지 않도록 수정함.
* --[[사용자:Klutzy|Klutzy]]
********************************************/
 
if (
mw.config.get(
'wgCanonicalSpecialPageName'
) == 'Upload'
) {
 
importScript(
'MediaWiki:Upload.js'
);
}
 
/*
* 인터랙티브 지도.
* 영어 위키백과에서 가져옴.
*/
 
/**
* WikiMiniAtlas
*
* Description:
* WikiMiniAtlas is a popup click and drag
* world map.
*
* Maintainers: [[User:Dschwen]]
*/
( function () {
 
var require_wikiminiatlas = false;
var coord_filter = /geohack/;
 
$( function () {
 
$( 'a.external.text' ).each(
function ( key, link ) {
 
if (
link.href &&
coord_filter.exec(
link.href
)
) {
 
require_wikiminiatlas =
true;
 
return false;
}
}
);
 
if (
$( 'div.kmldata' ).length
) {
 
require_wikiminiatlas =
true;
}
 
if ( require_wikiminiatlas ) {
 
mw.loader.load(
'//meta.wikimedia.org/w/index.php?title=MediaWiki:Wikiminiatlas.js&action=raw&ctype=text/javascript'
);
}
} );
 
}() );
 
/**
* Fix for Windows XP Unicode font rendering
*/
if (
navigator.appVersion.search(
/windows nt 5/i
) !== -1
) {
 
mw.util.addCSS(
'.IPA {' +
'font-family:' +
'"Lucida Sans Unicode",' +
'"Arial Unicode MS";' +
'} ' +
 
'.Unicode {' +
'font-family:' +
'"Arial Unicode MS",' +
'"Lucida Sans Unicode";' +
'} '
);
}
 
/**
* 편집 안내
*
* 생존 인물에 대한 편집 안내.
* 영어 위키백과에서 가져옴
*/
function addEditIntro( name ) {
 
$( '.mw-editsection, #ca-edit' )
.find( 'a' )
.each(
function () {
 
this.href =
$( this ).attr(
'href'
) +
'&editintro=' +
name;
}
);
}
 
if (
mw.config.get(
'wgNamespaceNumber'
) === 0
) {
 
$( function () {
 
var cats =
mw.config.get(
'wgCategories'
);
 
if ( !cats ) {
return;
}
 
if (
$.inArray(
'살아있는 사람',
cats
) !== -1 ||
 
$.inArray(
'생사 불명',
cats
) !== -1
) {
 
addEditIntro(
'틀:BLP_편집_안내'
);
}
} );
}
 
 
/* =========================================================
* 사용자 정의 펼치기 · 접기
*
* 예:
*
* id="toggleCompany"
*          ↓
* id="collapsibleCompany"
*
* 선택적으로:
* id="toggleTextCompany"
*
* 투명도 효과 없이 높이만 300ms 동안 애니메이션
* =========================================================
*/
 
function initializeCustomToggle( $root ) {
 
$root.find( '.toggleBtn' )
.addBack( '.toggleBtn' )
.each( function () {
 
var $toggle =
$( this );
 
/*
* 동일 요소 중복 초기화 방지
*/
if (
$toggle.data(
'custom-toggle-initialized'
)
) {
return;
}
 
var toggleId =
$toggle.attr( 'id' );
 
if ( !toggleId ) {
return;
}
 
/*
* toggleXXX
* → collapsibleXXX
*/
var contentId =
toggleId.replace(
'toggle',
'collapsible'
);
 
/*
* toggleXXX
* → toggleTextXXX
*/
var textId =
toggleId.replace(
'toggle',
'toggleText'
);
 
var $content =
$( '#' + contentId );
 
var $text =
$( '#' + textId );
 
if ( !$content.length ) {
return;
}
 
$toggle.data(
'custom-toggle-initialized',
true
);
 
/*
* 최초 상태는 접힘
*/
$content.hide();
 
$toggle.attr( {
'aria-expanded':
'false',
'tabindex':
$toggle.attr(
'tabindex'
) || '0'
} );
 
/*
* 펼치기/접기 실행
*/
function toggleContent() {
 
/*
* 진행 중인 애니메이션의
* 끝 상태로 강제 이동하지 않고
* 현재 상태에서 정리
*/
$content.stop(
true,
false
);
 
if (
$content.is(
':visible'
)
) {
 
/*
* 접기
*/
$toggle.attr(
'aria-expanded',
'false'
);
 
$content.slideUp(
300,
function () {
 
/*
* jQuery가 애니메이션 과정에서
* 넣은 높이 관련 스타일 정리.
*
* display:none은 slideUp이 유지.
*/
$content.css( {
height: '',
paddingTop: '',
paddingBottom: '',
marginTop: '',
marginBottom: '',
overflow: ''
} );
}
);
 
} else {
 
/*
* 펼치기
*/
$toggle.attr(
'aria-expanded',
'true'
);
 
$content.slideDown(
300,
function () {
 
/*
* 펼친 뒤에는 원래 CSS가
* 크기와 여백을 다시 결정.
*/
$content.css( {
height: '',
paddingTop: '',
paddingBottom: '',
marginTop: '',
marginBottom: '',
overflow: '',
display: ''
} );
}
);
}
 
/*
* 토글 문구가 따로 있는 경우
*/
if ( $text.length ) {
 
$text.text(
'[ 펼치기 · 접기 ]'
);
}
}
 
/*
* 마우스 클릭
*/
$toggle.on(
'click.customToggle',
function ( event ) {
 
event.preventDefault();
 
toggleContent();
}
);
 
/*
* 키보드
* Enter / Space
*/
$toggle.on(
'keydown.customToggle',
function ( event ) {
 
if (
event.key === 'Enter' ||
event.key === ' '
) {
 
event.preventDefault();
 
toggleContent();
}
}
);
} );
}
 
 
/*
* 일반 문서 최초 로딩
*/
$( function () {
 
initializeCustomToggle(
$( document )
);
} );
 
 
/*
* AJAX / VisualEditor / 동적 콘텐츠 등으로
* 문서 내용이 다시 삽입되는 경우에도 초기화
*/
mw.hook( 'wikipage.content' ).add(
function ( $content ) {
 
initializeCustomToggle(
$content
);
}
);
 
 
/* End of mw.loader.using callback */
} );
 
/* DO NOT ADD CODE BELOW THIS LINE */

2026년 8월 20일 (목) 15:13 기준 최신판

/* MediaWiki:Common.js */
mw.hook('wikipage.content').add(function ($content) {

    var initialized = {};

    $content.find('[class*="mw-customtoggle-"]').each(function () {
        var classList = (this.className || '').split(/\s+/);

        classList.forEach(function (cls) {
            if (cls.indexOf('mw-customtoggle-') !== 0) {
                return;
            }

            var suffix = cls.substring('mw-customtoggle-'.length);

            if (initialized[suffix]) {
                return;
            }

            initialized[suffix] = true;

            var targetId = 'mw-customcollapsible-' + suffix;

            /*
             * 중복 ID가 있을 수 있으므로
             * #id 대신 attribute selector 사용
             */
            var $targets = $content.find('[id="' + targetId + '"]');

            if (!$targets.length) {
                return;
            }


            /*
             * =====================================================
             * 특수형
             *
             * 아나운서 표처럼:
             *
             * [상단 버튼 wrapper]
             * [실제 내용 패널]
             *
             * 두 요소가 같은 ID를 공유하고,
             * 실제 패널 안에 wikitable이 있는 구조
             * =====================================================
             */
            var $specialPanel = $targets.filter(function () {
                return $(this).find('table.wikitable').length > 0;
            });

            if ($targets.length > 1 && $specialPanel.length) {
                initStackedCollapsible(
                    $content,
                    cls,
                    $targets
                );

                return;
            }


            /*
             * =====================================================
             * 일반 MediaWiki collapsible
             * =====================================================
             */
            initNormalCollapsible(
                $content,
                cls,
                $targets.first()
            );
        });
    });



    /*
     * =============================================================
     * 일반 펼치기 · 접기
     * =============================================================
     */
    function initNormalCollapsible($content, cls, $target) {

        var $toggles = $content.find('.' + cls);

        /*
         * 일반 MediaWiki 구조:
         *
         * .mw-collapsible
         *   └ .mw-collapsible-content
         *
         * content가 있으면 content만 애니메이션
         */
        var $contentTarget = $target.children('.mw-collapsible-content');

        if (!$contentTarget.length) {
            $contentTarget = $target.find('.mw-collapsible-content').first();
        }

        var $animTarget = $contentTarget.length
            ? $contentTarget
            : $target;


        /*
         * 현재 상태를 기준으로 초기 aria 설정
         */
        var initiallyOpen = $animTarget.is(':visible');

        $toggles.attr(
            'aria-expanded',
            initiallyOpen ? 'true' : 'false'
        );


        $toggles
            .off('click.smoothSlide')
            .on('click.smoothSlide', function (e) {

                e.preventDefault();
                e.stopImmediatePropagation();


                /*
                 * 애니메이션 중 재클릭 방지
                 */
                if ($animTarget.is(':animated')) {
                    return false;
                }


                var opening = !$animTarget.is(':visible');


                /*
                 * -------------------------------------------------
                 * 펼치기
                 * -------------------------------------------------
                 */
                if (opening) {

                    /*
                     * MediaWiki collapsed 상태 제거
                     */
                    $target.removeClass('mw-collapsed');


                    /*
                     * 내용만 펼침
                     */
                    $animTarget
                        .stop(true, true)
                        .hide()
                        .slideDown(250, function () {

                            /*
                             * jQuery 애니메이션 inline style 정리
                             */
                            $(this).css({
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });
                        });


                    $toggles.attr('aria-expanded', 'true');
                }


                /*
                 * -------------------------------------------------
                 * 접기
                 * -------------------------------------------------
                 */
                else {

                    $animTarget
                        .stop(true, true)
                        .slideUp(250, function () {

                            /*
                             * 애니메이션 종료 후 collapsed 복원
                             */
                            $target.addClass('mw-collapsed');

                            $(this).css({
                                display: 'none',
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });
                        });


                    $toggles.attr('aria-expanded', 'false');
                }


                return false;
            });
    }



    /*
     * =============================================================
     * 아나운서형 특수 펼치기 · 접기
     * =============================================================
     *
     * DOM 예:
     *
     * [남성 버튼 wrapper]
     * [남성 실제 패널]
     * [여성 버튼 wrapper]
     * [여성 실제 패널]
     *
     * 패널을 이동시키지 않고
     * 원래 DOM 위치에서 펼친다.
     *
     * 중요한 점:
     *
     * wrapper와 panel을 둘 다 애니메이션하지 않는다.
     *
     * 버튼 wrapper는 즉시 교체하고,
     * 실제 패널 하나만 slide 애니메이션한다.
     *
     * 따라서 이중 움직임이나
     * 중간 겹침 현상이 최소화된다.
     * =============================================================
     */
    function initStackedCollapsible($content, cls, $targets) {

        /*
         * wikitable이 들어 있는 요소를 실제 패널로 사용
         */
        var $panel = $targets.filter(function () {
            return $(this).find('table.wikitable').length > 0;
        }).first();

        if (!$panel.length) {
            return;
        }


        /*
         * 실제 패널이 아닌 동일 ID 요소 중
         * 해당 toggle을 포함하는 요소 = 상단 버튼 wrapper
         */
        var $topWrapper = $targets.not($panel).filter(function () {
            return $(this).find('.' + cls).length > 0;
        }).first();

        if (!$topWrapper.length) {
            return;
        }


        var $topToggle = $topWrapper.find('.' + cls).first();
        var $panelToggle = $panel.find('.' + cls).first();


        if (!$topToggle.length || !$panelToggle.length) {
            return;
        }



        /*
         * =========================================================
         * 최초 상태
         * =========================================================
         */
        $panel
            .stop(true, true)
            .addClass('mw-collapsed')
            .hide()
            .css({
                height: '',
                overflow: '',
                paddingTop: '',
                paddingBottom: '',
                marginTop: '',
                marginBottom: ''
            });


        $topWrapper
            .stop(true, true)
            .show()
            .css({
                height: '',
                overflow: '',
                paddingTop: '',
                paddingBottom: '',
                marginTop: '',
                marginBottom: ''
            });


        $topToggle.attr('aria-expanded', 'false');
        $panelToggle.attr('aria-expanded', 'false');



        /*
         * =========================================================
         * 위쪽 버튼 클릭 → 펼치기
         * =========================================================
         */
        $topToggle
            .off('click.smoothSlide')
            .on('click.smoothSlide', function (e) {

                e.preventDefault();
                e.stopImmediatePropagation();


                /*
                 * 애니메이션 중 재클릭 방지
                 */
                if ($panel.is(':animated')) {
                    return false;
                }


                /*
                 * 이미 열려 있으면 중단
                 */
                if ($panel.is(':visible')) {
                    return false;
                }


                /*
                 * -------------------------------------------------
                 * 상단 버튼 wrapper는 즉시 숨김
                 *
                 * wrapper 자체를 애니메이션하지 않으므로
                 * 이중 움직임이 발생하지 않는다.
                 * -------------------------------------------------
                 */
                $topWrapper
                    .stop(true, true)
                    .hide();


                /*
                 * MediaWiki collapsed 상태 제거
                 */
                $panel.removeClass('mw-collapsed');


                /*
                 * -------------------------------------------------
                 * 실제 패널 하나만 부드럽게 펼침
                 * -------------------------------------------------
                 */
                $panel
                    .stop(true, true)
                    .hide()
                    .slideDown(260, function () {

                        /*
                         * animation 종료 후
                         * jQuery가 만든 inline style 정리
                         */
                        $(this).css({
                            height: '',
                            overflow: '',
                            paddingTop: '',
                            paddingBottom: '',
                            marginTop: '',
                            marginBottom: ''
                        });
                    });


                /*
                 * ARIA
                 */
                $topToggle.attr('aria-expanded', 'true');
                $panelToggle.attr('aria-expanded', 'true');


                return false;
            });



        /*
         * =========================================================
         * 패널 안쪽 버튼 클릭 → 접기
         * =========================================================
         */
        $panelToggle
            .off('click.smoothSlide')
            .on('click.smoothSlide', function (e) {

                e.preventDefault();
                e.stopImmediatePropagation();


                /*
                 * 애니메이션 중 재클릭 방지
                 */
                if ($panel.is(':animated')) {
                    return false;
                }


                /*
                 * -------------------------------------------------
                 * 실제 패널 하나만 접음
                 * -------------------------------------------------
                 */
                $panel
                    .stop(true, true)
                    .slideUp(260, function () {

                        /*
                         * 패널을 완전히 닫은 뒤
                         * collapsed 상태 복원
                         */
                        $(this)
                            .addClass('mw-collapsed')
                            .css({
                                display: 'none',
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });


                        /*
                         * -------------------------------------------------
                         * 원래 상단 버튼 즉시 복귀
                         *
                         * 별도 애니메이션을 하지 않기 때문에
                         * 닫힘 동작도 한 번의 움직임으로 보인다.
                         * -------------------------------------------------
                         */
                        $topWrapper
                            .stop(true, true)
                            .show()
                            .css({
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });
                    });


                /*
                 * ARIA
                 */
                $topToggle.attr('aria-expanded', 'false');
                $panelToggle.attr('aria-expanded', 'false');


                return false;
            });
    }

});