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

Страница интерфейса MediaWiki
(Содержимое страницы заменено на «// Создаем элемент div для тестирования var testDiv = document.createElement("div"); testDiv.textContent = "Common.js работает!"; document.body.appendChild(testDiv);»)
Метки: замена отменено
(! New style (js) try 1)
 
(не показана 1 промежуточная версия 1 участника)
Строка 1: Строка 1:
// Создаем элемент div для тестирования
(function() {
var testDiv = document.createElement("div");
    'use strict';
testDiv.textContent = "Common.js работает!";
   
document.body.appendChild(testDiv);
    // Проверяем, что мы не на мобильном устройстве (для производительности)
    var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    var isLowPerformance = navigator.hardwareConcurrency < 4;
   
    // Конфигурация частиц под тему сайта
    var themeColors = {
        primary: '#77c1d9',
        secondary: '#9dd7ea',
        accent: '#b8e6ff',
        background: '#1a1a1f'
    };
   
    // Функция создания и настройки частиц
    function initParticleSystem() {
        // Проверяем, не создан ли уже контейнер
        if (document.getElementById('particles-js')) {
            return;
        }
       
        // Создаем стилизованный контейнер
        var particlesDiv = document.createElement('div');
        particlesDiv.id = 'particles-js';
        particlesDiv.setAttribute('aria-hidden', 'true'); // Для доступности
       
        // Вставляем после body, но перед основным контентом
        var mwBody = document.querySelector('.mw-body');
        if (mwBody) {
            document.body.insertBefore(particlesDiv, mwBody);
        } else {
            document.body.appendChild(particlesDiv);
        }
       
        // Улучшенные стили с адаптивностью
        var particleStyles = document.createElement('style');
        particleStyles.id = 'particles-styles';
        particleStyles.innerHTML = `
            #particles-js {
                position: fixed;
                top: 0;
                left: 0;
                width: 100vw;
                height: 100vh;
                z-index: -1;
                pointer-events: none;
                opacity: 0.8;
                transition: opacity 0.5s ease;
            }
           
            /* Уменьшаем эффект на маленьких экранах */
            @media (max-width: 768px) {
                #particles-js {
                    opacity: 0.3;
                }
            }
           
            /* Полностью отключаем на очень маленьких экранах */
            @media (max-width: 480px) {
                #particles-js {
                    display: none;
                }
            }
           
            /* Уменьшаем эффект при предпочтении пользователя */
            @media (prefers-reduced-motion: reduce) {
                #particles-js {
                    opacity: 0.2;
                }
            }
           
            /* Адаптация под высокий DPI */
            @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
                #particles-js canvas {
                    image-rendering: crisp-edges;
                }
            }
           
            /* Плавное появление частиц */
            #particles-js.loaded {
                animation: particlesFadeIn 2s ease-in;
            }
           
            @keyframes particlesFadeIn {
                from { opacity: 0; }
                to { opacity: 0.8; }
            }
        `;
        document.head.appendChild(particleStyles);
       
        // Загружаем библиотеку с обработкой ошибок
        loadParticlesLibrary();
    }
   
    // Улучшенная функция загрузки библиотеки
    function loadParticlesLibrary() {
        // Проверяем, не загружена ли уже библиотека
        if (window.particlesJS) {
            initParticles();
            return;
        }
       
        var script = document.createElement('script');
        script.src = 'https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js';
        script.async = true;
        script.defer = true;
       
        script.onload = function() {
            console.log('Particles.js загружена успешно');
            initParticles();
        };
       
        script.onerror = function() {
            console.warn('Не удалось загрузить particles.js');
            // Можно добавить fallback эффект
            addFallbackEffect();
        };
       
        document.head.appendChild(script);
    }
   
    // Основная функция инициализации частиц
    function initParticles() {
        var particleCount = getOptimalParticleCount();
       
        var config = {
            particles: {
                number: {
                    value: particleCount,
                    density: {
                        enable: true,
                        value_area: 1000
                    }
                },
                color: {
                    value: [themeColors.primary, themeColors.secondary, themeColors.accent]
                },
                shape: {
                    type: ['circle', 'triangle'],
                    stroke: {
                        width: 0,
                        color: themeColors.primary
                    },
                    polygon: {
                        nb_sides: 6
                    }
                },
                opacity: {
                    value: 0.6,
                    random: true,
                    anim: {
                        enable: true,
                        speed: 0.8,
                        opacity_min: 0.1,
                        sync: false
                    }
                },
                size: {
                    value: 4,
                    random: true,
                    anim: {
                        enable: true,
                        speed: 2,
                        size_min: 0.5,
                        sync: false
                    }
                },
                line_linked: {
                    enable: true,
                    distance: 180,
                    color: themeColors.primary,
                    opacity: 0.3,
                    width: 1.5
                },
                move: {
                    enable: true,
                    speed: isMobile ? 2 : 4,
                    direction: 'none',
                    random: true,
                    straight: false,
                    out_mode: 'out',
                    bounce: false,
                    attract: {
                        enable: true,
                        rotateX: 600,
                        rotateY: 1200
                    }
                }
            },
            interactivity: {
                detect_on: 'window',
                events: {
                    onhover: {
                        enable: !isMobile,
                        mode: 'grab'
                    },
                    onclick: {
                        enable: true,
                        mode: 'push'
                    },
                    resize: true
                },
                modes: {
                    grab: {
                        distance: 200,
                        line_linked: {
                            opacity: 0.8
                        }
                    },
                    bubble: {
                        distance: 300,
                        size: 8,
                        duration: 2,
                        opacity: 0.8,
                        speed: 3
                    },
                    repulse: {
                        distance: 150,
                        duration: 0.4
                    },
                    push: {
                        particles_nb: 3
                    },
                    remove: {
                        particles_nb: 2
                    }
                }
            },
            retina_detect: true
        };
       
        // Инициализируем частицы с callback
        particlesJS('particles-js', config, function() {
            console.log('Particles.js: система частиц активирована');
            document.getElementById('particles-js').classList.add('loaded');
        });
       
        // Добавляем контроли производительности
        addPerformanceControls();
    }
   
    // Определяем оптимальное количество частиц
    function getOptimalParticleCount() {
        var baseCount = 60;
       
        if (isMobile) return Math.floor(baseCount * 0.5);
        if (isLowPerformance) return Math.floor(baseCount * 0.7);
        if (window.innerWidth < 1200) return Math.floor(baseCount * 0.8);
       
        return baseCount;
    }
   
    // Добавляем контроли производительности
    function addPerformanceControls() {
        var particleContainer = document.getElementById('particles-js');
        if (!particleContainer) return;
       
        // Уменьшаем интенсивность при переключении вкладок
        document.addEventListener('visibilitychange', function() {
            if (document.hidden) {
                particleContainer.style.opacity = '0.1';
            } else {
                particleContainer.style.opacity = '0.8';
            }
        });
       
        // Адаптируем к изменению размера окна
        var resizeTimeout;
        window.addEventListener('resize', function() {
            clearTimeout(resizeTimeout);
            resizeTimeout = setTimeout(function() {
                if (window.pJSDom && window.pJSDom[0]) {
                    window.pJSDom[0].pJS.fn.particlesRefresh();
                }
            }, 300);
        });
    }
   
    // Fallback эффект при неудачной загрузке
    function addFallbackEffect() {
        var particleContainer = document.getElementById('particles-js');
        if (!particleContainer) return;
       
        particleContainer.innerHTML = `
            <div style="
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: radial-gradient(ellipse at center,
                    rgba(119, 193, 217, 0.1) 0%,
                    rgba(26, 26, 31, 0.8) 70%);
                animation: pulseGlow 4s ease-in-out infinite;
            "></div>
        `;
       
        var fallbackStyle = document.createElement('style');
        fallbackStyle.innerHTML = `
            @keyframes pulseGlow {
                0%, 100% { opacity: 0.3; }
                50% { opacity: 0.6; }
            }
        `;
        document.head.appendChild(fallbackStyle);
    }
   
    // Функция очистки (для отладки)
    function cleanupParticles() {
        var container = document.getElementById('particles-js');
        var styles = document.getElementById('particles-styles');
       
        if (container) container.remove();
        if (styles) styles.remove();
       
        if (window.pJSDom) {
            window.pJSDom = [];
        }
    }
   
    // Экспорт функций для отладки
    window.particleSystem = {
        init: initParticleSystem,
        cleanup: cleanupParticles,
        config: themeColors
    };
   
    // Инициализация после загрузки MediaWiki
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initParticleSystem);
    } else {
        initParticleSystem();
    }
   
})();
 
