MediaWiki:Common.js: различия между версиями

Кнопка копирования документов
 
Мобильное меню: не выскакивать при загрузке страницы
 
(не показаны 4 промежуточные версии этого же участника)
Строка 29: Строка 29:
         Array.prototype.forEach.call( items, function ( item ) {
         Array.prototype.forEach.call( items, function ( item ) {
             var paper = item.querySelector( 'pre.doc-paper' );
             var paper = item.querySelector( 'pre.doc-paper' );
             var head = item.querySelector( 'th' );
             var host = item.querySelector( 'th' ) || item.querySelector( 'td' );
             if ( !paper || !head || item.querySelector( '.doc-copy' ) ) { return; }
             if ( !paper || !host || item.querySelector( '.doc-copy' ) ) { return; }


             var button = document.createElement( 'button' );
             var button = document.createElement( 'button' );
Строка 47: Строка 47:
                 } );
                 } );
             } );
             } );
             head.appendChild( button );
             host.appendChild( button );
         } );
         } );
     }
     }
Строка 56: Строка 56:
         init();
         init();
     }
     }
}() );
/* Мобильное меню вики: панель выезжает слева, как на основном сайте */
( function () {
    'use strict';
    var mq = window.matchMedia( '(max-width: 960px)' );
    function build() {
        var sidebar = document.querySelector( '.sidebar' );
        var topbar = document.querySelector( '.topbar-inner' );
        if ( !sidebar || !topbar ) { return; }
        document.documentElement.classList.toggle( 'ms-nav-ready', mq.matches );
        var button = document.getElementById( 'msNavToggle' );
        var backdrop = document.getElementById( 'navBackdrop' );
        if ( !mq.matches ) {
            if ( button ) { button.remove(); }
            if ( backdrop ) { backdrop.remove(); }
            sidebar.classList.remove( 'open' );
            document.body.classList.remove( 'nav-open' );
            return;
        }
        if ( button && backdrop ) { return; }
        /* Бургер из шаблона скина (skin.js вешает на него только nav-open —
          панель он не открывает, а прокрутку блокирует) убираем: рабочая
          кнопка здесь одна, своя. */
        var skinButton = document.getElementById( 'navToggle' );
        if ( skinButton ) {
            skinButton.remove();
            document.body.classList.remove( 'nav-open' );
        }
        button = document.createElement( 'button' );
        button.type = 'button';
        button.id = 'msNavToggle';
        button.className = 'nav-toggle';
        button.setAttribute( 'aria-label', 'Меню' );
        button.setAttribute( 'aria-expanded', 'false' );
        button.innerHTML = '<i class="fa-solid fa-bars" aria-hidden="true"></i> Меню';
        backdrop = document.createElement( 'div' );
        backdrop.id = 'navBackdrop';
        backdrop.className = 'nav-backdrop';
        backdrop.setAttribute( 'aria-hidden', 'true' );
        var logo = topbar.querySelector( '.logo' );
        if ( logo && logo.nextSibling ) {
            topbar.insertBefore( button, logo.nextSibling );
        } else {
            topbar.insertBefore( button, topbar.firstChild );
        }
        document.body.appendChild( backdrop );
        function setOpen( open ) {
            sidebar.classList.toggle( 'open', open );
            button.setAttribute( 'aria-expanded', open ? 'true' : 'false' );
            backdrop.classList.toggle( 'visible', open );
            backdrop.setAttribute( 'aria-hidden', open ? 'false' : 'true' );
            document.body.classList.toggle( 'nav-open', open );
        }
        button.addEventListener( 'click', function () {
            setOpen( !sidebar.classList.contains( 'open' ) );
        } );
        backdrop.addEventListener( 'click', function () { setOpen( false ); } );
        document.addEventListener( 'keydown', function ( event ) {
            if ( event.key === 'Escape' ) { setOpen( false ); }
        } );
    }
    if ( document.readyState === 'loading' ) {
        document.addEventListener( 'DOMContentLoaded', build );
    } else {
        build();
    }
    if ( mq.addEventListener ) { mq.addEventListener( 'change', build ); }
}() );
}() );

Текущая версия от 17:17, 10 октября 2026

