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

Материал из Space Station 14 Вики
мНет описания правки
Нет описания правки
 
(не показано 10 промежуточных версий этого же участника)
Строка 1: Строка 1:
;(function($, mw){
;(function($, mw){
     const COOKIE = 'ss14_wikiTheme';
     const COOKIE = 'ss14_wikiTheme';
     const COOKIE_SPACE = 'ss14_spaceAnimation';  
     const COOKIE_SPACE = 'ss14_spaceAnimation';
    const COOKIE_PROJECT = 'ss14_preferredProject';


     function loadTheme() {
     function loadTheme() {
Строка 30: Строка 31:
         $.cookie(COOKIE_SPACE, val, { expires: 365, path: '/' });
         $.cookie(COOKIE_SPACE, val, { expires: 365, path: '/' });
     }
     }
 
   
     function applySpaceAnimation(val) {
     function applySpaceAnimation(val) {
         const $body = $('body');
         const $body = $('body');
         $body.attr('data-space-animation', val);
         const themeClasses = ($body.attr('class') || '')
         mw.hook('ss14.spaceAnimationChanged').fire(val);
            .split(/\s+/)
            .filter(cls => cls.indexOf('wgl-space-animation-') === 0);
        if (themeClasses.length) {
            $body.removeClass(themeClasses.join(' '));
        }
        $body.addClass(`wgl-space-animation-${val}`);
        mw.hook('wgl.spaceAnimationChanged').fire(val);
    }
 
    function loadPreferredProject() {
        return $.cookie(COOKIE_PROJECT) || 'corvax';
    }
 
    function savePreferredProject(val) {
        $.cookie(COOKIE_PROJECT, val, { expires: 365, path: '/' });
    }
 
    function applyPreferredProject(val) {
        const $body = $('body');
        const classes = ($body.attr('class') || '')
            .split(/\s+/)
            .filter(cls => cls.indexOf('wgl-preferred-project-') === 0);
 
        if (classes.length) {
            $body.removeClass(classes.join(' '));
        }
 
        $body.addClass(`wgl-preferred-project-${val}`);
         mw.hook('wgl.preferredProjectChanged').fire(val);
     }
     }


Строка 41: Строка 70:


         const $portlet = $('<div>', {
         const $portlet = $('<div>', {
             class: 'mw-portlet mw-portlet-skin-client-prefs-skin-theme mw-portlet-js theme-menu',
             class: 'mw-portlet mw-portlet-js theme-menu',
             id: 'skin-client-prefs-skin-theme'
             id: 'skin-client-prefs-skin-theme'
         });
         });
Строка 58: Строка 87:
             const $wr = $('<div>', { class: 'theme-client-prefs-radio' });
             const $wr = $('<div>', { class: 'theme-client-prefs-radio' });
             const $inp = $('<input>', {
             const $inp = $('<input>', {
                 type:     'radio',
                 type: 'radio',
                 name:     'theme-selection',
                 name: 'theme-selection',
                 id:       `theme-value-${opt.key}`,
                 id: `theme-value-${opt.key}`,
                 value:   opt.key,
                 value: opt.key,
                 checked: opt.key === currentTheme
                 checked: opt.key === currentTheme
             });
             });
             const $lbl = $('<label>', {
             const $lbl = $('<label>', {
                 for:     `theme-value-${opt.key}`,
                 for: `theme-value-${opt.key}`,
                 text:     opt.label
                 text: opt.label
             });
             });
             $wr.append($inp, $lbl);
             $wr.append($inp, $lbl);
Строка 82: Строка 111:
         $container.append($portlet);
         $container.append($portlet);
         initSpaceMenu($portlet);
         initSpaceMenu($portlet);
        initPreferredProjectMenu($portlet);


         $form.on('change', 'input[name="theme-selection"]', function() {
         $form.on('change', 'input[name="theme-selection"]', function() {
Строка 94: Строка 124:


         const $spacePortlet = $('<div>', {
         const $spacePortlet = $('<div>', {
             class: 'mw-portlet mw-portlet-skin-client-prefs-skin-space mw-portlet-js space-menu',
             class: 'mw-portlet mw-portlet-js theme-menu',
             id: 'skin-client-prefs-skin-space'
             id: 'skin-client-prefs-skin-space'
         });
         });
Строка 102: Строка 132:
         );
         );


         const $form = $('<form>');
         const $form = $('<form style="grid-template-columns:1fr 1fr;">');
         [
         [
             { val: 'on',  label: 'Включено' },
             { val: 'on',  label: 'Включено' },
             { val: 'off', label: 'Выключено' }
             { val: 'off', label: 'Отключено' }
         ].forEach(opt => {
         ].forEach(opt => {
             const $wr = $('<div>', { class: 'space-client-prefs-radio' });
             const $wr = $('<div>', { class: 'theme-client-prefs-radio' });
             const $inp = $('<input>', {
             const $inp = $('<input>', {
                 type: 'radio',
                 type: 'radio',
Строка 138: Строка 168:
             saveSpaceAnimation(newVal);
             saveSpaceAnimation(newVal);
             applySpaceAnimation(newVal);
             applySpaceAnimation(newVal);
        });
    }
    function initPreferredProjectMenu($afterPortlet, currentVal) {
        currentVal = currentVal || loadPreferredProject();
        const $projectPortlet = $('<div>', {
            class: 'mw-portlet mw-portlet-js theme-menu',
            id: 'skin-client-prefs-skin-project'
        });
        $projectPortlet.append(
            $('<div>', { class: 'theme-menu__heading', text: 'Предпочитаемый проект' }),
            $('<div>', { class: 'theme-menu__content' })
        );
        const $form = $('<form style="grid-template-columns:1fr 1fr;">');
        [
            { val: 'corvax', label: 'Corvax' },
            { val: 'goob',  label: 'Goob' },
            { val: 'wl', label: 'WL' },
            { val: 'wega',  label: 'Wega' }
        ].forEach(opt => {
            const $wr = $('<div>', { class: 'theme-client-prefs-radio' });
            const $inp = $('<input>', {
                type: 'radio',
                name: 'preferred-project-selection',
                id: `project-value-${opt.val}`,
                value: opt.val,
                checked: opt.val === currentVal
            });
            const $lbl = $('<label>', {
                for: `project-value-${opt.val}`,
                text: opt.label
            });
            $wr.append($inp, $lbl);
            $form.append($wr);
        });
        $projectPortlet.find('.theme-menu__content').append(
            $('<ul>', { class: 'theme-menu__content-list' })
                .append(
                    $('<li>', { class: 'mw-list-item mw-list-item-js' })
                        .append($form)
                )
        );
        $afterPortlet.after($projectPortlet);
        applyPreferredProject(currentVal);
        $form.on('change', 'input[name="preferred-project-selection"]', function() {
            const newVal = $(this).val();
            savePreferredProject(newVal);
            applyPreferredProject(newVal);
         });
         });
     }
     }
Строка 148: Строка 231:
         saveSpaceAnimation,
         saveSpaceAnimation,
         applySpaceAnimation,
         applySpaceAnimation,
         initSpaceMenu
         initSpaceMenu,
        loadPreferredProject,
        savePreferredProject,
        applyPreferredProject,
        initPreferredProjectMenu
     };
     };


}(jQuery, mediaWiki));
}(jQuery, mediaWiki));

Текущая версия от 14:26, 24 июня 2026

;(function($, mw){
    const COOKIE = 'ss14_wikiTheme';
    const COOKIE_SPACE = 'ss14_spaceAnimation';
    const COOKIE_PROJECT = 'ss14_preferredProject';

    function loadTheme() {
        return $.cookie(COOKIE) || 'dark';
    }

    function saveTheme(theme) {
        $.cookie(COOKIE, theme, { expires: 365, path: '/' });
    }

    function applyTheme(theme) {
        const $body = $('body');
        const themeClasses = ($body.attr('class') || '')
            .split(/\s+/)
            .filter(cls => cls.indexOf('wgl-theme-') === 0);
        if (themeClasses.length) {
            $body.removeClass(themeClasses.join(' '));
        }
        $body.addClass(`wgl-theme-${theme}`);
        mw.hook('wgl.themeChanged').fire(theme);
    }

    function loadSpaceAnimation() {
        return $.cookie(COOKIE_SPACE) || 'on';
    }

    function saveSpaceAnimation(val) {
        $.cookie(COOKIE_SPACE, val, { expires: 365, path: '/' });
    }
    
    function applySpaceAnimation(val) {
        const $body = $('body');
        const themeClasses = ($body.attr('class') || '')
            .split(/\s+/)
            .filter(cls => cls.indexOf('wgl-space-animation-') === 0);
        if (themeClasses.length) {
            $body.removeClass(themeClasses.join(' '));
        }
        $body.addClass(`wgl-space-animation-${val}`);
        mw.hook('wgl.spaceAnimationChanged').fire(val);
    }

    function loadPreferredProject() {
        return $.cookie(COOKIE_PROJECT) || 'corvax';
    }

    function savePreferredProject(val) {
        $.cookie(COOKIE_PROJECT, val, { expires: 365, path: '/' });
    }

    function applyPreferredProject(val) {
        const $body = $('body');
        const classes = ($body.attr('class') || '')
            .split(/\s+/)
            .filter(cls => cls.indexOf('wgl-preferred-project-') === 0);

        if (classes.length) {
            $body.removeClass(classes.join(' '));
        }

        $body.addClass(`wgl-preferred-project-${val}`);
        mw.hook('wgl.preferredProjectChanged').fire(val);
    }

    function initThemeMenu($container, currentTheme) {
        currentTheme = currentTheme || loadTheme();

        const $portlet = $('<div>', {
            class: 'mw-portlet mw-portlet-js theme-menu',
            id: 'skin-client-prefs-skin-theme'
        });
        $portlet.append(
            $('<div>', { class: 'theme-menu__heading', text: 'Тема' }),
            $('<div>', { class: 'theme-menu__content' })
        );

        const $form = $('<form>');
        [
            { key: 'light',  label: 'Светлая' },
            { key: 'normal', label: 'Стандартная' },
            { key: 'dark',   label: 'Тёмная' },
            { key: 'ss14',   label: 'Space Station 14' }
        ].forEach(opt => {
            const $wr = $('<div>', { class: 'theme-client-prefs-radio' });
            const $inp = $('<input>', {
                type: 'radio',
                name: 'theme-selection',
                id: `theme-value-${opt.key}`,
                value: opt.key,
                checked: opt.key === currentTheme
            });
            const $lbl = $('<label>', {
                for: `theme-value-${opt.key}`,
                text: opt.label
            });
            $wr.append($inp, $lbl);
            $form.append($wr);
        });

        $portlet.find('.theme-menu__content').append(
            $('<ul>', { class: 'theme-menu__content-list' })
                .append(
                    $('<li>', { class: 'mw-list-item mw-list-item-js' })
                        .append($form)
                )
        );

        $container.append($portlet);
        initSpaceMenu($portlet);
        initPreferredProjectMenu($portlet);

        $form.on('change', 'input[name="theme-selection"]', function() {
            const newTheme = $(this).val();
            saveTheme(newTheme);
            applyTheme(newTheme);
        });
    }

    function initSpaceMenu($afterPortlet, currentVal) {
        currentVal = currentVal || loadSpaceAnimation();

        const $spacePortlet = $('<div>', {
            class: 'mw-portlet mw-portlet-js theme-menu',
            id: 'skin-client-prefs-skin-space'
        });
        $spacePortlet.append(
            $('<div>', { class: 'theme-menu__heading', text: 'Космос' }),
            $('<div>', { class: 'theme-menu__content' })
        );

        const $form = $('<form style="grid-template-columns:1fr 1fr;">');
        [
            { val: 'on',  label: 'Включено' },
            { val: 'off', label: 'Отключено' }
        ].forEach(opt => {
            const $wr = $('<div>', { class: 'theme-client-prefs-radio' });
            const $inp = $('<input>', {
                type: 'radio',
                name: 'space-animation-selection',
                id: `space-value-${opt.val}`,
                value: opt.val,
                checked: opt.val === currentVal
            });
            const $lbl = $('<label>', {
                for: `space-value-${opt.val}`,
                text: opt.label
            });
            $wr.append($inp, $lbl);
            $form.append($wr);
        });

        $spacePortlet.find('.theme-menu__content').append(
            $('<ul>', { class: 'theme-menu__content-list' })
                .append(
                    $('<li>', { class: 'mw-list-item mw-list-item-js' })
                        .append($form)
                )
        );

        $afterPortlet.after($spacePortlet);
        applySpaceAnimation(currentVal);

        $form.on('change', 'input[name="space-animation-selection"]', function() {
            const newVal = $(this).val();
            saveSpaceAnimation(newVal);
            applySpaceAnimation(newVal);
        });
    }

    function initPreferredProjectMenu($afterPortlet, currentVal) {
        currentVal = currentVal || loadPreferredProject();

        const $projectPortlet = $('<div>', {
            class: 'mw-portlet mw-portlet-js theme-menu',
            id: 'skin-client-prefs-skin-project'
        });
        $projectPortlet.append(
            $('<div>', { class: 'theme-menu__heading', text: 'Предпочитаемый проект' }),
            $('<div>', { class: 'theme-menu__content' })
        );

        const $form = $('<form style="grid-template-columns:1fr 1fr;">');
        [
            { val: 'corvax', label: 'Corvax' },
            { val: 'goob',   label: 'Goob' },
            { val: 'wl', label: 'WL' },
            { val: 'wega',   label: 'Wega' }
        ].forEach(opt => {
            const $wr = $('<div>', { class: 'theme-client-prefs-radio' });
            const $inp = $('<input>', {
                type: 'radio',
                name: 'preferred-project-selection',
                id: `project-value-${opt.val}`,
                value: opt.val,
                checked: opt.val === currentVal
            });
            const $lbl = $('<label>', {
                for: `project-value-${opt.val}`,
                text: opt.label
            });
            $wr.append($inp, $lbl);
            $form.append($wr);
        });

        $projectPortlet.find('.theme-menu__content').append(
            $('<ul>', { class: 'theme-menu__content-list' })
                .append(
                    $('<li>', { class: 'mw-list-item mw-list-item-js' })
                        .append($form)
                )
        );

        $afterPortlet.after($projectPortlet);
        applyPreferredProject(currentVal);

        $form.on('change', 'input[name="preferred-project-selection"]', function() {
            const newVal = $(this).val();
            savePreferredProject(newVal);
            applyPreferredProject(newVal);
        });
    }

    mw.themeUtils = {
        loadTheme,
        applyTheme,
        initThemeMenu,
        loadSpaceAnimation,
        saveSpaceAnimation,
        applySpaceAnimation,
        initSpaceMenu,
        loadPreferredProject,
        savePreferredProject,
        applyPreferredProject,
        initPreferredProjectMenu
    };

}(jQuery, mediaWiki));