미디어위키:Common.js

신사 (토론 | 기여)님의 2026년 8월 20일 (목) 13:51 판

참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.

  • 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)
  • 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)
  • 인터넷 익스플로러 / 엣지: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.
  • 오페라: Ctrl-F5를 입력.
/**
 * =========================================================
 * Animated Collapse / Expand
 * MediaWiki:Common.js
 * =========================================================
 *
 * 사용 예:
 *
 * <div
 *     class="animated-toggle"
 *     data-collapse-target="example-1"
 *     role="button"
 *     tabindex="0"
 * >
 *     <b>[ 펼치기 · 접기 ]</b>
 * </div>
 *
 * <div
 *     id="example-1"
 *     class="animated-content"
 * >
 *     <div class="animated-content-inner">
 *         내용
 *     </div>
 * </div>
 *
 */


(function ($, mw) {
    'use strict';


    /**
     * -----------------------------------------------------
     * 펼치기 초기화
     * -----------------------------------------------------
     */

    function initAnimatedCollapse($content) {

        $content.find('.animated-toggle').each(function () {

            var $toggle = $(this);


            /*
             * 이미 초기화되었다면 중복 실행하지 않음
             */
            if ($toggle.data('animatedCollapseInitialized')) {
                return;
            }


            /*
             * 대상 ID
             */
            var targetId = $toggle.attr('data-collapse-target');


            /*
             * target이 없는 경우 무시
             */
            if (!targetId) {
                return;
            }


            /*
             * 특수문자가 ID에 들어갈 가능성을 고려해서
             * document.getElementById 사용
             */
            var targetElement = document.getElementById(targetId);


            if (!targetElement) {
                return;
            }


            var $target = $(targetElement);


            /*
             * 초기화 완료 표시
             */
            $toggle.data(
                'animatedCollapseInitialized',
                true
            );


            /**
             * ---------------------------------------------
             * 접근성 속성 초기화
             * ---------------------------------------------
             */

            if (!$toggle.attr('role')) {
                $toggle.attr('role', 'button');
            }


            if (!$toggle.attr('tabindex')) {
                $toggle.attr('tabindex', '0');
            }


            /*
             * aria-controls 연결
             */
            $toggle.attr(
                'aria-controls',
                targetId
            );


            /*
             * 초기 열린 상태 확인
             *
             * is-open 클래스가 있으면 펼쳐진 상태로 시작
             */
            var isInitiallyOpen =
                $target.hasClass('is-open');


            $toggle.attr(
                'aria-expanded',
                isInitiallyOpen ? 'true' : 'false'
            );


            $target.attr(
                'aria-hidden',
                isInitiallyOpen ? 'false' : 'true'
            );


            /**
             * ---------------------------------------------
             * 열기
             * ---------------------------------------------
             */

            function openCollapse() {

                $target.addClass('is-open');

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

                $target.attr(
                    'aria-hidden',
                    'false'
                );


                /*
                 * 필요하면 사용자 정의 이벤트도 발생
                 */
                $target.trigger(
                    'animatedcollapse:open'
                );
            }


            /**
             * ---------------------------------------------
             * 닫기
             * ---------------------------------------------
             */

            function closeCollapse() {

                $target.removeClass('is-open');

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

                $target.attr(
                    'aria-hidden',
                    'true'
                );


                $target.trigger(
                    'animatedcollapse:close'
                );
            }


            /**
             * ---------------------------------------------
             * 토글
             * ---------------------------------------------
             */

            function toggleCollapse() {

                if ($target.hasClass('is-open')) {

                    closeCollapse();

                } else {

                    openCollapse();

                }
            }


            /**
             * ---------------------------------------------
             * 클릭
             * ---------------------------------------------
             */

            $toggle.on(
                'click.animatedCollapse',
                function (event) {

                    event.preventDefault();

                    toggleCollapse();
                }
            );


            /**
             * ---------------------------------------------
             * 키보드
             *
             * Enter
             * Space
             * ---------------------------------------------
             */

            $toggle.on(
                'keydown.animatedCollapse',
                function (event) {

                    if (
                        event.key === 'Enter' ||
                        event.key === ' '
                    ) {

                        event.preventDefault();

                        toggleCollapse();
                    }
                }
            );

        });

    }


    /**
     * -----------------------------------------------------
     * MediaWiki 페이지 최초 로드
     * -----------------------------------------------------
     */

    $(function () {

        initAnimatedCollapse(
            $(document)
        );

    });


    /**
     * -----------------------------------------------------
     * MediaWiki 동적 콘텐츠 대응
     *
     * VisualEditor,
     * AJAX,
     * 확장기능,
     * Lua 등에서 콘텐츠가 나중에 생성돼도
     * 자동으로 초기화
     * -----------------------------------------------------
     */

    if (
        typeof mw !== 'undefined' &&
        mw.hook
    ) {

        mw.hook('wikipage.content').add(
            function ($content) {

                initAnimatedCollapse(
                    $content
                );

            }
        );

    }


})(jQuery, mediaWiki);