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

편집 요약 없음
편집 요약 없음
23번째 줄: 23번째 줄:


             /*
             /*
             * 같은 id가 중복되어 있으므로 #id selector 사용하지 않음
             * ID 중복 가능성을 고려해서 attribute selector 사용
             */
             */
             var $sameIds = $content.find('[id="' + targetId + '"]');
             var $targets = $content.find('[id="' + targetId + '"]');
 
            if (!$targets.length) {
                return;
            }
 


             /*
             /*
             * wikitable을 가지고 있는 요소가 실제 펼쳐지는 패널
             * =====================================================
            * 1. 아나운서형 특수 구조
            *
            * 같은 ID가 여러 개 있고,
            * 그중 하나가 wikitable을 포함하는 경우
            * =====================================================
             */
             */
             var $panel = $sameIds.filter(function () {
             if (
                return $(this).find('table.wikitable').length > 0;
                $targets.length > 1 &&
            }).first();
                $targets.filter(function () {
                    return $(this).find('table.wikitable').length > 0;
                }).length
            ) {
                initStackedCollapsible(
                    $content,
                    cls,
                    $targets
                );


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


             /*
             /*
             * 위쪽 버튼 wrapper
             * =====================================================
            * 2. 일반 MediaWiki collapsible
            * =====================================================
             */
             */
             var $topWrapper = $sameIds.not($panel).filter(function () {
             initNormalCollapsible(
                 return $(this).find('.' + cls).length > 0;
                $content,
            }).first();
                cls,
                 $targets.first()
            );
        });
    });


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


            if (!$topToggle.length || !$panelToggle.length) {
    /*
                return;
    * -----------------------------------------------------
            }
    * 일반 펼치기 · 접기
    * -----------------------------------------------------
    */
    function initNormalCollapsible($content, cls, $target) {
 
        var $toggles = $content.find('.' + cls);
 
        /*
        * 실제로 애니메이션할 부분
        */
        var $contentTarget = $target.children('.mw-collapsible-content');
 
        if (!$contentTarget.length) {
            $contentTarget = $target.find('.mw-collapsible-content').first();
        }


        /*
        * mw-collapsible-content가 없다면
        * target 자체를 애니메이션
        */
        var $animTarget = $contentTarget.length
            ? $contentTarget
            : $target;


            /*
            * 초기 상태
            */
            $panel
                .addClass('mw-collapsed')
                .css({
                    display: 'none',
                    overflow: ''
                });


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


            /*
                /*
            * =========================
                * MediaWiki 기본 이벤트까지 완전히 죽이지 않고
            * 위쪽 버튼 → 펼치기
                * 우리가 애니메이션만 담당
            * =========================
                */
            */
                 e.preventDefault();
            $topToggle
                 e.stopImmediatePropagation();
                 .off('click.smoothSlide')
                 .on('click.smoothSlide', function (e) {


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


                    if ($panel.is(':animated') || $panel.is(':visible')) {
                var opening = !$animTarget.is(':visible');
                        return false;
                    }


                    /*
                    * 위쪽 버튼은 바로 제거.
                    * 그러면 다음 버튼(여성 등)이 아래쪽으로 밀림.
                    */
                    $topWrapper.hide();


                if (opening) {


                     /*
                     /*
                     * 중요:
                     * 먼저 collapsed 해제
                    * MediaWiki의 collapsed 상태를 먼저 제거
                     */
                     */
                     $panel.removeClass('mw-collapsed');
                     $target.removeClass('mw-collapsed');
 
                    $animTarget
                        .stop(true, false)
                        .slideDown(200, function () {
                            $(this).css({
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });
                        });


                } else {


                    /*
                     $animTarget
                    * display:none 상태에서 slideDown 실행
                    */
                     $panel
                         .stop(true, false)
                         .stop(true, false)
                         .hide()
                         .slideUp(200, function () {
                        .slideDown(250, function () {


                             /*
                             /*
                             * jQuery 애니메이션 잔여 스타일 제거
                             * 다 접힌 뒤 collapsed 복원
                             */
                             */
                            $target.addClass('mw-collapsed');
                             $(this).css({
                             $(this).css({
                                 display: '',
                                 display: 'none',
                                 height: '',
                                 height: '',
                                 overflow: '',
                                 overflow: '',
115번째 줄: 153번째 줄:
                             });
                             });
                         });
                         });
                }


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


                $toggles.attr(
                    'aria-expanded',
                    opening ? 'true' : 'false'
                );
                return false;
            });
    }
    /*
    * -----------------------------------------------------
    * 아나운서처럼
    *
    * 상단 버튼
    * 실제 패널
    * 다음 버튼
    * 실제 패널
    *
    * 구조인 경우
    * -----------------------------------------------------
    */
    function initStackedCollapsible($content, cls, $targets) {
        /*
        * wikitable이 들어 있는 것이 실제 패널
        */
        var $panel = $targets.filter(function () {
            return $(this).find('table.wikitable').length > 0;
        }).first();
        if (!$panel.length) {
            return;
        }
        /*
        * 나머지가 위쪽 버튼 wrapper
        */
        var $topWrapper = $targets.not($panel).filter(function () {
            return $(this).find('.' + cls).length > 0;
        }).first();
        var $topToggle = $topWrapper.find('.' + cls).first();
        var $panelToggle = $panel.find('.' + cls).first();
        if (!$topToggle.length || !$panelToggle.length) {
            return;
        }
        /*
        * 초기에는 패널 숨김
        */
        $panel.hide();
        /*
        * 위 버튼 클릭
        */
        $topToggle
            .off('click.smoothSlide')
            .on('click.smoothSlide', function (e) {
                e.preventDefault();
                e.stopImmediatePropagation();
                if ($panel.is(':animated') || $panel.is(':visible')) {
                     return false;
                     return false;
                 });
                 }




            /*
                /*
            * =========================
                * 원래 상단 버튼 제거
            * 펼쳐진 버튼 → 접기
                *
            * =========================
                * DOM 위치는 유지되므로
            */
                * 뒤의 여성/다음 버튼이 아래로 내려감
            $panelToggle
                */
                 .off('click.smoothSlide')
                 $topWrapper.hide();
                .on('click.smoothSlide', function (e) {


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


                    if ($panel.is(':animated')) {
                /*
                         return false;
                * 중요:
                     }
                * 패널 자체를 움직이지 않음
                */
                $panel
                    .removeClass('mw-collapsed')
                    .stop(true, false)
                    .hide()
                    .slideDown(200, function () {
                         $(this).css({
                            height: '',
                            overflow: '',
                            paddingTop: '',
                            paddingBottom: '',
                            marginTop: '',
                            marginBottom: ''
                        });
                     });




                    /*
                $topToggle.attr('aria-expanded', 'true');
                    * 접힐 때는 mw-collapsed를 아직 붙이면 안 됨.
                $panelToggle.attr('aria-expanded', 'true');
                    *
                    * 먼저 slideUp을 끝낸 뒤 붙여야
                    * 애니메이션이 정상적으로 보임.
                    */
                    $panel
                        .stop(true, false)
                        .slideUp(250, function () {


                            /*
                return false;
                            * 애니메이션 완료 후 collapsed 상태 복원
            });
                            */
                            $(this)
                                .addClass('mw-collapsed')
                                .css({
                                    display: 'none',
                                    height: '',
                                    overflow: '',
                                    paddingTop: '',
                                    paddingBottom: '',
                                    marginTop: '',
                                    marginBottom: ''
                                });




                            /*
        /*
                            * 원래 위쪽 버튼 다시 표시
        * 펼쳐진 패널 안쪽 버튼 클릭
                            */
        */
                            $topWrapper.show();
        $panelToggle
                        });
            .off('click.smoothSlide')
            .on('click.smoothSlide', function (e) {


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


                if ($panel.is(':animated')) {
                     return false;
                     return false;
                 });
                 }
 
 
                $panel
                    .stop(true, false)
                    .slideUp(200, function () {
 
                        $(this)
                            .addClass('mw-collapsed')
                            .css({
                                display: 'none',
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });


        });
 
    });
                        /*
                        * 애니메이션이 끝난 뒤
                        * 원래 상단 버튼 복귀
                        */
                        $topWrapper.show();
                    });
 
 
                $topToggle.attr('aria-expanded', 'false');
                $panelToggle.attr('aria-expanded', 'false');
 
                return false;
            });
    }


});
});

