|
|
| Рядок 104: |
Рядок 104: |
|
| |
|
|
| |
|
| // В MediaWiki:Common.js - блокируем переход по ссылкам | | // Простой и надежный перехватчик без ошибок |
| document.addEventListener('click', function(e) { | | document.addEventListener('click', function(e) { |
| var target = e.target; | | var target = e.target; |
| var linkElement = target.closest('a'); | | var link = target.closest('a'); |
| | | |
| // Если кликнули на изображение или ссылку с изображением | | if (!link) return; |
| if (target.tagName === 'IMG' || (linkElement && linkElement.querySelector('img'))) { | | |
| | var href = link.href; |
| | if (!href) return; |
| | |
| | // Проверяем, является ли ссылка изображением |
| | var isImageLink = href.match(/\.(jpg|jpeg|png|gif|bmp|webp)$/i) || |
| | href.includes('/wiki/File:') || |
| | href.includes('/images/'); |
| | |
| | if (isImageLink) { |
| | e.preventDefault(); |
| | e.stopImmediatePropagation(); |
| | | |
| // Определяем href ссылки | | // Простая попытка открыть в MediaViewer |
| var href = linkElement ? linkElement.href : '';
| | if (window.mw && window.mw.mmv && window.mw.mmv.viewer) { |
|
| | setTimeout(function() { |
| // Проверяем, ведет ли ссылка на файл изображения
| | try { |
| if (href && (href.match(/\.(jpg|jpeg|png|gif|bmp|webp)$/i) || href.includes('/wiki/File:'))) { | | // Пробуем получить название файла разными способами |
| e.preventDefault(); | | var fileTitle = link.title || |
| e.stopPropagation();
| | link.getAttribute('data-title') || |
|
| | extractSimpleFilename(href); |
| // Получаем название файла для MediaViewer
| | |
| var fileTitle = getFileTitleFromElement(target, linkElement, href);
| | if (fileTitle && !fileTitle.startsWith('File:')) { |
|
| | fileTitle = 'File:' + fileTitle; |
| console.log('Перехвачен клик на изображении:', href, 'FileTitle:', fileTitle);
| | } |
|
| | |
| // Открываем в MediaViewer вместо перехода
| | if (fileTitle) { |
| if (fileTitle && window.mw && window.mw.mmv && window.mw.mmv.viewer) {
| |
| // Небольшая задержка для гарантии загрузки MediaViewer
| |
| setTimeout(function() {
| |
| try {
| |
| window.mw.mmv.viewer.openImage(fileTitle); | | window.mw.mmv.viewer.openImage(fileTitle); |
| console.log('Изображение открыто в MediaViewer:', fileTitle);
| |
| } catch (error) {
| |
| console.error('Ошибка открытия в MediaViewer:', error);
| |
| // Резервный вариант - показать alert
| |
| alert('Изображение: ' + fileTitle + '\nЗакройте это окно для возврата.');
| |
| } | | } |
| }, 100); | | } catch (e) { |
| } else if (fileTitle) {
| | // Игнорируем ошибки |
| // Если MediaViewer не доступен, показываем сообщение
| | } |
| alert('Изображение: ' + fileTitle + '\nПросмотрщик недоступен.'); | | }, 50); |
| } | |
| }
| |
| }
| |
| }, true); // Используем capture phase для перехвата
| |
| | |
| // Функция для извлечения названия файла
| |
| function getFileTitleFromElement(imgElement, linkElement, href) {
| |
| // Пробуем разные способы получить название файла
| |
|
| |
| // 1. Из data-атрибутов
| |
| if (imgElement && imgElement.getAttribute('data-file-title')) {
| |
| return imgElement.getAttribute('data-file-title');
| |
| }
| |
|
| |
| // 2. Из атрибута alt
| |
| if (imgElement && imgElement.alt && imgElement.alt.includes('.')) {
| |
| return 'File:' + imgElement.alt;
| |
| }
| |
|
| |
| // 3. Из title ссылки
| |
| if (linkElement && linkElement.title) {
| |
| return linkElement.title;
| |
| }
| |
|
| |
| // 4. Из href (URL)
| |
| if (href) {
| |
| return extractFileTitleFromUrl(href);
| |
| }
| |
|
| |
| // 5. Из имени файла в src изображения
| |
| if (imgElement && imgElement.src) {
| |
| var filename = imgElement.src.split('/').pop();
| |
| if (filename && filename.match(/\.(jpg|jpeg|png|gif|bmp|webp)/i)) {
| |
| return 'File:' + decodeURIComponent(filename);
| |
| } | | } |
| } | | } |
|
| | }, true); |
| return 'File:Unknown.jpg'; // Запасной вариант
| |
| }
| |
|
| |
|
| // Функция извлечения названия файла из URL
| | function extractSimpleFilename(url) { |
| function extractFileTitleFromUrl(url) { | |
| try { | | try { |
| // Для URL вида /wiki/File:Filename.jpg | | var filename = url.split('/').pop().split('?')[0]; |
| if (url.includes('/wiki/File:')) {
| | if (filename.match(/\.(jpg|jpeg|png|gif|bmp|webp)/i)) { |
| var match = url.match(/\/wiki\/File:([^?]+)/i);
| | return decodeURIComponent(filename); |
| if (match && match[1]) {
| |
| return 'File:' + decodeURIComponent(match[1]);
| |
| }
| |
| }
| |
|
| |
| // Для прямых ссылок на изображения
| |
| if (url.match(/\.(jpg|jpeg|png|gif|bmp|webp)/i)) { | |
| var filename = url.split('/').pop(); | |
| if (filename) {
| |
| // Удаляем параметры URL если есть
| |
| filename = filename.split('?')[0];
| |
| filename = filename.split('#')[0];
| |
| return 'File:' + decodeURIComponent(filename);
| |
| }
| |
| } | | } |
|
| | } catch (e) {} |
| // Для URL с thumb/ и другими параметрами
| |
| if (url.includes('/thumb/')) {
| |
| var parts = url.split('/thumb/');
| |
| if (parts.length > 1) {
| |
| var filePart = parts[1].split('/')[0];
| |
| if (filePart) {
| |
| return 'File:' + decodeURIComponent(filePart);
| |
| }
| |
| }
| |
| }
| |
| } catch (error) { | |
| console.error('Ошибка извлечения названия файла:', error);
| |
| }
| |
|
| |
| return null; | | return null; |
| } | | } |
|
| |
|
| // Улучшенная блокировка правого клика | | // Минимальные блокировки |
| document.addEventListener('contextmenu', function(e) { | | document.addEventListener('contextmenu', function(e) { |
| if (e.target.tagName === 'IMG' || e.target.closest('a img')) { | | if (e.target.closest('a img')) e.preventDefault(); |
| e.preventDefault();
| |
| // Можно показать кастомное меню вместо стандартного
| |
| showCustomImageMenu(e);
| |
| return false;
| |
| }
| |
| }); | | }); |
|
| |
|
| // Блокировка drag-and-drop изображений
| |
| document.addEventListener('dragstart', function(e) { | | document.addEventListener('dragstart', function(e) { |
| if (e.target.tagName === 'IMG') { | | if (e.target.tagName === 'IMG') e.preventDefault(); |
| e.preventDefault();
| |
| return false;
| |
| }
| |
| });
| |
| | |
| // Дополнительно: блокировка среднего клика (открытие в новой вкладке)
| |
| document.addEventListener('auxclick', function(e) {
| |
| if (e.button === 1 && (e.target.tagName === 'IMG' || e.target.closest('a img'))) {
| |
| e.preventDefault();
| |
| return false;
| |
| }
| |
| }); | | }); |
|
| |
| // Дополнительно: блокировка клавиш для открытия в новой вкладке
| |
| document.addEventListener('keydown', function(e) {
| |
| // Ctrl+Click или Cmd+Click
| |
| if ((e.ctrlKey || e.metaKey) && e.target.tagName === 'IMG') {
| |
| e.preventDefault();
| |
| return false;
| |
| }
| |
| });
| |
|
| |
| // Кастомное меню для изображений (опционально)
| |
| function showCustomImageMenu(e) {
| |
| // Создаем кастомное контекстное меню
| |
| var menu = document.createElement('div');
| |
| menu.innerHTML = '📷 Открыть в просмотрщике';
| |
| menu.style.cssText = `
| |
| position: fixed;
| |
| left: ${e.clientX}px;
| |
| top: ${e.clientY}px;
| |
| background: white;
| |
| border: 1px solid #ccc;
| |
| padding: 10px;
| |
| border-radius: 5px;
| |
| box-shadow: 0 2px 10px rgba(0,0,0,0.2);
| |
| z-index: 10000;
| |
| cursor: pointer;
| |
| `;
| |
|
| |
| menu.onclick = function() {
| |
| var img = e.target;
| |
| var fileTitle = getFileTitleFromElement(img, img.closest('a'), '');
| |
| if (fileTitle && window.mw && window.mw.mmv && window.mw.mmv.viewer) {
| |
| window.mw.mmv.viewer.openImage(fileTitle);
| |
| }
| |
| document.body.removeChild(menu);
| |
| };
| |
|
| |
| document.body.appendChild(menu);
| |
|
| |
| // Удаляем меню при клике в другом месте
| |
| setTimeout(function() {
| |
| document.addEventListener('click', function removeMenu() {
| |
| if (document.body.contains(menu)) {
| |
| document.body.removeChild(menu);
| |
| }
| |
| document.removeEventListener('click', removeMenu);
| |
| }, { once: true });
| |
| }, 100);
| |
| }
| |
|
| |
| // Инициализация после загрузки MediaViewer
| |
| mw.hook('mmv.loaded').add(function(viewer) {
| |
| console.log('MediaViewer загружен, перехватчик активирован');
| |
|
| |
| // Добавляем глобальный обработчик для всех динамически загружаемых изображений
| |
| function observeImages() {
| |
| var observer = new MutationObserver(function(mutations) {
| |
| mutations.forEach(function(mutation) {
| |
| mutation.addedNodes.forEach(function(node) {
| |
| if (node.nodeType === 1) { // Element node
| |
| var images = node.querySelectorAll ? node.querySelectorAll('img') : [];
| |
| images.forEach(function(img) {
| |
| var link = img.closest('a');
| |
| if (link && (link.href.match(/\.(jpg|jpeg|png|gif|bmp|webp)$/i) || link.href.includes('/wiki/File:'))) {
| |
| img.style.cursor = 'pointer';
| |
| }
| |
| });
| |
| }
| |
| });
| |
| });
| |
| });
| |
|
| |
| observer.observe(document.body, {
| |
| childList: true,
| |
| subtree: true
| |
| });
| |
| }
| |
|
| |
| // Запускаем наблюдение за новыми изображениями
| |
| observeImages();
| |
| });
| |
|
| |
| // Резервный метод для случаев, когда MediaViewer недоступен
| |
| function fallbackImageHandler(fileTitle, href) {
| |
| // Создаем простой lightbox
| |
| var overlay = document.createElement('div');
| |
| overlay.style.cssText = `
| |
| position: fixed;
| |
| top: 0;
| |
| left: 0;
| |
| width: 100%;
| |
| height: 100%;
| |
| background: rgba(0,0,0,0.9);
| |
| z-index: 10000;
| |
| display: flex;
| |
| align-items: center;
| |
| justify-content: center;
| |
| `;
| |
|
| |
| var img = document.createElement('img');
| |
| img.src = href;
| |
| img.style.maxWidth = '90%';
| |
| img.style.maxHeight = '90%';
| |
|
| |
| overlay.appendChild(img);
| |
| document.body.appendChild(overlay);
| |
|
| |
| // Закрытие по клику
| |
| overlay.onclick = function() {
| |
| document.body.removeChild(overlay);
| |
| };
| |
| }
| |
|
| |
| console.log('Перехватчик изображений для MediaViewer активирован');
| |