MediaWiki:Gadget-Thickbox.js: Difference between revisions

no edit summary
 
No edit summary
Line 1: Line 1:
/* <pre>
/*
  * Thickbox4MediaWiki v3.13 - Based on Thickbox 3.1 By Cody Lindley (http://www.codylindley.com)
  * Thickbox4MediaWiki v3.12 - Based on Thickbox 3.1 By Cody Lindley (http://www.codylindley.com)
  * Copyright (c) 2010 - 2023 Jesús Martínez (User:Ciencia_Al_Poder), Original Thickbox Copyright (c) 2007 Cody Lindley
  * Copyright (c) 2010 - 2022 Jesús Martínez (User:Ciencia_Al_Poder), Original Thickbox Copyright (c) 2007 Cody Lindley
  * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
  * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
*/
*/
window.Thickbox = (function($, mw) {
window.Thickbox = (function($, mw) {
'use strict';
'use strict';
var _version = '3.13',
var _version = '3.12',
// Dimensiones mínimas
// Minimum dimensions
_minWidth = 210,
_minWidth = 210,
// Margen entre la imagen y el borde de ThickBox
// Margin between the image and the border of ThickBox
_imageMarginWidth = 15,
_imageMarginWidth = 15,
// Margen mínimo hasta el borde de la ventana. Si se supera la imagen se reducirá
// Minimum margin to the edge of the window. If the image is exceeded it will be reduced
_minMarginWidth = 30,
_minMarginWidth = 30,
_minMarginHeight = 15,
_minMarginHeight = 15,
// Tiempo de espera para la aparición del loader en ms
// Waiting time for the loader to appear in ms
_loaderWait = 500,
_loaderWait = 500,
// Internos
// Internal
_imgPreloader = null,
_imgPreloader = null,
_galleryData = null,
_galleryData = null,
Line 29: Line 29:
_loaderTm = null,
_loaderTm = null,
_logger = null,
_logger = null,
// Funciones privadas
// Private functions
_init = function() {
_init = function() {
// Se podría haber puesto un evento directamente en cada 'a.image', pero esto es mucho más rápido y eficiente (tarda solo el 20% en FF2) que recorrerse todo el DOM
// COMPAT
if (window.Thickbox4MediaWikiLoaded) { return; }
window.Thickbox4MediaWikiLoaded = true;
// You could have put an event directly in each 'a.image', but this is much faster and more efficient (it only takes 20% in FF2) than to go through the entire DOM
$('#mw-content-text').off('click.thickbox mouseover.thickbox_imgtip').on({
$('#mw-content-text').off('click.thickbox mouseover.thickbox_imgtip').on({
'click.thickbox': _triggerEvent,
'click.thickbox': _triggerEvent,
Line 38: Line 41:
},
},
_triggerEvent = function(e) {
_triggerEvent = function(e) {
// Si hay alguna tecla especial pulsada, salimos
// If there is any special key pressed, we exit
if (e.ctrlKey || e.altKey || e.shiftKey) {
if (e.ctrlKey || e.altKey || e.shiftKey) {
return true;
return true;
Line 45: Line 48:
if (_isTag(target,'img')) { // Gallery o thumb
if (_isTag(target,'img')) { // Gallery o thumb
var a = target.parentNode;
var a = target.parentNode;
// Imágenes con enlaces a otros artículos no tienen la clase "image", excepto en Wikia donde sí la tiene y añaden "link-internal" o "link-external"
// Images with links to other articles do not have the "image" class, except in Wikia where it does and add "link-internal" or "link-external"
if (!a || !_isTag(a,'a') || !(_isClass(a,'image') || _isClass(a,'mw-file-description')) || _isClass(a, 'link-internal') || _isClass(a, 'link-external')) {
if (!a || !_isTag(a,'a') || !_isClass(a,'image') || _isClass(a, 'link-internal') || _isClass(a, 'link-external')) {
return true;
return true;
}
}
// MW < 1.40
// Wikia 2 Gallery
if (_isClass(target,'thumbimage')) {
if (_isClass(a,'lightbox')) {
// Es thumb
target.blur();
a.blur();
_getCaption = _getCaptionWikia;
_getCaption = _getCaptionThumb;
_galleryData = $(target).closest('div.wikia-gallery').find('> div.wikia-gallery-item > div.thumb > div.gallery-image-wrapper > a.lightbox');
if (_galleryData.length === 0) {
_galleryData = $(target).closest('div.wikia-gallery').find('> div.wikia-gallery-row > div.wikia-gallery-item > div.thumb > div.gallery-image-wrapper > a.lightbox');
}
if (_galleryData.length === 0) {
return true;
}
_galleryIndex = _galleryData.index(a);
_showImage(a);
_showImage(a);
return false;
return false;
}
}
// MW >= 1.40
if (_isClass(target,'thumbimage')) {
if (_isTag(a.parentNode,'figure')) {
// Its thumbnail
// Es thumb
a.blur();
a.blur();
_getCaption = _getCaptionThumb140;
_getCaption = _getCaptionThumb;
_showImage(a);
_showImage(a);
return false;
return false;
}
}
var gb = $(a).closest('li.gallerybox').get(0);
var gb = a.parentNode.parentNode.parentNode.parentNode;
// MediaWiki gallery
// MediaWiki gallery
if (gb) {
if (_isTag(gb,'li') && _isClass(gb,'gallerybox')) {
var t = gb.parentNode;
var t = gb.parentNode;
if (_isTag(t,'ul') && _isClass(t,'gallery')) {
if (_isTag(t,'ul') && _isClass(t,'gallery')) {
a.blur();
a.blur();
_getCaption = _getCaptionMW;
_getCaption = _getCaptionMW;
_galleryData = $(t).find('div.thumb a.image,div.thumb a.mw-file-description'); // MW<1.40,MW>=1.40
_galleryData = $(t).find('div.thumb a.image');
_galleryIndex = _galleryData.index(a);
_galleryIndex = _galleryData.index(a);
_showImage(a);
_showImage(a);
Line 78: Line 87:
}
}
}
}
// Es thumb genérico
// Its generic thumbnail
a.blur();
a.blur();
_getCaption = _getCaptionEmpty;
_getCaption = _getCaptionEmpty;
_showImage(a);
_showImage(a);
return false;
return false;
} else if (_isTag(target,'a')) {
/*} else if (_isTag(target,'a')) {
var sup = target.parentNode;
var sup = target.parentNode;
if (!_isTag(sup,'sup') || !_isClass(sup,'reference')) {
if (!_isTag(sup,'sup') || !_isClass(sup,'reference')) {
Line 90: Line 99:
target.blur();
target.blur();
_showElement(target);
_showElement(target);
return false;
return false;*/
}
}
return true;
return true;
Line 146: Line 155:
descUrl = $a.attr('href');
descUrl = $a.attr('href');
if ($img.data('image-key')) {
if ($img.data('image-key')) {
// image-key es el nombre para la URL. No usar image-name porque está codificado doble (& --> &amp;amp;)
// image-key is the name for the URL. Do not use image-name because it is encoded
descUrl = mw.util.wikiGetlink(mw.config.get('wgFormattedNamespaces')['6'] + ':' + decodeURIComponent($img.data('image-key')));
descUrl = mw.util.wikiGetlink(mw.config.get('wgFormattedNamespaces')['6'] + ':' + decodeURIComponent($img.data('image-key')));
}
}
TB_descLink = '<a id="TB_descLink" class="sprite details" title="Ir a la página de descripción de la imagen"></a>';
TB_descLink = '<a id="TB_descLink" class="sprite details" title="Go to the image\'s description page">File Page</a>';
// Se trata de un gallery?
// Is it a gallery?
if (_galleryIndex != -1) {
if (_galleryIndex != -1) {
TB_secondLine = '<div id="TB_secondLine">'+
TB_secondLine = '<div id="TB_secondLine">'+
'<span id="TB_imageCount"></span>'+
'<span id="TB_imageCount"></span>'+
'<span id="TB_prev"><a href="#" title="Ver imagen anterior [A]">&lt; Ant.</a></span>'+
'<span id="TB_prev"><a href="#" title="See previous image [Left arrow]"></a></span>'+
'<span id="TB_next"><a href="#" title="Ver imagen siguiente [S]">Sig. &gt;</a></span></div>';
'<span id="TB_next"><a href="#" title="See next image [Right arrow]"></a></span></div>';
}
}
$('#TB_window').append('<div id="TB_closeWindow"><a href="#" id="TB_closeWindowButton" title="Cerrar [ESC]">cerrar</a></div>' +
$('#TB_window').append('<div id="TB_closeWindow"><a href="#" id="TB_closeWindowButton" title="Close [ESC]">close</a></div>' +
'<div id="TB_ImageOff"><img id="TB_Image" alt="Imagen" title="Cerrar" />' + TB_descLink + '</div>' + TB_secondLine + '<div id="TB_caption"></div>');
'<div id="TB_ImageOff"><img id="TB_Image" alt="Image" title="Close" />' + TB_descLink + '</div>' + TB_secondLine + '<div id="TB_caption"></div>');
if (_galleryIndex != -1) {
if (_galleryIndex != -1) {
_updateNavigation();
_updateNavigation();
Line 168: Line 177:
$('#TB_prev').add('#TB_next').click(_navigate);
$('#TB_prev').add('#TB_next').click(_navigate);
$('#TB_descLink').attr('href', descUrl);
$('#TB_descLink').attr('href', descUrl);
$('#TB_ImageOff').on({
mouseover: function() {
$('#TB_descLink').css('display','block');
},
mouseout: function() {
$('#TB_descLink').css('display','none');
}
});


if (_imgPreloader === null) {
if (_imgPreloader === null) {
Line 184: Line 185:
_imgPreloader.src = ''; // chromium bug 7731
_imgPreloader.src = ''; // chromium bug 7731
if (url.length > 3 && url.substr(url.length - 4).toLowerCase() == '.svg') {
if (url.length > 3 && url.substr(url.length - 4).toLowerCase() == '.svg') {
// Para SVG ya conocemos su relación de aspecto, aunque no sus dimensiones originales
// For SVG we already know its aspect ratio, although not its original dimensions
// Habría que hacerlo diferente para cargar el SVG. En su lugar, aquí se determina dinámicamente
// It would have to be done differently to load the SVG. Instead, here it is dynamically determined
// Se agranda artificialmente, y luego esta función lo reducirá al tamaño máximo de la ventana
// It is artificially enlarged, and then this function will reduce it to the maximum window size
_updateImageView($img.prop('width') * 1000, $img.prop('height') * 1000, url);
_updateImageView($img.prop('width') * 1000, $img.prop('height') * 1000, url);
} else {
} else {
_imgPreloader.src = url;
_imgPreloader.src = url;
}
}
} catch(e) {
} catch(e) {
_log(e);
_log(e);
Line 203: Line 205:
var baseurl = url.substr(0, idx),
var baseurl = url.substr(0, idx),
hash = decodeURIComponent(url.substr(idx + 1)),
hash = decodeURIComponent(url.substr(idx + 1)),
// Comprobamos que la URL sea del mismo documento
// We check that the URL is from the same document
locbase = document.location.href.replace(baseurl, ''),
locbase = document.location.href.replace(baseurl, ''),
rel = document.getElementById(hash);
rel = document.getElementById(hash);
Line 214: Line 216:
$('#TB_overlay').click(_remove);
$('#TB_overlay').click(_remove);


var titleHTML = '<div id="TB_title"><div id="TB_closeAjaxWindow"><a href="#" id="TB_closeWindowButton" title="Cerrar [ESC]">cerrar</a></div></div>',
var titleHTML = '<div id="TB_title"><div id="TB_closeAjaxWindow"><a href="#" id="TB_closeWindowButton" title="Close [ESC]">close</a></div></div>',
wnd = $('#TB_window'),
wnd = $('#TB_window'),
cel = $(rel).clone();
cel = $(rel).clone();
Line 222: Line 224:


var tgEl = $(target),
var tgEl = $(target),
// espacio horizontal a cada lado del elemento
// horizontal space on each side of the element
elOffset = tgEl.offset(),
elOffset = tgEl.offset(),
lw = elOffset.left,
lw = elOffset.left,
rw = $(document).width() - elOffset.left - tgEl.width(),
rw = $(document).width() - elOffset.left - tgEl.width(),
// Calculamos las dimensiones óptimas. Calculamos el área y determinamos que lo ideal es proporción 3/2
// We calculate the optimal dimensions. We calculate the area and determine that the ideal is ratio 3/2
prefw = parseInt(Math.sqrt(wnd.width()*wnd.height()*3/2),10),
prefw = parseInt(Math.sqrt(wnd.width()*wnd.height()*3/2),10),
// Corrección de ancho mínimo en caso de producirse scroll
// Minimum width correction if scroll occurs
cd = $('#TB_ajaxContent')[0];
cd = $('#TB_ajaxContent')[0];
prefw += cd.scrollWidth-cd.clientWidth;
prefw += cd.scrollWidth-cd.clientWidth;
// No se debe reducir el ancho mínimo
// The minimum width should not be reduced
if (prefw < _minWidth) {
if (prefw < _minWidth) {
prefw = _minWidth;
prefw = _minWidth;
}
}
// Posición. 5px de margen respecto el origen. Situación ideal: a la derecha del elemento
// Position. 5px of margin with respect to the origin. Ideal situation: to the right of the element
var margen = 5, left = $(document).width() - rw + margen;
var margen = 5, left = $(document).width() - rw + margen;
if (rw > prefw + margen) {
if (rw > prefw + margen) {
// ya es correcto
// is already correct
} else if (lw > prefw + margen) {
} else if (lw > prefw + margen) {
left = lw - prefw - margen;
left = lw - prefw - margen;
} else if (lw < 250 || rw < 250) { // No cabe en ninguno de los dos lados. Miramos si no puede usarse el ancho mínimo (250). En ese caso el ancho lo forzamos y lo ponemos a la derecha
} else if (lw < 250 || rw < 250) { // It does not fit on either side. We look to see if the minimum width (250) cannot be used. In that case the width we force it and put it to the right
prefw = 250;
prefw = 250;
} else if (rw > lw) { // Se usa el ancho disponible del lado mayor
} else if (rw > lw) { // The available width of the major side is used
prefw = rw - margen;
prefw = rw - margen;
} else {
} else {
Line 250: Line 252:
}
}
wnd.css({width: prefw, left: left});
wnd.css({width: prefw, left: left});
// Ahora la posición vertical. necesita que hayamos asignado el width para que lo calcule bien
// Now the vertical position. it needs that we have assigned the width to calculate it well
var top = elOffset.top - parseInt(wnd.height(), 10) - margen;
var top = elOffset.top - parseInt(wnd.height(), 10) - margen;
// Si no cabe arriba lo colocamos debajo
// If it does not fit above we place it below
if (top < margen) {
if (top < margen) {
top = elOffset.top + tgEl.height() + margen;
top = elOffset.top + tgEl.height() + margen;
}
}
wnd.css({top: top, visibility: 'visible'});
wnd.css({top: top, visibility: 'visible'});
// Animación si queda fuera del campo visual
// Animation if it is outside the visual field
if (($('html')[0].scrollTop||$('body')[0].scrollTop) > top-margen) {
if (($('html')[0].scrollTop||$('body')[0].scrollTop) > top-margen) {
$('html,body').animate({scrollTop: top - margen}, 250, 'swing');
$('html,body').animate({scrollTop: top - margen}, 250, 'swing');
Line 292: Line 294:
if (keycode == 27) { // close
if (keycode == 27) { // close
_remove();
_remove();
} else if (keycode == 65) { // 'A' display previous image
} else if (keycode == 37) { // 'Left arrow' display previous image
$('#TB_prev').click();
$('#TB_prev').click();
} else if (keycode == 83) { // 'S' display next image
} else if (keycode == 39) { // 'Right arrow' display next image
$('#TB_next').click();
$('#TB_next').click();
}
}
Line 324: Line 326:
//return thumb.replace(/\/revision\/latest\/scale-to-width(-down)?\/\d+/, '');
//return thumb.replace(/\/revision\/latest\/scale-to-width(-down)?\/\d+/, '');
// Si la imagen no es thumb, o bien es un SVG, usamos la imagen tal cual.
// If the image is not thumb, or it is an SVG, we use the image as is.
if (thumb.indexOf('/thumb/') == -1 || thumb.indexOf('.svg/') != -1 ) {
if (thumb.indexOf('/thumb/') == -1 || thumb.indexOf('.svg/') != -1 ) {
return thumb;
return thumb;
Line 334: Line 336:
_getCaptionThumb = function(elem) {
_getCaptionThumb = function(elem) {
return elem.closest('.thumbinner').find('> .thumbcaption').clone().find('> div.magnify').remove().end().html();
return elem.closest('.thumbinner').find('> .thumbcaption').clone().find('> div.magnify').remove().end().html();
},
_getCaptionThumb140 = function(elem) {
return elem.closest('figure').find('> figcaption').clone().html();
},
},
_getCaptionEmpty = function(elem) {
_getCaptionEmpty = function(elem) {
Line 359: Line 358:
// Resizing large images - orginal by Christian Montoya edited by me.
// Resizing large images - orginal by Christian Montoya edited by me.
pagesize = _getPageSize(),
pagesize = _getPageSize(),
// Dimensiones máximas
// Maximum dimensions
x = pagesize[0] - _minMarginWidth * 2 - _imageMarginWidth * 2,
x = pagesize[0] - _minMarginWidth * 2 - _imageMarginWidth * 2,
y = pagesize[1] - _minMarginHeight * 2 - wndH + img.height(),
y = pagesize[1] - _minMarginHeight * 2 - wndH + img.height(),
imageWidth = _imgPreloader.width,
imageHeight = _imgPreloader.height,
firstNav, imgOpt;
firstNav, imgOpt;
// Puede entrar por una o por las dos. De hecho, con esta comprobación basta, ya que si tiene que pasar por las dos da igual por qué lado se reduzca primero
// You can enter by one or both. In fact, this check is enough, because if you have to go through both it does not matter which side is reduced first
if (imageWidth > x) {
if (imageWidth > x) {
imageHeight = imageHeight * (x / imageWidth);
imageHeight = imageHeight * (x / imageWidth);
Line 375: Line 376:


firstNav = (img.attr('src') || '') === '';
firstNav = (img.attr('src') || '') === '';
// Dimensiones de la ventana Thickbox para posicionar
// Thickbox window dimensions to position
_width = imageWidth + _imageMarginWidth * 2; // 15px de espacio en cada lado
_width = imageWidth + _imageMarginWidth * 2; // 15px de espacio en cada lado
// La altura de la ventana la conocemos. Solo hay que reemplazar la imagen antigua y poner la nueva, esto es, sus dimensiones. El height se tiene que hacer diferente porque intervienen más elementos que en el ancho
// We know the height of the window. Just replace the old image and put the new one, that is, its dimensions. The height has to be done differently because more elements are involved than in the width
_height = wndH - img.height() + imageHeight;
_height = wndH - img.height() + imageHeight;
img.attr({
img.attr({
Line 385: Line 386:


imgOpt = {width: imageWidth, height: imageHeight, opacity: 1};
imgOpt = {width: imageWidth, height: imageHeight, opacity: 1};
// Miramos si se carga al abrir o después de navegar. Si viene de abrirse, sin animación
// We look to see if it loads when opening or after browsing. If it comes from opening, without animation
if (firstNav) {
if (firstNav) {
img.css(imgOpt);
img.css(imgOpt);
Line 399: Line 400:
$('#TB_prev').css('display', (seq === 0 ? 'none' : ''));
$('#TB_prev').css('display', (seq === 0 ? 'none' : ''));
$('#TB_next').css('display', (seq >= len-1 ? 'none' : ''));
$('#TB_next').css('display', (seq >= len-1 ? 'none' : ''));
$('#TB_imageCount').text('Imagen ' + (seq+1) + ' de ' + len);
$('#TB_imageCount').text('Image ' + (seq+1) + ' of ' + len);
},
},
_navigate = function() {
_navigate = function() {
Line 416: Line 417:
if (url.length > 3 && url.substr(url.length - 4).toLowerCase() == '.svg') {
if (url.length > 3 && url.substr(url.length - 4).toLowerCase() == '.svg') {
$img = gitem.find('> img').eq(0);
$img = gitem.find('> img').eq(0);
// Para SVG ya conocemos su relación de aspecto, aunque no sus dimensiones originales
        // For SVG we already know its aspect ratio, although not its original dimensions
// Habría que hacerlo diferente para cargar el SVG. En su lugar, aquí se determina dinámicamente
        // It would have to be done differently to load the SVG. Instead, here it is dynamically determined
// Se agranda artificialmente, y luego esta función lo reducirá al tamaño máximo de la ventana
        // It is artificially enlarged, and then this function will reduce it to the maximum window size
_updateImageView($img.prop('width') * 1000, $img.prop('height') * 1000, url);
_updateImageView($img.prop('width') * 1000, $img.prop('height') * 1000, url);
_imgPreloader.src = '';
_imgPreloader.src = '';
Line 426: Line 427:
}});
}});
}
}
// Si la función no encuentra el elemento, puede devolver undefined, y en este caso no cambia el contenido. Forzamos un null en ese caso
// If the function does not find the item, it can return undefined, and in this case the content does not change. We force a null in that case
$('#TB_caption').html( ( _getCaption(gitem) || null ) );
$('#TB_caption').html( ( _getCaption(gitem) || null ) );
$('#TB_descLink').attr('href',gitem.attr('href'));
$('#TB_descLink').attr('href',gitem.attr('href'));
Line 475: Line 476:
if (_isTag(target,'img')) { // Gallery o thumb
if (_isTag(target,'img')) { // Gallery o thumb
a = target.parentNode;
a = target.parentNode;
if (!_isTag(a,'a') || !(_isClass(a,'image') || _isClass(a,'mw-file-description')) || _isClass(a,'link-internal')) {
if (!_isTag(a,'a') || !_isClass(a,'image') || _isClass(a,'link-internal')) {
_hideImgTip();
_hideImgTip();
return;
return;
}
}
t = $(target);
t = $(target);
// Mostramos solo si la imagen tiene un tamaño mínimo
// We show only if the image has a minimum size
if (t.width() < 40 || t.height() < 40) {
if (t.width() < 40 || t.height() < 40) {
return;
return;
Line 496: Line 497:
},
},
_createImgTip = function() {
_createImgTip = function() {
_imgTip = $('<div id="TB_imagetip" title="Clic sobre la imagen para ampliar. Ctrl, Alt o Mayús. para acceder a la página de descripción de la imagen.">').appendTo(document.body);
_imgTip = $('<div id="TB_imagetip" title="Click on the image to enlarge. Click with Ctrl or Shift to go to the file page.">').appendTo(document.body);
_imgTip.on('click',_imgTipClickEvent);
_imgTip.on('click',_imgTipClickEvent);
},
},
Line 507: Line 508:
display: 'block',
display: 'block',
left: of.left + target.width(),
left: of.left + target.width(),
top: of.top + target.height()
top: of.top
});
});
_imgTipVisible = true;
_imgTipVisible = true;
Line 534: Line 535:
$(window.Thickbox.init);
$(window.Thickbox.init);
}
}
/* </pre> */