2026년 8월 20일 (목) 15:01 판

/* 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 중복 가능성을 고려해서 attribute selector 사용
             */
            var $targets = $content.find('[id="' + targetId + '"]');

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


            /*
             * =====================================================
             * 1. 아나운서형 특수 구조
             *
             * 같은 ID가 여러 개 있고,
             * 그중 하나가 wikitable을 포함하는 경우
             * =====================================================
             */
            if (
                $targets.length > 1 &&
                $targets.filter(function () {
                    return $(this).find('table.wikitable').length > 0;
                }).length
            ) {
                initStackedCollapsible(
                    $content,
                    cls,
                    $targets
                );

                return;
            }


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


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

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

        /*
         * 실제로 애니메이션할 부분
         */
        var $contentTarget = $target.children('.mw-collapsible-content');

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

        /*
         * mw-collapsible-content가 없다면
         * target 자체를 애니메이션
         */
        var $animTarget = $contentTarget.length
            ? $contentTarget
            : $target;


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

                /*
                 * MediaWiki 기본 이벤트까지 완전히 죽이지 않고
                 * 우리가 애니메이션만 담당
                 */
                e.preventDefault();
                e.stopImmediatePropagation();


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


                if (opening) {

                    /*
                     * 먼저 collapsed 해제
                     */
                    $target.removeClass('mw-collapsed');

                    $animTarget
                        .stop(true, false)
                        .slideDown(200, function () {
                            $(this).css({
                                height: '',
                                overflow: '',
                                paddingTop: '',
                                paddingBottom: '',
                                marginTop: '',
                                marginBottom: ''
                            });
                        });

                } else {

                    $animTarget
                        .stop(true, false)
                        .slideUp(200, function () {

                            /*
                             * 다 접힌 뒤 collapsed 복원
                             */
                            $target.addClass('mw-collapsed');

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


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

                return false;
            });
    }



    /*
     * -----------------------------------------------------
     * 아나운서처럼
     *
     * 상단 버튼
     * 실제 패널
     * 다음 버튼
     * 실제 패널
     *
     * 구조인 경우
     * -----------------------------------------------------
     */
    function initStackedCollapsible($content, cls, $targets) {

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

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


        /*
         * 나머지가 위쪽 버튼 wrapper
         */
        var $topWrapper = $targets.not($panel).filter(function () {
            return $(this).find('.' + cls).length > 0;
        }).first();

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

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


        /*
         * 초기에는 패널 숨김
         */
        $panel.hide();


        /*
         * 위 버튼 클릭
         */
        $topToggle
            .off('click.smoothSlide')
            .on('click.smoothSlide', function (e) {

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

                if ($panel.is(':animated') || $panel.is(':visible')) {
                    return false;
                }


                /*
                 * 원래 상단 버튼 제거
                 *
                 * DOM 위치는 유지되므로
                 * 뒤의 여성/다음 버튼이 아래로 내려감
                 */
                $topWrapper.hide();


                /*
                 * 중요:
                 * 패널 자체를 움직이지 않음
                 */
                $panel
                    .removeClass('mw-collapsed')
                    .stop(true, false)
                    .hide()
                    .slideDown(200, function () {
                        $(this).css({
                            height: '',
                            overflow: '',
                            paddingTop: '',
                            paddingBottom: '',
                            marginTop: '',
                            marginBottom: ''
                        });
                    });


                $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, false)
                    .slideUp(200, function () {

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


                        /*
                         * 애니메이션이 끝난 뒤
                         * 원래 상단 버튼 복귀
                         */
                        $topWrapper.show();
                    });


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

                return false;
            });
    }

});