// Дополнительные улучшения для интеграции с темой
mw.hook('wikipage.content').add(function($content) {
    // Подстраиваем частицы под контент страницы
    setTimeout(function() {
        if (window.pJSDom && window.pJSDom[0]) {
            window.pJSDom[0].pJS.fn.particlesRefresh();
        }
    }, 500);
});

Текущая версия от 01:51, 1 августа 2025

(function() {
    'use strict';
    
    // Проверяем, что мы не на мобильном устройстве (для производительности)
    var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    var isLowPerformance = navigator.hardwareConcurrency < 4;
    
    // Конфигурация частиц под тему сайта
    var themeColors = {
        primary: '#77c1d9',
        secondary: '#9dd7ea',
        accent: '#b8e6ff',
        background: '#1a1a1f'
    };
    
    // Функция создания и настройки частиц
    function initParticleSystem() {
        // Проверяем, не создан ли уже контейнер
        if (document.getElementById('particles-js')) {
            return;
        }
        
        // Создаем стилизованный контейнер
        var particlesDiv = document.createElement('div');
        particlesDiv.id = 'particles-js';
        particlesDiv.setAttribute('aria-hidden', 'true'); // Для доступности
        
        // Вставляем после body, но перед основным контентом
        var mwBody = document.querySelector('.mw-body');
        if (mwBody) {
            document.body.insertBefore(particlesDiv, mwBody);
        } else {
            document.body.appendChild(particlesDiv);
        }
        
        // Улучшенные стили с адаптивностью
        var particleStyles = document.createElement('style');
        particleStyles.id = 'particles-styles';
        particleStyles.innerHTML = `
            #particles-js {
                position: fixed;
                top: 0;
                left: 0;
                width: 100vw;
                height: 100vh;
                z-index: -1;
                pointer-events: none;
                opacity: 0.8;
                transition: opacity 0.5s ease;
            }
            
            /* Уменьшаем эффект на маленьких экранах */
            @media (max-width: 768px) {
                #particles-js {
                    opacity: 0.3;
                }
            }
            
            /* Полностью отключаем на очень маленьких экранах */
            @media (max-width: 480px) {
                #particles-js {
                    display: none;
                }
            }
            
            /* Уменьшаем эффект при предпочтении пользователя */
            @media (prefers-reduced-motion: reduce) {
                #particles-js {
                    opacity: 0.2;
                }
            }
            
            /* Адаптация под высокий DPI */
            @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
                #particles-js canvas {
                    image-rendering: crisp-edges;
                }
            }
            
            /* Плавное появление частиц */
            #particles-js.loaded {
                animation: particlesFadeIn 2s ease-in;
            }
            
            @keyframes particlesFadeIn {
                from { opacity: 0; }
                to { opacity: 0.8; }
            }
        `;
        document.head.appendChild(particleStyles);
        
        // Загружаем библиотеку с обработкой ошибок
        loadParticlesLibrary();
    }
    
    // Улучшенная функция загрузки библиотеки
    function loadParticlesLibrary() {
        // Проверяем, не загружена ли уже библиотека
        if (window.particlesJS) {
            initParticles();
            return;
        }
        
        var script = document.createElement('script');
        script.src = 'https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js';
        script.async = true;
        script.defer = true;
        
        script.onload = function() {
            console.log('Particles.js загружена успешно');
            initParticles();
        };
        
        script.onerror = function() {
            console.warn('Не удалось загрузить particles.js');
            // Можно добавить fallback эффект
            addFallbackEffect();
        };
        
        document.head.appendChild(script);
    }
    
    // Основная функция инициализации частиц
    function initParticles() {
        var particleCount = getOptimalParticleCount();
        
        var config = {
            particles: {
                number: {
                    value: particleCount,
                    density: {
                        enable: true,
                        value_area: 1000
                    }
                },
                color: {
                    value: [themeColors.primary, themeColors.secondary, themeColors.accent]
                },
                shape: {
                    type: ['circle', 'triangle'],
                    stroke: {
                        width: 0,
                        color: themeColors.primary
                    },
                    polygon: {
                        nb_sides: 6
                    }
                },
                opacity: {
                    value: 0.6,
                    random: true,
                    anim: {
                        enable: true,
                        speed: 0.8,
                        opacity_min: 0.1,
                        sync: false
                    }
                },
                size: {
                    value: 4,
                    random: true,
                    anim: {
                        enable: true,
                        speed: 2,
                        size_min: 0.5,
                        sync: false
                    }
                },
                line_linked: {
                    enable: true,
                    distance: 180,
                    color: themeColors.primary,
                    opacity: 0.3,
                    width: 1.5
                },
                move: {
                    enable: true,
                    speed: isMobile ? 2 : 4,
                    direction: 'none',
                    random: true,
                    straight: false,
                    out_mode: 'out',
                    bounce: false,
                    attract: {
                        enable: true,
                        rotateX: 600,
                        rotateY: 1200
                    }
                }
            },
            interactivity: {
                detect_on: 'window',
                events: {
                    onhover: {
                        enable: !isMobile,
                        mode: 'grab'
                    },
                    onclick: {
                        enable: true,
                        mode: 'push'
                    },
                    resize: true
                },
                modes: {
                    grab: {
                        distance: 200,
                        line_linked: {
                            opacity: 0.8
                        }
                    },
                    bubble: {
                        distance: 300,
                        size: 8,
                        duration: 2,
                        opacity: 0.8,
                        speed: 3
                    },
                    repulse: {
                        distance: 150,
                        duration: 0.4
                    },
                    push: {
                        particles_nb: 3
                    },
                    remove: {
                        particles_nb: 2
                    }
                }
            },
            retina_detect: true
        };
        
        // Инициализируем частицы с callback
        particlesJS('particles-js', config, function() {
            console.log('Particles.js: система частиц активирована');
            document.getElementById('particles-js').classList.add('loaded');
        });
        
        // Добавляем контроли производительности
        addPerformanceControls();
    }
    
    // Определяем оптимальное количество частиц
    function getOptimalParticleCount() {
        var baseCount = 60;
        
        if (isMobile) return Math.floor(baseCount * 0.5);
        if (isLowPerformance) return Math.floor(baseCount * 0.7);
        if (window.innerWidth < 1200) return Math.floor(baseCount * 0.8);
        
        return baseCount;
    }
    
    // Добавляем контроли производительности
    function addPerformanceControls() {
        var particleContainer = document.getElementById('particles-js');
        if (!particleContainer) return;
        
        // Уменьшаем интенсивность при переключении вкладок
        document.addEventListener('visibilitychange', function() {
            if (document.hidden) {
                particleContainer.style.opacity = '0.1';
            } else {
                particleContainer.style.opacity = '0.8';
            }
        });
        
        // Адаптируем к изменению размера окна
        var resizeTimeout;
        window.addEventListener('resize', function() {
            clearTimeout(resizeTimeout);
            resizeTimeout = setTimeout(function() {
                if (window.pJSDom && window.pJSDom[0]) {
                    window.pJSDom[0].pJS.fn.particlesRefresh();
                }
            }, 300);
        });
    }
    
    // Fallback эффект при неудачной загрузке
    function addFallbackEffect() {
        var particleContainer = document.getElementById('particles-js');
        if (!particleContainer) return;
        
        particleContainer.innerHTML = `
            <div style="
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: radial-gradient(ellipse at center, 
                    rgba(119, 193, 217, 0.1) 0%, 
                    rgba(26, 26, 31, 0.8) 70%);
                animation: pulseGlow 4s ease-in-out infinite;
            "></div>
        `;
        
        var fallbackStyle = document.createElement('style');
        fallbackStyle.innerHTML = `
            @keyframes pulseGlow {
                0%, 100% { opacity: 0.3; }
                50% { opacity: 0.6; }
            }
        `;
        document.head.appendChild(fallbackStyle);
    }
    
    // Функция очистки (для отладки)
    function cleanupParticles() {
        var container = document.getElementById('particles-js');
        var styles = document.getElementById('particles-styles');
        
        if (container) container.remove();
        if (styles) styles.remove();
        
        if (window.pJSDom) {
            window.pJSDom = [];
        }
    }
    
    // Экспорт функций для отладки
    window.particleSystem = {
        init: initParticleSystem,
        cleanup: cleanupParticles,
        config: themeColors
    };
    
    // Инициализация после загрузки MediaWiki
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initParticleSystem);
    } else {
        initParticleSystem();
    }
    
})();

// Дополнительные улучшения для интеграции с темой
mw.hook('wikipage.content').add(function($content) {
    // Подстраиваем частицы под контент страницы
    setTimeout(function() {
        if (window.pJSDom && window.pJSDom[0]) {
            window.pJSDom[0].pJS.fn.particlesRefresh();
        }
    }, 500);
});