|
|
| Рядок 1: |
Рядок 1: |
| // ========================= | | // ========================= |
| // ОСНОВНИЙ КОД ДЛЯ ТЕМ, ДОСТУПНОСТІ ТА ЛУПИ | | // ОСНОВНІ КНОПКИ ПРАВОРУЧ |
| // ========================= | | // ========================= |
| $(function () { | | $(function () { |
| Рядок 14: |
Рядок 14: |
| } | | } |
| | | |
| // Завантажуємо тему
| |
| if (themes[theme]) { | | if (themes[theme]) { |
| mw.loader.load(themes[theme], 'text/css'); | | mw.loader.load(themes[theme], 'text/css'); |
| Рядок 29: |
Рядок 28: |
| } | | } |
|
| |
|
| // Масив для збереження позицій кнопок
| | // Функція створення кнопки праворуч |
| var buttonCount = 0;
| |
| | |
| // Функція створення кнопки праворуч з автоматичним вертикальним розташуванням | |
| function createButtonRight(text, onClick, title) { | | function createButtonRight(text, onClick, title) { |
| var btn = document.createElement('button'); | | var btn = document.createElement('button'); |
| Рядок 39: |
Рядок 35: |
| btn.style.position = 'fixed'; | | btn.style.position = 'fixed'; |
| btn.style.right = '10px'; | | btn.style.right = '10px'; |
| btn.style.bottom = (10 + buttonCount * 60) + 'px'; // вертикальний відступ між кнопками | | btn.style.bottom = (10 + document.querySelectorAll('.right-button').length * 60) + 'px'; |
| btn.style.padding = '10px 16px'; | | btn.style.padding = '10px 16px'; |
| btn.style.border = 'none'; | | btn.style.border = 'none'; |
| Рядок 52: |
Рядок 48: |
| btn.style.boxShadow = '0 2px 6px rgba(0,0,0,0.3)'; | | btn.style.boxShadow = '0 2px 6px rgba(0,0,0,0.3)'; |
| btn.style.whiteSpace = 'nowrap'; | | btn.style.whiteSpace = 'nowrap'; |
| | btn.className = 'right-button'; |
|
| |
|
| btn.onclick = onClick; | | btn.onclick = onClick; |
| document.body.appendChild(btn); | | document.body.appendChild(btn); |
|
| |
| buttonCount++; // збільшуємо лічильник кнопок для наступного bottom
| |
| return btn; | | return btn; |
| } | | } |
| Рядок 73: |
Рядок 68: |
| // Кнопка доступності | | // Кнопка доступності |
| createButtonRight( | | createButtonRight( |
| localStorage.getItem('accessibilityMode') === 'on' ? 'Доступність' : 'Доступність', | | 'Доступність', |
| function () { | | function () { |
| if (!$('body').hasClass('accessibility-mode')) { | | if (!$('body').hasClass('accessibility-mode')) { |
| Рядок 101: |
Рядок 96: |
| }, 'Зменшити шрифт'); | | }, 'Зменшити шрифт'); |
|
| |
|
| // Застосовуємо шрифт при завантаженні
| |
| applyFontSize(); | | applyFontSize(); |
|
| |
|
| // Відновлення стану доступності при завантаженні
| |
| if (localStorage.getItem('accessibilityMode') === 'on') { | | if (localStorage.getItem('accessibilityMode') === 'on') { |
| $('body').addClass('accessibility-mode'); | | $('body').addClass('accessibility-mode'); |
| } | | } |
| }); | | }); |
|
| |
|
| |
|
| // ========================= | | // ========================= |
| // ВАШ СТАРИЙ OVERLAY КОД (без змін) | | // КНОПКИ ЗЛІВА: ВИПАДКОВА СТОРІНКА ТА ЯК ЦЕ ПРАЦЮЄ |
| // ========================= | | // ========================= |
| (function() {
| | function createLeftButtons() { |
| 'use strict'; | | // Перевіряємо чи це Minerva тема |
| | if (!document.body.classList.contains('skin-minerva')) { |
| | return; |
| | } |
| | | |
| // Конфигурація в стилі MediaViewer
| |
| const config = {
| |
| // Стиль оверлею
| |
| overlayBg: 'rgba(0,0,0,0.95)',
| |
| animationDuration: '0.3s',
| |
|
| |
| // Стиль зображення
| |
| imageMaxWidth: '90vw',
| |
| imageMaxHeight: '80vh',
| |
|
| |
| // Панель інформації
| |
| infoPanel: {
| |
| background: 'rgba(0,0,0,0.8)',
| |
| color: '#fff',
| |
| padding: '15px',
| |
| borderRadius: '8px',
| |
| marginTop: '15px',
| |
| maxWidth: '600px',
| |
| fontSize: '14px'
| |
| },
| |
|
| |
| // Кнопки
| |
| buttons: {
| |
| background: 'rgba(0,0,0,0.7)',
| |
| color: '#fff',
| |
| size: '40px',
| |
| fontSize: '18px',
| |
| borderRadius: '5px',
| |
| margin: '5px'
| |
| },
| |
|
| |
| // Кнопка закриття
| |
| closeBtn: {
| |
| background: 'rgba(0,0,0,0.7)',
| |
| color: '#fff',
| |
| size: '40px',
| |
| fontSize: '20px',
| |
| top: '20px',
| |
| right: '20px'
| |
| },
| |
|
| |
| // Винятки
| |
| excludeSelectors: [
| |
| '.no-overlay',
| |
| '[data-no-overlay]',
| |
| '.mw-editsection img',
| |
| '.sprite',
| |
| '.icon',
| |
| '.logo',
| |
| '.nav-icon'
| |
| ]
| |
| };
| |
|
| |
| let currentOverlay = null;
| |
| let currentImageIndex = 0;
| |
| let imagesInGallery = [];
| |
| let currentScale = 1;
| |
| const minScale = 0.5;
| |
| const maxScale = 3;
| |
| const scaleStep = 0.25;
| |
|
| |
| // Повністю відключаємо стандартний MediaViewer
| |
| function disableMediaViewerCompletely() {
| |
| const mediaViewerLinks = document.querySelectorAll('a[href*="/wiki/File:"], a[href*="/w/images/"]');
| |
| mediaViewerLinks.forEach(link => {
| |
| link.removeAttribute('data-mw');
| |
| link.removeAttribute('data-mediatype');
| |
| link.removeAttribute('data-file');
| |
|
| |
| link.addEventListener('click', function(e) {
| |
| const img = this.querySelector('img');
| |
| if (img && shouldOpenInOverlay(img)) {
| |
| e.preventDefault();
| |
| e.stopImmediatePropagation();
| |
| showMediaViewerOverlay(img);
| |
| return false;
| |
| }
| |
| }, true);
| |
| });
| |
| }
| |
|
| |
| // Створення оверлею в стилі MediaViewer
| |
| function createMediaViewerStyleOverlay() {
| |
| const overlay = document.createElement('div');
| |
| overlay.className = 'custom-media-viewer';
| |
| overlay.style.cssText = `
| |
| position: fixed;
| |
| top: 0;
| |
| left: 0;
| |
| width: 100%;
| |
| height: 100%;
| |
| background: ${config.overlayBg};
| |
| display: none;
| |
| justify-content: center;
| |
| align-items: center;
| |
| z-index: 10000;
| |
| opacity: 0;
| |
| transition: opacity ${config.animationDuration} ease;
| |
| cursor: default;
| |
| `;
| |
|
| |
| // Головний контейнер
| |
| const mainContainer = document.createElement('div');
| |
| mainContainer.style.cssText = `
| |
| position: relative;
| |
| display: flex;
| |
| flex-direction: column;
| |
| align-items: center;
| |
| max-width: 95vw;
| |
| max-height: 95vh;
| |
| `;
| |
|
| |
| // Кнопка закриття ×
| |
| const closeBtn = document.createElement('button');
| |
| closeBtn.innerHTML = '×';
| |
| closeBtn.title = 'Закрити (Esc)';
| |
| closeBtn.style.cssText = `
| |
| width: ${config.closeBtn.size};
| |
| height: ${config.closeBtn.size};
| |
| background: ${config.closeBtn.background};
| |
| color: ${config.closeBtn.color};
| |
| border: none;
| |
| border-radius: 50%;
| |
| font-size: ${config.closeBtn.fontSize};
| |
| cursor: pointer;
| |
| display: flex;
| |
| align-items: center;
| |
| justify-content: center;
| |
| transition: all 0.2s ease;
| |
| position: absolute;
| |
| top: ${config.closeBtn.top};
| |
| right: ${config.closeBtn.right};
| |
| z-index: 10001;
| |
| `;
| |
|
| |
| // Основний контейнер для зображення та кнопок
| |
| const imageAndControlsContainer = document.createElement('div');
| |
| imageAndControlsContainer.style.cssText = `
| |
| position: relative;
| |
| display: inline-block;
| |
| max-width: ${config.imageMaxWidth};
| |
| max-height: ${config.imageMaxHeight};
| |
| margin-bottom: 10px;
| |
| `;
| |
|
| |
| // Контейнер для зображення
| |
| const imageContainer = document.createElement('div');
| |
| imageContainer.style.cssText = `
| |
| position: relative;
| |
| display: block;
| |
| max-width: 100%;
| |
| max-height: 100%;
| |
| `;
| |
|
| |
| const img = document.createElement('img');
| |
| img.style.cssText = `
| |
| max-width: 100%;
| |
| max-height: 100%;
| |
| object-fit: contain;
| |
| border-radius: 8px;
| |
| box-shadow: 0 10px 30px rgba(0,0,0,0.5);
| |
| cursor: default !important;
| |
| transition: transform 0.3s ease;
| |
| display: block;
| |
| `;
| |
|
| |
| // Кнопки навігації (зліва/справа від зображення)
| |
| const prevBtn = createNavButton('‹', 'Попереднє зображення (←)');
| |
| const nextBtn = createNavButton('›', 'Наступне зображення (→)');
| |
| prevBtn.style.cssText += 'left: 10px;';
| |
| nextBtn.style.cssText += 'right: 10px;';
| |
|
| |
| // Контейнер для кнопок масштабування - ПРИКРІПЛЕНИЙ ДО НИЗУ ЗОБРАЖЕННЯ
| |
| const buttonPanel = document.createElement('div');
| |
| buttonPanel.className = 'zoom-controls-panel';
| |
| buttonPanel.style.cssText = `
| |
| position: absolute;
| |
| bottom: 10px;
| |
| left: 50%;
| |
| transform: translateX(-50%);
| |
| display: flex;
| |
| justify-content: center;
| |
| align-items: center;
| |
| gap: 8px;
| |
| background: rgba(0,0,0,0.8);
| |
| padding: 8px 12px;
| |
| border-radius: 8px;
| |
| z-index: 10001;
| |
| min-width: 200px;
| |
| backdrop-filter: blur(5px);
| |
| `;
| |
|
| |
| // Кнопки масштабування
| |
| const zoomOutBtn = createToolButton('−', 'Зменшити (Ctrl + -)');
| |
| const resetZoomBtn = createToolButton('1:1', 'Скинути масштаб (Ctrl + 0)');
| |
| const zoomInBtn = createToolButton('+', 'Збільшити (Ctrl + +)');
| |
| const infoBtn = createToolButton('i', 'Інформація (I)');
| |
|
| |
| // Панель інформації
| |
| const infoPanel = document.createElement('div');
| |
| infoPanel.className = 'image-info-panel';
| |
| infoPanel.style.cssText = `
| |
| background: ${config.infoPanel.background};
| |
| color: ${config.infoPanel.color};
| |
| padding: ${config.infoPanel.padding};
| |
| border-radius: ${config.infoPanel.borderRadius};
| |
| margin-top: 10px;
| |
| max-width: ${config.infoPanel.maxWidth};
| |
| width: 100%;
| |
| text-align: center;
| |
| font-size: ${config.infoPanel.fontSize};
| |
| display: none;
| |
| `;
| |
|
| |
| // Функція для оновлення позиції кнопок при зміні розміру зображення
| |
| function updateButtonPanelPosition() {
| |
| if (!img.parentElement) return;
| |
|
| |
| const imgRect = img.getBoundingClientRect();
| |
| const containerRect = imageAndControlsContainer.getBoundingClientRect();
| |
|
| |
| // Позиціонуємо кнопки відносно видимого зображення
| |
| if (imgRect.height > 0) {
| |
| buttonPanel.style.bottom = '10px';
| |
| }
| |
| }
| |
|
| |
| // Спостерігач за змінами розміру зображення
| |
| const resizeObserver = new ResizeObserver(() => {
| |
| updateButtonPanelPosition();
| |
| });
| |
|
| |
| // Збірка інтерфейсу
| |
| imageContainer.appendChild(img);
| |
| imageContainer.appendChild(prevBtn);
| |
| imageContainer.appendChild(nextBtn);
| |
| imageContainer.appendChild(buttonPanel);
| |
|
| |
| imageAndControlsContainer.appendChild(imageContainer);
| |
|
| |
| buttonPanel.appendChild(zoomOutBtn);
| |
| buttonPanel.appendChild(resetZoomBtn);
| |
| buttonPanel.appendChild(zoomInBtn);
| |
| buttonPanel.appendChild(infoBtn);
| |
|
| |
| mainContainer.appendChild(closeBtn);
| |
| mainContainer.appendChild(imageAndControlsContainer);
| |
| mainContainer.appendChild(infoPanel);
| |
|
| |
| overlay.appendChild(mainContainer);
| |
| document.body.appendChild(overlay);
| |
|
| |
| // Спостерігаємо за змінами розміру зображення
| |
| resizeObserver.observe(img);
| |
|
| |
| // Функції масштабування
| |
| function zoomImage(scale) {
| |
| currentScale = Math.max(minScale, Math.min(maxScale, scale));
| |
| img.style.transform = `scale(${currentScale})`;
| |
| updateZoomButtons();
| |
| // Оновлюємо позицію кнопок після масштабування
| |
| setTimeout(updateButtonPanelPosition, 50);
| |
| }
| |
|
| |
| function updateZoomButtons() {
| |
| zoomInBtn.disabled = currentScale >= maxScale;
| |
| zoomOutBtn.disabled = currentScale <= minScale;
| |
|
| |
| zoomInBtn.style.opacity = zoomInBtn.disabled ? '0.5' : '1';
| |
| zoomOutBtn.style.opacity = zoomOutBtn.disabled ? '0.5' : '1';
| |
| }
| |
|
| |
| // Обробники подій
| |
| function setupEventListeners() {
| |
| // Закриття
| |
| const closeOverlay = () => {
| |
| resizeObserver.disconnect();
| |
| overlay.style.opacity = '0';
| |
| setTimeout(() => {
| |
| overlay.style.display = 'none';
| |
| document.body.style.overflow = 'auto';
| |
| currentOverlay = null;
| |
| imagesInGallery = [];
| |
| currentScale = 1;
| |
| }, 300);
| |
| };
| |
|
| |
| closeBtn.addEventListener('click', closeOverlay);
| |
| overlay.addEventListener('click', (e) => {
| |
| if (e.target === overlay) closeOverlay();
| |
| });
| |
|
| |
| // Навігація
| |
| prevBtn.addEventListener('click', (e) => {
| |
| e.stopPropagation();
| |
| navigateImages(-1);
| |
| });
| |
|
| |
| nextBtn.addEventListener('click', (e) => {
| |
| e.stopPropagation();
| |
| navigateImages(1);
| |
| });
| |
|
| |
| // Масштабування
| |
| zoomInBtn.addEventListener('click', (e) => {
| |
| e.stopPropagation();
| |
| zoomImage(currentScale + scaleStep);
| |
| });
| |
|
| |
| zoomOutBtn.addEventListener('click', (e) => {
| |
| e.stopPropagation();
| |
| zoomImage(currentScale - scaleStep);
| |
| });
| |
|
| |
| resetZoomBtn.addEventListener('click', (e) => {
| |
| e.stopPropagation();
| |
| currentScale = 1;
| |
| img.style.transform = 'scale(1)';
| |
| updateZoomButtons();
| |
| setTimeout(updateButtonPanelPosition, 50);
| |
| });
| |
|
| |
| // Інформація
| |
| infoBtn.addEventListener('click', (e) => {
| |
| e.stopPropagation();
| |
| toggleInfoPanel();
| |
| });
| |
|
| |
| // Клавіатура
| |
| const keyHandler = (e) => {
| |
| if (!currentOverlay) return;
| |
|
| |
| switch(e.key) {
| |
| case 'Escape':
| |
| closeOverlay();
| |
| break;
| |
| case 'ArrowLeft':
| |
| navigateImages(-1);
| |
| break;
| |
| case 'ArrowRight':
| |
| navigateImages(1);
| |
| break;
| |
| case 'i':
| |
| case 'І':
| |
| e.preventDefault();
| |
| toggleInfoPanel();
| |
| break;
| |
| case '+':
| |
| case '=':
| |
| if (e.ctrlKey) {
| |
| e.preventDefault();
| |
| zoomImage(currentScale + scaleStep);
| |
| }
| |
| break;
| |
| case '-':
| |
| if (e.ctrlKey) {
| |
| e.preventDefault();
| |
| zoomImage(currentScale - scaleStep);
| |
| }
| |
| break;
| |
| case '0':
| |
| if (e.ctrlKey) {
| |
| e.preventDefault();
| |
| currentScale = 1;
| |
| img.style.transform = 'scale(1)';
| |
| updateZoomButtons();
| |
| setTimeout(updateButtonPanelPosition, 50);
| |
| }
| |
| break;
| |
| }
| |
| };
| |
|
| |
| document.addEventListener('keydown', keyHandler);
| |
|
| |
| // Видаляємо обробник при закритті
| |
| overlay.addEventListener('click', function handler() {
| |
| if (overlay.style.display === 'none') {
| |
| document.removeEventListener('keydown', keyHandler);
| |
| overlay.removeEventListener('click', handler);
| |
| }
| |
| });
| |
|
| |
| // Hover ефекти
| |
| [closeBtn, prevBtn, nextBtn, zoomInBtn, zoomOutBtn, resetZoomBtn, infoBtn].forEach(btn => {
| |
| btn.addEventListener('mouseenter', () => {
| |
| if (!btn.disabled) {
| |
| btn.style.background = 'rgba(0,0,0,0.9)';
| |
| btn.style.transform = 'scale(1.1)';
| |
| }
| |
| });
| |
| btn.addEventListener('mouseleave', () => {
| |
| btn.style.background = config.buttons.background;
| |
| btn.style.transform = 'scale(1)';
| |
| });
| |
| });
| |
|
| |
| // Оновлюємо позицію при завантаженні зображення
| |
| img.addEventListener('load', () => {
| |
| setTimeout(updateButtonPanelPosition, 100);
| |
| });
| |
| }
| |
|
| |
| setupEventListeners();
| |
| updateZoomButtons();
| |
|
| |
| return {
| |
| overlay,
| |
| img,
| |
| infoPanel,
| |
| prevBtn,
| |
| nextBtn,
| |
| zoomInBtn,
| |
| zoomOutBtn,
| |
| resetZoomBtn,
| |
| infoBtn,
| |
| buttonPanel,
| |
| updateZoomButtons,
| |
| updateButtonPanelPosition
| |
| };
| |
| }
| |
|
| |
| // Створення кнопки навігації
| |
| function createNavButton(text, title) {
| |
| const btn = document.createElement('button');
| |
| btn.innerHTML = text;
| |
| btn.title = title;
| |
| btn.style.cssText = `
| |
| position: absolute;
| |
| top: 50%;
| |
| transform: translateY(-50%);
| |
| width: ${config.buttons.size};
| |
| height: ${config.buttons.size};
| |
| background: ${config.buttons.background};
| |
| color: ${config.buttons.color};
| |
| border: none;
| |
| border-radius: 50%;
| |
| font-size: ${config.buttons.fontSize};
| |
| cursor: pointer;
| |
| display: none;
| |
| align-items: center;
| |
| justify-content: center;
| |
| transition: all 0.2s ease;
| |
| z-index: 10001;
| |
| `;
| |
| return btn;
| |
| }
| |
|
| |
| // Створення кнопки інструменту
| |
| function createToolButton(text, title) {
| |
| const btn = document.createElement('button');
| |
| btn.innerHTML = text;
| |
| btn.title = title;
| |
| btn.style.cssText = `
| |
| min-width: ${config.buttons.size};
| |
| height: ${config.buttons.size};
| |
| background: ${config.buttons.background};
| |
| color: ${config.buttons.color};
| |
| border: none;
| |
| border-radius: ${config.buttons.borderRadius};
| |
| font-size: ${config.buttons.fontSize};
| |
| cursor: pointer;
| |
| display: flex;
| |
| align-items: center;
| |
| justify-content: center;
| |
| transition: all 0.2s ease;
| |
| padding: 0 10px;
| |
| `;
| |
| return btn;
| |
| }
| |
|
| |
| // Навігація по зображенням
| |
| function navigateImages(direction) {
| |
| if (imagesInGallery.length <= 1) return;
| |
|
| |
| currentImageIndex += direction;
| |
|
| |
| if (currentImageIndex < 0) {
| |
| currentImageIndex = imagesInGallery.length - 1;
| |
| } else if (currentImageIndex >= imagesInGallery.length) {
| |
| currentImageIndex = 0;
| |
| }
| |
|
| |
| showImage(imagesInGallery[currentImageIndex]);
| |
| }
| |
|
| |
| // Показ інформації
| |
| function toggleInfoPanel() {
| |
| if (!currentOverlay) return;
| |
| const infoPanel = currentOverlay.infoPanel;
| |
| infoPanel.style.display = infoPanel.style.display === 'none' ? 'block' : 'none';
| |
| }
| |
|
| |
| // Збір всіх зображень на сторінці для галереї
| |
| function collectAllImages(clickedImage) {
| |
| const images = Array.from(document.querySelectorAll('img'))
| |
| .filter(img => shouldOpenInOverlay(img) && !img.closest('.custom-media-viewer'))
| |
| .map(img => ({
| |
| src: img.src,
| |
| alt: img.alt || 'Зображення',
| |
| title: img.title || '',
| |
| width: img.naturalWidth,
| |
| height: img.naturalHeight
| |
| }));
| |
|
| |
| currentImageIndex = images.findIndex(img => img.src === clickedImage.src);
| |
| return images;
| |
| }
| |
|
| |
| // Перевірка, чи повинна картинка відкриватися в оверлеї
| |
| function shouldOpenInOverlay(element) {
| |
| if (config.excludeSelectors.some(selector =>
| |
| element.matches(selector) || element.closest(selector))) {
| |
| return false;
| |
| }
| |
|
| |
| if (element.width < 50 || element.height < 50) {
| |
| return false;
| |
| }
| |
|
| |
| if (element.closest('.gallery, .thumb, .mw-gallery')) {
| |
| return false;
| |
| }
| |
|
| |
| return true;
| |
| }
| |
|
| |
| // Показ оверлею
| |
| function showMediaViewerOverlay(imageElement) {
| |
| if (imageElement.closest('a')) {
| |
| const link = imageElement.closest('a');
| |
| if (link.href && link.href.includes('/wiki/File:')) {
| |
| link.addEventListener('click', function(e) {
| |
| e.preventDefault();
| |
| e.stopImmediatePropagation();
| |
| }, true);
| |
| }
| |
| }
| |
|
| |
| if (!currentOverlay) {
| |
| currentOverlay = createMediaViewerStyleOverlay();
| |
| }
| |
|
| |
| imagesInGallery = collectAllImages(imageElement);
| |
|
| |
| if (imagesInGallery.length === 0) return;
| |
|
| |
| showImage(imagesInGallery[currentImageIndex]);
| |
|
| |
| currentOverlay.overlay.style.display = 'flex';
| |
| setTimeout(() => {
| |
| currentOverlay.overlay.style.opacity = '1';
| |
| }, 10);
| |
|
| |
| document.body.style.overflow = 'hidden';
| |
|
| |
| currentOverlay.prevBtn.style.display = imagesInGallery.length > 1 ? 'flex' : 'none';
| |
| currentOverlay.nextBtn.style.display = imagesInGallery.length > 1 ? 'flex' : 'none';
| |
|
| |
| currentScale = 1;
| |
| currentOverlay.img.style.transform = 'scale(1)';
| |
| if (currentOverlay.updateZoomButtons) {
| |
| currentOverlay.updateZoomButtons();
| |
| }
| |
|
| |
| // Оновлюємо позицію кнопок після показу
| |
| setTimeout(() => {
| |
| if (currentOverlay && currentOverlay.updateButtonPanelPosition) {
| |
| currentOverlay.updateButtonPanelPosition();
| |
| }
| |
| }, 200);
| |
| }
| |
|
| |
| // Показ конкретного зображення
| |
| function showImage(imageData) {
| |
| if (!currentOverlay) return;
| |
|
| |
| currentOverlay.img.src = imageData.src;
| |
| currentOverlay.img.alt = imageData.alt;
| |
|
| |
| currentOverlay.infoPanel.innerHTML = `
| |
| <div><strong>${imageData.alt}</strong></div>
| |
| <div>Розмір: ${imageData.width} × ${imageData.height}px</div>
| |
| <div style="margin-top: 10px; opacity: 0.7;">
| |
| ← → для навігації • I для інформації • Ctrl + +-/0 для масштабу • Esc для закриття
| |
| </div>
| |
| `;
| |
|
| |
| currentScale = 1;
| |
| currentOverlay.img.style.transform = 'scale(1)';
| |
| if (currentOverlay.updateZoomButtons) {
| |
| currentOverlay.updateZoomButtons();
| |
| }
| |
|
| |
| // Оновлюємо позицію кнопок після завантаження нового зображення
| |
| currentOverlay.img.onload = () => {
| |
| setTimeout(() => {
| |
| if (currentOverlay && currentOverlay.updateButtonPanelPosition) {
| |
| currentOverlay.updateButtonPanelPosition();
| |
| }
| |
| }, 100);
| |
| };
| |
| }
| |
|
| |
| // Обробник кліків
| |
| document.addEventListener('click', function(e) {
| |
| const target = e.target;
| |
|
| |
| if (target.closest('.custom-media-viewer')) {
| |
| return;
| |
| }
| |
|
| |
| if (target.tagName === 'IMG' && shouldOpenInOverlay(target)) {
| |
| e.preventDefault();
| |
| e.stopImmediatePropagation();
| |
| showMediaViewerOverlay(target);
| |
| return false;
| |
| }
| |
|
| |
| if (target.tagName === 'A' && target.href &&
| |
| (target.href.match(/\/wiki\/File:|\.(jpg|jpeg|png|gif|webp)(\?|$)/i))) {
| |
| const img = target.querySelector('img');
| |
| if (img && shouldOpenInOverlay(img)) {
| |
| e.preventDefault();
| |
| e.stopImmediatePropagation();
| |
| showMediaViewerOverlay(img);
| |
| return false;
| |
| }
| |
| }
| |
| }, true);
| |
|
| |
| // Повністю відключаємо MediaViewer при завантаженні
| |
| document.addEventListener('DOMContentLoaded', disableMediaViewerCompletely);
| |
| setTimeout(disableMediaViewerCompletely, 100);
| |
|
| |
| // Стилі
| |
| const style = document.createElement('style');
| |
| style.textContent = `
| |
| .custom-media-viewer * {
| |
| box-sizing: border-box;
| |
| }
| |
|
| |
| .custom-media-viewer button:hover:not(:disabled) {
| |
| transform: scale(1.1) !important;
| |
| background: rgba(0,0,0,0.9) !important;
| |
| }
| |
|
| |
| .custom-media-viewer button:disabled {
| |
| cursor: not-allowed !important;
| |
| opacity: 0.5 !important;
| |
| }
| |
|
| |
| .custom-media-viewer img {
| |
| transition: transform 0.3s ease !important;
| |
| cursor: default !important;
| |
| }
| |
|
| |
| /* Панель кнопок масштабування - завжди внизу зображення */
| |
| .zoom-controls-panel {
| |
| position: absolute !important;
| |
| bottom: 10px !important;
| |
| left: 50% !important;
| |
| transform: translateX(-50%) !important;
| |
| background: rgba(0,0,0,0.8) !important;
| |
| padding: 8px 12px !important;
| |
| border-radius: 8px !important;
| |
| z-index: 10001 !important;
| |
| min-width: 200px !important;
| |
| backdrop-filter: blur(5px) !important;
| |
| }
| |
|
| |
| /* Контейнер зображення */
| |
| .custom-media-viewer .image-container {
| |
| position: relative !important;
| |
| display: inline-block !important;
| |
| }
| |
|
| |
| /* Повністю ховаємо стандартний MediaViewer */
| |
| .mw-mmv-overlay,
| |
| .mediaViewerOverlay {
| |
| display: none !important;
| |
| }
| |
|
| |
| @media (max-width: 768px) {
| |
| .custom-media-viewer button {
| |
| min-width: 35px !important;
| |
| height: 35px !important;
| |
| font-size: 16px !important;
| |
| padding: 0 8px !important;
| |
| }
| |
|
| |
| .image-info-panel {
| |
| font-size: 12px !important;
| |
| padding: 10px !important;
| |
| margin-top: 10px !important;
| |
| }
| |
|
| |
| .zoom-controls-panel {
| |
| min-width: 180px !important;
| |
| padding: 6px 10px !important;
| |
| bottom: 8px !important;
| |
| }
| |
| }
| |
|
| |
| @media (max-width: 480px) {
| |
| .custom-media-viewer button {
| |
| min-width: 30px !important;
| |
| height: 30px !important;
| |
| font-size: 14px !important;
| |
| padding: 0 6px !important;
| |
| }
| |
|
| |
| .zoom-controls-panel {
| |
| min-width: 160px !important;
| |
| padding: 5px 8px !important;
| |
| bottom: 5px !important;
| |
| gap: 5px !important;
| |
| }
| |
| }
| |
| `;
| |
| document.head.appendChild(style);
| |
|
| |
| })();
| |
|
| |
| // =========================
| |
| // =========================
| |
| // КНОПКИ ВИПАДКОВА СТОРІНКА ТА ЯК ЦЕ ПРАЦЮЄ
| |
| // =========================
| |
| function createLeftSideButtons() {
| |
| // Перевіряємо чи кнопки вже існують | | // Перевіряємо чи кнопки вже існують |
| if (document.getElementById('how-it-works-btn') || document.getElementById('float-random-btn')) { | | if (document.getElementById('left-random-btn') || document.getElementById('left-how-btn')) { |
| return; | | return; |
| } | | } |
| | | |
| // Перевіряємо чи це мобільна версія | | console.log('Створюємо ліві кнопки для Minerva'); |
| if (!document.body.classList.contains('skin-minerva')) {
| |
| return;
| |
| }
| |
| | | |
| // Визначаємо висоту для врахування екранної клавіатури | | // Визначаємо відступ для клавіатури |
| const keyboardOffset = 80; // Відступ для клавіатури | | const keyboardHeight = 100; |
| | | |
| // 1. Спочатку створюємо кнопку "Як це працює?" (кругла, вище) | | // 1. Кнопка "Як це працює?" (кругла, зелена) |
| const howItWorksBtn = document.createElement('button'); | | const howBtn = document.createElement('button'); |
| howItWorksBtn.id = 'how-it-works-btn'; | | howBtn.id = 'left-how-btn'; |
| howItWorksBtn.innerHTML = '?'; | | howBtn.innerHTML = '?'; |
| howItWorksBtn.title = 'Як це працює?'; | | howBtn.title = 'Як це працює?'; |
| howItWorksBtn.style.cssText = ` | | howBtn.style.cssText = ` |
| position: fixed; | | position: fixed; |
| bottom: ${140 + keyboardOffset}px; /* Вище за кнопку випадкової сторінки */ | | bottom: ${120 + keyboardHeight}px; |
| left: 20px; | | left: 15px; |
| z-index: 9998; | | z-index: 9998; |
| background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%); | | background: #4CAF50; |
| color: white; | | color: white; |
| border: none; | | border: none; |
| width: 60px; | | width: 50px; |
| height: 60px; | | height: 50px; |
| border-radius: 50%; | | border-radius: 50%; |
| font-size: 24px; | | font-size: 20px; |
| font-weight: bold; | | font-weight: bold; |
| cursor: pointer; | | cursor: pointer; |
| box-shadow: 0 4px 15px rgba(0,0,0,0.3); | | box-shadow: 0 2px 10px rgba(0,0,0,0.3); |
| display: flex; | | display: flex; |
| align-items: center; | | align-items: center; |
| justify-content: center; | | justify-content: center; |
| transition: all 0.3s ease; | | transition: all 0.2s ease; |
| line-height: 1;
| |
| `; | | `; |
| | | |
| // 2. Потім створюємо кнопку "Випадкова сторінка" (звичайна, нижче) | | // 2. Кнопка "Випадкова сторінка" (червона) |
| const randomBtn = document.createElement('button'); | | const randomBtn = document.createElement('button'); |
| randomBtn.id = 'float-random-btn'; | | randomBtn.id = 'left-random-btn'; |
| randomBtn.innerHTML = '🎲 Випадкова cторінка'; | | randomBtn.innerHTML = '🎲 Випадкова'; |
| randomBtn.title = 'Випадкова сторінка'; | | randomBtn.title = 'Випадкова сторінка'; |
| randomBtn.style.cssText = ` | | randomBtn.style.cssText = ` |
| position: fixed; | | position: fixed; |
| bottom: ${70 + keyboardOffset}px; /* Нижче за кнопку "Як це працює" */ | | bottom: ${60 + keyboardHeight}px; |
| left: 20px; | | left: 15px; |
| z-index: 9998; | | z-index: 9998; |
| background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%); | | background: #ff4444; |
| color: white; | | color: white; |
| border: none; | | border: none; |
| padding: 12px 18px; | | padding: 10px 15px; |
| border-radius: 25px; | | border-radius: 20px; |
| font-size: 16px; | | font-size: 14px; |
| font-weight: bold; | | font-weight: bold; |
| cursor: pointer; | | cursor: pointer; |
| box-shadow: 0 4px 15px rgba(0,0,0,0.3); | | box-shadow: 0 2px 10px rgba(0,0,0,0.3); |
| display: flex; | | display: flex; |
| align-items: center; | | align-items: center; |
| gap: 8px; | | gap: 5px; |
| transition: all 0.3s ease; | | transition: all 0.2s ease; |
| white-space: nowrap; | | white-space: nowrap; |
| `; | | `; |
| | | |
| // Обробник для кнопки "Як це працює?" | | // Обробники кліків |
| howItWorksBtn.addEventListener('click', function(e) { | | howBtn.addEventListener('click', function() { |
| e.preventDefault(); | | console.log('Клік на "Як це працює?"'); |
| e.stopPropagation();
| | // Змініть посилання на потрібне |
|
| |
| // Відкриваємо локальну сторінку з поясненнями | |
| // Замініть '/wiki/Довідка:Як_це_працює' на вашу реальну URL-адресу
| |
| window.location.href = '/wiki/Довідка:Як_це_працює'; | | window.location.href = '/wiki/Довідка:Як_це_працює'; |
| }); | | }); |
| | | |
| // Обробник для кнопки "Випадкова сторінка"
| | randomBtn.addEventListener('click', function() { |
| randomBtn.addEventListener('click', function(e) { | | console.log('Клік на "Випадкова сторінка"'); |
| e.preventDefault(); | | this.innerHTML = '⏳...'; |
| e.stopPropagation(); | | this.disabled = true; |
| | | |
| // Додаємо індикатор завантаження
| |
| randomBtn.innerHTML = '⏳ Завантаження...';
| |
| randomBtn.style.opacity = '0.7';
| |
| randomBtn.disabled = true;
| |
|
| |
| // Використовуємо window.location.replace для чистого переходу
| |
| setTimeout(() => { | | setTimeout(() => { |
| window.location.replace('/w/index.php/Спеціальна:Випадкова_сторінка'); | | window.location.href = '/wiki/Special:Random'; |
| }, 100); | | }, 100); |
| }); | | }); |
| | | |
| // Додаємо hover-ефекти для обох кнопок | | // Hover ефекти |
| [howItWorksBtn, randomBtn].forEach(btn => { | | [howBtn, randomBtn].forEach(btn => { |
| btn.addEventListener('mouseenter', function() { | | btn.addEventListener('mouseenter', function() { |
| if (!this.disabled) { | | this.style.transform = 'scale(1.05)'; |
| this.style.transform = 'scale(1.05)';
| | this.style.boxShadow = '0 4px 15px rgba(0,0,0,0.4)'; |
| this.style.boxShadow = '0 6px 20px rgba(0,0,0,0.4)';
| |
| }
| |
| }); | | }); |
| | | |
| btn.addEventListener('mouseleave', function() { | | btn.addEventListener('mouseleave', function() { |
| this.style.transform = 'scale(1)'; | | this.style.transform = 'scale(1)'; |
| this.style.boxShadow = '0 4px 15px rgba(0,0,0,0.3)'; | | this.style.boxShadow = '0 2px 10px rgba(0,0,0,0.3)'; |
| }); | | }); |
| }); | | }); |
| | | |
| // Додаємо кнопки до DOM | | // Додаємо кнопки на сторінку |
| document.body.appendChild(howItWorksBtn); | | document.body.appendChild(howBtn); |
| document.body.appendChild(randomBtn); | | document.body.appendChild(randomBtn); |
| | | |
| console.log('Ліві кнопки створені'); | | console.log('Ліві кнопки успішно створені'); |
| }
| |
| | |
| // =========================
| |
| // АДАПТАЦІЯ ДО ЕКРАННОЇ КЛАВІАТУРИ
| |
| // =========================
| |
| function adjustForKeyboard() {
| |
| const keyboardOffset = 80; // Базовий відступ
| |
|
| |
| // Функція для оновлення позицій кнопок
| |
| function updateButtonPositions() {
| |
| const howItWorksBtn = document.getElementById('how-it-works-btn');
| |
| const randomBtn = document.getElementById('float-random-btn');
| |
|
| |
| if (howItWorksBtn && randomBtn) {
| |
| // Можна додати логіку для динамічного визначення висоти клавіатури
| |
| // Наприклад, перевірка висоти вікна або інших елементів
| |
| const currentKeyboardOffset = window.innerHeight < 500 ? 120 : keyboardOffset;
| |
|
| |
| howItWorksBtn.style.bottom = `${140 + currentKeyboardOffset}px`;
| |
| randomBtn.style.bottom = `${70 + currentKeyboardOffset}px`;
| |
| }
| |
| }
| |
|
| |
| // Оновлюємо позиції при зміні розміру вікна
| |
| window.addEventListener('resize', updateButtonPositions);
| |
|
| |
| // Оновлюємо позиції при завантаженні
| |
| setTimeout(updateButtonPositions, 100);
| |
| } | | } |
|
| |
|
| // ========================= | | // ========================= |
| // ОНОВЛЕНА ФУНКЦІЯ ПРИХОВАННЯ ЕЛЕМЕНТІВ | | // ПРОСТЕ ПРИХОВАННЯ ЕЛЕМЕНТІВ |
| // ========================= | | // ========================= |
| function hideMobileElements() { | | function hideElements() { |
| if (!document.body.classList.contains('skin-minerva')) return; | | if (!document.body.classList.contains('skin-minerva')) return; |
| | | |
| setTimeout(() => { | | setTimeout(() => { |
| const elements = document.querySelectorAll('*'); | | // Приховуємо елементи з текстом "Відмова" |
| elements.forEach(element => {
| | document.querySelectorAll('*').forEach(el => { |
| if (element.textContent && element.textContent.includes('Відмова')) { | | if (el.textContent && el.textContent.includes('Відмова')) { |
| element.style.display = 'none'; | | el.style.display = 'none'; |
| const parentLi = element.closest('li');
| |
| if (parentLi) parentLi.style.display = 'none';
| |
| } | | } |
| }); | | }); |
|
| | }, 500); |
| const links = document.querySelectorAll('a[href*="%D0%92%D1%96%D0%B4%D0%BC%D0%BE%D0%B2%D0%B0"]');
| |
| links.forEach(link => {
| |
| link.style.display = 'none';
| |
| const parentLi = link.closest('li');
| |
| if (parentLi) parentLi.style.display = 'none';
| |
| });
| |
| }, 1000); | |
| } | | } |
|
| |
|
| // ========================= | | // ========================= |
| // ОНОВЛЕНИЙ ЗАГАЛЬНИЙ ІНІЦІАЛІЗАТОР | | // ІНІЦІАЛІЗАЦІЯ |
| // ========================= | | // ========================= |
| document.addEventListener('DOMContentLoaded', function() { | | document.addEventListener('DOMContentLoaded', function() { |
| // Для мобільної версії | | console.log('DOM завантажено, перевіряємо тему...'); |
| | |
| if (document.body.classList.contains('skin-minerva')) { | | if (document.body.classList.contains('skin-minerva')) { |
| hideMobileElements(); | | console.log('Це Minerva тема, ініціалізуємо кнопки...'); |
| createLeftSideButtons();
| | createLeftButtons(); |
| adjustForKeyboard();
| | hideElements(); |
|
| |
| setTimeout(() => {
| |
| if (!document.getElementById('float-random-btn') || !document.getElementById('how-it-works-btn')) {
| |
| createLeftSideButtons();
| |
| adjustForKeyboard();
| |
| }
| |
| hideMobileElements();
| |
| }, 2000);
| |
| } | | } |
| }); | | }); |
|
| |
|
| | // Дублюємо ініціалізацію на випадок динамічного завантаження |
| window.addEventListener('load', function() { | | window.addEventListener('load', function() { |
| | console.log('Вікно завантажено, перевіряємо тему...'); |
| | |
| if (document.body.classList.contains('skin-minerva')) { | | if (document.body.classList.contains('skin-minerva')) { |
| setTimeout(() => { | | console.log('Це Minerva тема, ініціалізуємо кнопки...'); |
| createLeftSideButtons();
| | setTimeout(createLeftButtons, 1000); |
| adjustForKeyboard();
| |
| }, 500);
| |
| } | | } |
| }); | | }); |
|
| |
|
| | // Резервна ініціалізація |
| setTimeout(function() { | | setTimeout(function() { |
| if (document.body.classList.contains('skin-minerva') && | | if (document.body.classList.contains('skin-minerva') && |
| (!document.getElementById('float-random-btn') || !document.getElementById('how-it-works-btn'))) { | | !document.getElementById('left-random-btn')) { |
| createLeftSideButtons(); | | console.log('Резервна ініціалізація кнопок...'); |
| adjustForKeyboard(); | | createLeftButtons(); |
| } | | } |
| }, 3000); | | }, 3000); |
|
| |
|
| // ========================= | | // Відновлюємо кнопки після переходу |
| // АВТОМАТИЧНЕ ВІДНОВЛЕННЯ КНОПОК ПІСЛЯ ПЕРЕХОДУ
| | window.addEventListener('pageshow', function() { |
| // =========================
| | if (document.body.classList.contains('skin-minerva') && |
| function restoreButtons() {
| | !document.getElementById('left-random-btn')) { |
| // Перевіряємо чи ми на випадковій сторінці або сторінці довідки
| | console.log('Відновлюємо кнопки після переходу...'); |
| const isRandomPage = window.location.href.includes('Випадкова_сторінка') ||
| | setTimeout(createLeftButtons, 500); |
| window.location.href.includes('Special:Random');
| |
| const isHowItWorksPage = window.location.href.includes('Як_це_працює');
| |
|
| |
| if ((isRandomPage || isHowItWorksPage) && document.body.classList.contains('skin-minerva')) { | |
| // Чекаємо повного завантаження сторінки | |
| setTimeout(() => {
| |
| if (!document.getElementById('float-random-btn') || !document.getElementById('how-it-works-btn')) {
| |
| createLeftSideButtons();
| |
| adjustForKeyboard();
| |
| }
| |
| }, 500);
| |
| }
| |
| }
| |
| | |
| // Додаємо обробник для відновлення кнопок
| |
| window.addEventListener('pageshow', restoreButtons);
| |
| }
| |
| | |
| // =========================
| |
| // ПРИХОВАННЯ ЕЛЕМЕНТІВ У МОБІЛЬНІЙ ВЕРСІЇ
| |
| // =========================
| |
| function hideMobileElements() {
| |
| if (!document.body.classList.contains('skin-minerva')) return;
| |
|
| |
| setTimeout(() => {
| |
| const elements = document.querySelectorAll('*');
| |
| elements.forEach(element => {
| |
| if (element.textContent && element.textContent.includes('Відмова')) {
| |
| element.style.display = 'none';
| |
| const parentLi = element.closest('li');
| |
| if (parentLi) parentLi.style.display = 'none';
| |
| }
| |
| });
| |
| | |
| const links = document.querySelectorAll('a[href*="%D0%92%D1%96%D0%B4%D0%BC%D0%BE%D0%B2%D0%B0"]');
| |
| links.forEach(link => {
| |
| link.style.display = 'none';
| |
| const parentLi = link.closest('li');
| |
| if (parentLi) parentLi.style.display = 'none';
| |
| });
| |
| }, 1000);
| |
| }
| |
| | |
| // =========================
| |
| // ЗАГАЛЬНИЙ ІНІЦІАЛІЗАТОР
| |
| // =========================
| |
| document.addEventListener('DOMContentLoaded', function() {
| |
| // Для мобільної версії
| |
| if (document.body.classList.contains('skin-minerva')) {
| |
| hideMobileElements();
| |
| createRandomButton();
| |
|
| |
| setTimeout(() => { | |
| if (!document.getElementById('float-random-btn')) {
| |
| createRandomButton();
| |
| }
| |
| hideMobileElements();
| |
| }, 2000);
| |
| } | | } |
| }); | | }); |
|
| |
| window.addEventListener('load', function() {
| |
| if (document.body.classList.contains('skin-minerva')) {
| |
| setTimeout(createRandomButton, 500);
| |
| }
| |
| });
| |
|
| |
| setTimeout(function() {
| |
| if (document.body.classList.contains('skin-minerva') && !document.getElementById('float-random-btn')) {
| |
| createRandomButton();
| |
| }
| |
| }, 3000);
| |