/* Кнопка «Скопировать» у документов (страница «Бумажная работа») */
( function () {
    'use strict';

    function copyText( text, onDone ) {
        if ( navigator.clipboard && navigator.clipboard.writeText ) {
            navigator.clipboard.writeText( text ).then( onDone, function () { fallback( text, onDone ); } );
            return;
        }
        fallback( text, onDone );
    }

    function fallback( text, onDone ) {
        var area = document.createElement( 'textarea' );
        area.value = text;
        area.setAttribute( 'readonly', '' );
        area.style.position = 'fixed';
        area.style.top = '-1000px';
        document.body.appendChild( area );
        area.select();
        try { document.execCommand( 'copy' ); onDone(); } catch ( e ) { /* ничего */ }
        document.body.removeChild( area );
    }

    function init() {
        var items = document.querySelectorAll( 'table.doc-item' );
        Array.prototype.forEach.call( items, function ( item ) {
            var paper = item.querySelector( 'pre.doc-paper' );
            var host = item.querySelector( 'th' ) || item.querySelector( 'td' );
            if ( !paper || !host || item.querySelector( '.doc-copy' ) ) { return; }

            var button = document.createElement( 'button' );
            button.type = 'button';
            button.className = 'doc-copy';
            button.textContent = 'Скопировать';
            button.title = 'Скопировать текст документа';
            button.addEventListener( 'click', function () {
                copyText( paper.textContent, function () {
                    button.textContent = 'Скопировано';
                    button.classList.add( 'is-done' );
                    window.setTimeout( function () {
                        button.textContent = 'Скопировать';
                        button.classList.remove( 'is-done' );
                    }, 1500 );
                } );
            } );
            host.appendChild( button );
        } );
    }

    if ( document.readyState === 'loading' ) {
        document.addEventListener( 'DOMContentLoaded', init );
    } else {
        init();
    }
}() );

/* Мобильное меню вики: панель выезжает слева, как на основном сайте */
( function () {
    'use strict';

    var mq = window.matchMedia( '(max-width: 960px)' );

    function build() {
        var sidebar = document.querySelector( '.sidebar' );
        var topbar = document.querySelector( '.topbar-inner' );
        if ( !sidebar || !topbar ) { return; }

        document.documentElement.classList.toggle( 'ms-nav-ready', mq.matches );

        var button = document.getElementById( 'msNavToggle' );
        var backdrop = document.getElementById( 'navBackdrop' );

        if ( !mq.matches ) {
            if ( button ) { button.remove(); }
            if ( backdrop ) { backdrop.remove(); }
            sidebar.classList.remove( 'open' );
            document.body.classList.remove( 'nav-open' );
            return;
        }
        if ( button && backdrop ) { return; }

        /* Бургер из шаблона скина (skin.js вешает на него только nav-open —
           панель он не открывает, а прокрутку блокирует) убираем: рабочая
           кнопка здесь одна, своя. */
        var skinButton = document.getElementById( 'navToggle' );
        if ( skinButton ) {
            skinButton.remove();
            document.body.classList.remove( 'nav-open' );
        }

        button = document.createElement( 'button' );
        button.type = 'button';
        button.id = 'msNavToggle';
        button.className = 'nav-toggle';
        button.setAttribute( 'aria-label', 'Меню' );
        button.setAttribute( 'aria-expanded', 'false' );
        button.innerHTML = '<i class="fa-solid fa-bars" aria-hidden="true"></i> Меню';

        backdrop = document.createElement( 'div' );
        backdrop.id = 'navBackdrop';
        backdrop.className = 'nav-backdrop';
        backdrop.setAttribute( 'aria-hidden', 'true' );

        var logo = topbar.querySelector( '.logo' );
        if ( logo && logo.nextSibling ) {
            topbar.insertBefore( button, logo.nextSibling );
        } else {
            topbar.insertBefore( button, topbar.firstChild );
        }
        document.body.appendChild( backdrop );

        function setOpen( open ) {
            sidebar.classList.toggle( 'open', open );
            button.setAttribute( 'aria-expanded', open ? 'true' : 'false' );
            backdrop.classList.toggle( 'visible', open );
            backdrop.setAttribute( 'aria-hidden', open ? 'false' : 'true' );
            document.body.classList.toggle( 'nav-open', open );
        }

        button.addEventListener( 'click', function () {
            setOpen( !sidebar.classList.contains( 'open' ) );
        } );
        backdrop.addEventListener( 'click', function () { setOpen( false ); } );
        document.addEventListener( 'keydown', function ( event ) {
            if ( event.key === 'Escape' ) { setOpen( false ); }
        } );
    }

    if ( document.readyState === 'loading' ) {
        document.addEventListener( 'DOMContentLoaded', build );
    } else {
        build();
    }
    if ( mq.addEventListener ) { mq.addEventListener( 'change', build ); }
}() );