MediaWiki:Gadget-Thickbox.js: Difference between revisions
(Created page with "→<pre> * Thickbox4MediaWiki v3.13 - 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 * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php: window.Thickbox = (function($, mw) { 'use strict'; var _version = '3.13', // Dimensiones mínimas _minWidth = 210, // Margen entre la imagen y el borde de...") |
No edit summary |
||
(2 intermediate revisions by the same user not shown) | |||
Line 7: | Line 7: | ||
'use strict'; | 'use strict'; | ||
var _version = '3.13', | var _version = '3.13', | ||
// | // Minimum dimensions | ||
_minWidth = 210, | _minWidth = 210, | ||
// | // Margin between the image and the border of ThickBox | ||
_imageMarginWidth = 15, | _imageMarginWidth = 15, | ||
// | // 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, | ||
// | // Waiting time for the loader to appear in ms | ||
_loaderWait = 500, | _loaderWait = 500, | ||
// | // Internal | ||
_imgPreloader = null, | _imgPreloader = null, | ||
_galleryData = null, | _galleryData = null, | ||
Line 29: | Line 29: | ||
_loaderTm = null, | _loaderTm = null, | ||
_logger = null, | _logger = null, | ||
// | // Private methods | ||
_init = function() { | _init = function() { | ||
// | // We could have this event listener directly on 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 38: | ||
}, | }, | ||
_triggerEvent = function(e) { | _triggerEvent = function(e) { | ||
// | // 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 45: | ||
if (_isTag(target,'img')) { // Gallery o thumb | if (_isTag(target,'img')) { // Gallery o thumb | ||
var a = target.parentNode; | var a = target.parentNode; | ||
// | // 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,'mw-file-description')) || _isClass(a, 'link-internal') || _isClass(a, 'link-external')) { | ||
return true; | return true; | ||
Line 78: | Line 78: | ||
} | } | ||
} | } | ||
// | // Is generic thumbnail | ||
a.blur(); | a.blur(); | ||
_getCaption = _getCaptionEmpty; | _getCaption = _getCaptionEmpty; | ||
Line 146: | Line 146: | ||
descUrl = $a.attr('href'); | descUrl = $a.attr('href'); | ||
if ($img.data('image-key')) { | if ($img.data('image-key')) { | ||
// image-key | // image-key is the name for the URL. So not use image-name because it's encoded (& --> &amp;) | ||
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="Ir a la página de descripción de la imagen"></a>'; | ||
// | // 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=" | '<span id="TB_prev"><a href="#" title="See previous [A]">< Prev.</a></span>'+ | ||
'<span id="TB_next"><a href="#" title=" | '<span id="TB_next"><a href="#" title="See next [S]">Next. ></a></span></div>'; | ||
} | } | ||
$('#TB_window').append('<div id="TB_closeWindow"><a href="#" id="TB_closeWindowButton" title=" | $('#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=" | '<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 184: | Line 184: | ||
_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') { | ||
// | // For SVG we already know its aspect ratio, although not its original dimensions | ||
// | // It would have to be done differently to load the SVG. Instead, here it is dynamically determined | ||
// | // 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 { | ||
Line 203: | Line 203: | ||
var baseurl = url.substr(0, idx), | var baseurl = url.substr(0, idx), | ||
hash = decodeURIComponent(url.substr(idx + 1)), | hash = decodeURIComponent(url.substr(idx + 1)), | ||
// | // 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 214: | ||
$('#TB_overlay').click(_remove); | $('#TB_overlay').click(_remove); | ||
var titleHTML = '<div id="TB_title"><div id="TB_closeAjaxWindow"><a href="#" id="TB_closeWindowButton" title=" | 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 222: | ||
var tgEl = $(target), | var tgEl = $(target), | ||
// | // 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(), | ||
// | // Calculating the optimal dimensions. Calculating 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), | ||
// | // Minimum width correction if scroll occurs | ||
cd = $('#TB_ajaxContent')[0]; | cd = $('#TB_ajaxContent')[0]; | ||
prefw += cd.scrollWidth-cd.clientWidth; | prefw += cd.scrollWidth-cd.clientWidth; | ||
// | // Should not go below minimum | ||
if (prefw < _minWidth) { | if (prefw < _minWidth) { | ||
prefw = _minWidth; | prefw = _minWidth; | ||
} | } | ||
// | // 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) { | ||
// | // 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) { // | } 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) { // | } else if (rw > lw) { // Using the width of the larger side | ||
prefw = rw - margen; | prefw = rw - margen; | ||
} else { | } else { | ||
Line 250: | Line 250: | ||
} | } | ||
wnd.css({width: prefw, left: left}); | wnd.css({width: prefw, left: left}); | ||
// | // Now the vertical position. Width needs to be assigned in order to calculate correctly. | ||
var top = elOffset.top - parseInt(wnd.height(), 10) - margen; | var top = elOffset.top - parseInt(wnd.height(), 10) - margen; | ||
// | // 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'}); | ||
// | // 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 324: | Line 324: | ||
//return thumb.replace(/\/revision\/latest\/scale-to-width(-down)?\/\d+/, ''); | //return thumb.replace(/\/revision\/latest\/scale-to-width(-down)?\/\d+/, ''); | ||
// | // 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 359: | Line 359: | ||
// Resizing large images - orginal by Christian Montoya edited by me. | // Resizing large images - orginal by Christian Montoya edited by me. | ||
pagesize = _getPageSize(), | pagesize = _getPageSize(), | ||
// | // 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(), | ||
firstNav, imgOpt; | firstNav, imgOpt; | ||
// | // 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 375: | ||
firstNav = (img.attr('src') || '') === ''; | firstNav = (img.attr('src') || '') === ''; | ||
// | // Thickbox window dimensions for positioning | ||
_width = imageWidth + _imageMarginWidth * 2; // 15px | _width = imageWidth + _imageMarginWidth * 2; // 15px gap on both sides | ||
// | // 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 385: | ||
imgOpt = {width: imageWidth, height: imageHeight, opacity: 1}; | imgOpt = {width: imageWidth, height: imageHeight, opacity: 1}; | ||
// | // We look to see if it loads when opening or after browsing. If it comes from opening, skip animation | ||
if (firstNav) { | if (firstNav) { | ||
img.css(imgOpt); | img.css(imgOpt); | ||
Line 399: | Line 399: | ||
$('#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(' | $('#TB_imageCount').text('Image ' + (seq+1) + ' of ' + len); | ||
}, | }, | ||
_navigate = function() { | _navigate = function() { | ||
Line 416: | Line 416: | ||
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); | ||
// | // For SVG we already know its aspect ratio, although not its original dimensions | ||
// | // It would have to be done differently to load the SVG. Instead, here it is dynamically determined | ||
// | // 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 426: | ||
}}); | }}); | ||
} | } | ||
// | // 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 473: | Line 473: | ||
return; | return; | ||
} | } | ||
if (_isTag(target,'img')) { // Gallery | if (_isTag(target,'img')) { // Gallery or 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,'mw-file-description')) || _isClass(a,'link-internal')) { | ||
Line 480: | Line 480: | ||
} | } | ||
t = $(target); | t = $(target); | ||
// | // 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 496: | ||
}, | }, | ||
_createImgTip = function() { | _createImgTip = function() { | ||
_imgTip = $('<div id="TB_imagetip" title=" | _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 534: | Line 534: | ||
$(window.Thickbox.init); | $(window.Thickbox.init); | ||
} | } | ||
Latest revision as of 09:24, 18 December 2023
/* <pre>
* Thickbox4MediaWiki v3.13 - 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
* Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
*/
window.Thickbox = (function($, mw) {
'use strict';
var _version = '3.13',
// Minimum dimensions
_minWidth = 210,
// Margin between the image and the border of ThickBox
_imageMarginWidth = 15,
// Minimum margin to the edge of the window. If the image is exceeded it will be reduced
_minMarginWidth = 30,
_minMarginHeight = 15,
// Waiting time for the loader to appear in ms
_loaderWait = 500,
// Internal
_imgPreloader = null,
_galleryData = null,
_galleryIndex = -1,
_width = null,
_height = null,
_getCaption = null,
_imgTip = null,
_imgTipTarget = null,
_imgTipVisible = false,
_loaderPresent = false,
_loaderTm = null,
_logger = null,
// Private methods
_init = function() {
// We could have this event listener directly on 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({
'click.thickbox': _triggerEvent,
'mouseover.thickbox_imgtip': _imgTipEvent
});
},
_triggerEvent = function(e) {
// If there is any special key pressed, we exit
if (e.ctrlKey || e.altKey || e.shiftKey) {
return true;
}
var target = e.target;
if (_isTag(target,'img')) { // Gallery o thumb
var a = target.parentNode;
// 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')) {
return true;
}
// MW < 1.40
if (_isClass(target,'thumbimage')) {
// Es thumb
a.blur();
_getCaption = _getCaptionThumb;
_showImage(a);
return false;
}
// MW >= 1.40
if (_isTag(a.parentNode,'figure')) {
// Es thumb
a.blur();
_getCaption = _getCaptionThumb140;
_showImage(a);
return false;
}
var gb = $(a).closest('li.gallerybox').get(0);
// MediaWiki gallery
if (gb) {
var t = gb.parentNode;
if (_isTag(t,'ul') && _isClass(t,'gallery')) {
a.blur();
_getCaption = _getCaptionMW;
_galleryData = $(t).find('div.thumb a.image,div.thumb a.mw-file-description'); // MW<1.40,MW>=1.40
_galleryIndex = _galleryData.index(a);
_showImage(a);
return false;
}
}
// Is generic thumbnail
a.blur();
_getCaption = _getCaptionEmpty;
_showImage(a);
return false;
} else if (_isTag(target,'a')) {
var sup = target.parentNode;
if (!_isTag(sup,'sup') || !_isClass(sup,'reference')) {
return true;
}
target.blur();
_showElement(target);
return false;
}
return true;
},
// Helper and speedy functions
_isClass = function(el, cn) {
return el.className && (el.className === cn || (' '+el.className+' ').indexOf(' '+cn+' ') != -1);
},
_isTag = function(el, tn) {
return (el.nodeName && el.nodeName.toUpperCase() === tn.toUpperCase());
},
// Loader image
_startLoader = function() {
if (_loaderPresent || _loaderTm) {
return;
}
if (_loaderWait > 0) {
_loaderTm = setTimeout(_displayLoader, _loaderWait);
} else {
_displayLoader();
}
},
_stopLoader = function() {
var t = _loaderTm;
_loaderTm = null;
if (t) {
clearTimeout(t);
}
if (_loaderPresent) {
$('#TB_load').remove();
_loaderPresent = false;
}
},
_displayLoader = function() {
_loaderPresent = true;
_loaderTm = null;
$(document.body).append('<div id="TB_load">');
},
// Main functions
_preload = function() {
$(document.body).addClass('thickbox_loaded');
$('#TB_overlay').add('#TB_window').add('#TB_load').remove();
$(document.body).append('<div id="TB_overlay"></div><div id="TB_window" class="fixedpos"></div>');
$('#TB_overlay').click(_remove);
_startLoader();
},
_showImage = function(elem) {
try {
var url, $a, $img, descUrl, TB_secondLine = '', TB_descLink;
_preload();
$a = $(elem);
$img = $a.find('> img').eq(0);
url = _getUrlFromThumb( $img.attr('src') );
descUrl = $a.attr('href');
if ($img.data('image-key')) {
// image-key is the name for the URL. So not use image-name because it's encoded (& --> &amp;)
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>';
// Is it a gallery?
if (_galleryIndex != -1) {
TB_secondLine = '<div id="TB_secondLine">'+
'<span id="TB_imageCount"></span>'+
'<span id="TB_prev"><a href="#" title="See previous [A]">< Prev.</a></span>'+
'<span id="TB_next"><a href="#" title="See next [S]">Next. ></a></span></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="Image" title="Close" />' + TB_descLink + '</div>' + TB_secondLine + '<div id="TB_caption"></div>');
if (_galleryIndex != -1) {
_updateNavigation();
}
$('#TB_caption').html( ( _getCaption($a) || null ) );
$('#TB_Image').add('#TB_closeWindowButton').click(_remove);
$(document).on('keyup.thickbox', _keyListener);
$('#TB_prev').add('#TB_next').click(_navigate);
$('#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) {
_imgPreloader = new Image();
}
_imgPreloader.onload = _imageLoaded;
_imgPreloader.onerror = _imageError;
_imgPreloader.src = ''; // chromium bug 7731
if (url.length > 3 && url.substr(url.length - 4).toLowerCase() == '.svg') {
// For SVG we already know its aspect ratio, although not its original dimensions
// It would have to be done differently to load the SVG. Instead, here it is dynamically determined
// 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);
} else {
_imgPreloader.src = url;
}
} catch(e) {
_log(e);
}
},
_showElement = function(target) {
try {
var url = target.href, idx = url.indexOf('#');
if (idx == -1) {
return false;
}
var baseurl = url.substr(0, idx),
hash = decodeURIComponent(url.substr(idx + 1)),
// Check that the URL is from the same document
locbase = document.location.href.replace(baseurl, ''),
rel = document.getElementById(hash);
if ((locbase !== '' && locbase.indexOf('#') !== 0) || rel === null) {
return false;
}
$('#TB_overlay').add('#TB_window').remove();
$(document.body).append('<div id="TB_overlay" class="transparent"></div><div id="TB_window"></div>');
$('#TB_overlay').click(_remove);
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'),
cel = $(rel).clone();
cel.contents().eq(0).remove();
cel.find('> sup').remove();
wnd.width(_minWidth).append(titleHTML+'<div id="TB_ajaxContent">'+cel.html()+'</div>');
var tgEl = $(target),
// horizontal space on each side of the element
elOffset = tgEl.offset(),
lw = elOffset.left,
rw = $(document).width() - elOffset.left - tgEl.width(),
// Calculating the optimal dimensions. Calculating the area and determine that the ideal is ratio 3/2
prefw = parseInt(Math.sqrt(wnd.width()*wnd.height()*3/2),10),
// Minimum width correction if scroll occurs
cd = $('#TB_ajaxContent')[0];
prefw += cd.scrollWidth-cd.clientWidth;
// Should not go below minimum
if (prefw < _minWidth) {
prefw = _minWidth;
}
// 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;
if (rw > prefw + margen) {
// is already correct
} else if (lw > prefw + margen) {
left = lw - prefw - margen;
} 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;
} else if (rw > lw) { // Using the width of the larger side
prefw = rw - margen;
} else {
prefw = lw - margen*2;
left = margen;
}
wnd.css({width: prefw, left: left});
// Now the vertical position. Width needs to be assigned in order to calculate correctly.
var top = elOffset.top - parseInt(wnd.height(), 10) - margen;
// If it does not fit above we place it below
if (top < margen) {
top = elOffset.top + tgEl.height() + margen;
}
wnd.css({top: top, visibility: 'visible'});
// Animation if it is outside the visual field
if (($('html')[0].scrollTop||$('body')[0].scrollTop) > top-margen) {
$('html,body').animate({scrollTop: top - margen}, 250, 'swing');
}
$('#TB_closeWindowButton').click(_remove);
$(document).on('keyup.thickbox', _keyListener);
} catch (e) {
_log(e);
}
},
//helper functions below
_displayClean = function() {
_stopLoader();
$('#TB_window').css('visibility','visible');
},
_remove = function() {
$(document).off('keyup.thickbox');
_galleryData = null;
_galleryIndex = -1;
if (_imgPreloader !== null) {
_imgPreloader.onload = null;
_imgPreloader.onerror = null;
}
$('#TB_ImageOff').add('#TB_Image').add('#TB_closeWindowButton').add('#TB_prev').add('#TB_next').off();
$('#TB_window').add('#TB_Image').queue('fx',[]).stop();
$('#TB_window').fadeOut('fast',function(){$('#TB_window').add('#TB_overlay').off().remove();});
_stopLoader();
$(document.body).removeClass('thickbox_loaded');
return false;
},
_keyListener = function(e) {
var keycode = e.which;
if (keycode == 27) { // close
_remove();
} else if (keycode == 65) { // 'A' display previous image
$('#TB_prev').click();
} else if (keycode == 83) { // 'S' display next image
$('#TB_next').click();
}
},
_position = function(anim) {
// Ancho mínimo
var border = 4;
if (_width < _minWidth) {
_width = _minWidth;
}
var o = {marginLeft: '-' + parseInt((_width / 2)+border,10).toString() + 'px', width: _width + 'px', marginTop: '-' + parseInt((_height / 2)+border,10).toString() + 'px'};
if (anim) {
$('#TB_window').animate(o, {queue: false, duration: 'fast'});
} else {
$('#TB_window').css(o);
}
},
_getPageSize = function() {
var de = document.documentElement,
w = window.innerWidth || (de&&de.clientWidth) || document.body.clientWidth,
h = window.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
return [w,h];
},
_getUrlFromThumb = function(thumb) {
if (thumb.indexOf('.svg/') != -1) {
return thumb;
}
// Wikia
//return thumb.replace(/\/revision\/latest\/scale-to-width(-down)?\/\d+/, '');
// 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 ) {
return thumb;
}
var urlparts = thumb.split('/');
return thumb.replace('/thumb/','/').replace('/'+urlparts[urlparts.length-1], '');
},
_getCaptionThumb = function(elem) {
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) {
return $('<div>').text((elem.attr('title')||'')).html();
},
_getCaptionMW = function(gitem) {
return gitem.closest('li.gallerybox').find('div.gallerytext').eq(0).html();
},
_getCaptionWikia = function(gitem) {
return gitem.closest('div.wikia-gallery-item').find('> div.lightbox-caption').eq(0).html();
},
_imageError = function() {
_stopLoader();
},
_imageLoaded = function() {
_updateImageView(_imgPreloader.width, _imgPreloader.height, _imgPreloader.src);
},
_updateImageView = function(imageWidth, imageHeight, imageSrc) {
var navigation = (_galleryIndex != -1),
img = $('#TB_Image'),
wndH = $('#TB_window').height(),
// Resizing large images - orginal by Christian Montoya edited by me.
pagesize = _getPageSize(),
// Maximum dimensions
x = pagesize[0] - _minMarginWidth * 2 - _imageMarginWidth * 2,
y = pagesize[1] - _minMarginHeight * 2 - wndH + img.height(),
firstNav, imgOpt;
// 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) {
imageHeight = imageHeight * (x / imageWidth);
imageWidth = x;
}
if (imageHeight > y) {
imageWidth = imageWidth * (y / imageHeight);
imageHeight = y;
}
// End Resizing
firstNav = (img.attr('src') || '') === '';
// Thickbox window dimensions for positioning
_width = imageWidth + _imageMarginWidth * 2; // 15px gap on both sides
// 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;
img.attr({
src: imageSrc,
alt: $('#TB_caption').text()
});
imgOpt = {width: imageWidth, height: imageHeight, opacity: 1};
// We look to see if it loads when opening or after browsing. If it comes from opening, skip animation
if (firstNav) {
img.css(imgOpt);
} else {
img.animate(imgOpt, {duration: 'fast'});
}
_position(navigation && !firstNav);
_displayClean();
},
_updateNavigation = function() {
var seq = _galleryIndex, len = _galleryData.length;
$('#TB_prev').css('display', (seq === 0 ? 'none' : ''));
$('#TB_next').css('display', (seq >= len-1 ? 'none' : ''));
$('#TB_imageCount').text('Image ' + (seq+1) + ' of ' + len);
},
_navigate = function() {
var url, seq = _galleryIndex + (this.id == 'TB_prev' ? -1 : 1), len = _galleryData.length, gitem, $img;
if (seq < 0 || seq > len - 1) {
return false;
}
_galleryIndex = seq;
gitem = _galleryData.eq(seq);
url = _getUrlFromThumb(gitem.find('> img').eq(0).attr('src'));
_updateNavigation();
if (_imgPreloader.src != url) {
$('#TB_window').stop();
$('#TB_Image').queue('fx',[]).stop().animate({opacity: 0}, {duration: 'fast', complete: function() {
_startLoader();
if (url.length > 3 && url.substr(url.length - 4).toLowerCase() == '.svg') {
$img = gitem.find('> img').eq(0);
// For SVG we already know its aspect ratio, although not its original dimensions
// It would have to be done differently to load the SVG. Instead, here it is dynamically determined
// 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);
_imgPreloader.src = '';
} else {
_imgPreloader.src = url;
}
}});
}
// 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_descLink').attr('href',gitem.attr('href'));
return false;
},
_setParams = function(p) {
var val;
if (typeof p != 'object') {
return;
}
for (var n in p) {
if (p.hasOwnProperty(n)) {
val = p[n];
switch(n) {
case 'minWidth':
_minWidth = val;
break;
case 'imageMarginWidth':
_imageMarginWidth = val;
break;
case 'minMarginWidth':
_minMarginWidth = val;
break;
case 'minMarginHeight':
_minMarginHeight = val;
break;
case 'loaderWait':
_loaderWait = (typeof val == 'number' && val);
break;
case 'logger':
_logger = (typeof val == 'function' && val);
break;
}
}
}
},
_log = function(msg) {
if (_logger) {
_logger(msg);
}
},
_imgTipEvent = function(e) {
var target = e.target, a, t;
if (e.ctrlKey || e.altKey || e.shiftKey) {
_hideImgTip();
return;
}
if (_isTag(target,'img')) { // Gallery or thumb
a = target.parentNode;
if (!_isTag(a,'a') || !(_isClass(a,'image') || _isClass(a,'mw-file-description')) || _isClass(a,'link-internal')) {
_hideImgTip();
return;
}
t = $(target);
// We show only if the image has a minimum size
if (t.width() < 40 || t.height() < 40) {
return;
}
_showImgTip(t);
return;
}
_hideImgTip();
},
_imgTipClickEvent = function() {
if (_imgTipTarget) {
$(_imgTipTarget).click();
return false;
}
},
_createImgTip = function() {
_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);
},
_showImgTip = function(target) {
if (!_imgTip) {
_createImgTip();
}
var of = target.offset();
_imgTip.css({
display: 'block',
left: of.left + target.width(),
top: of.top + target.height()
});
_imgTipVisible = true;
_imgTipTarget = target;
},
_hideImgTip = function() {
if (_imgTipVisible) {
_imgTip.css('display','none');
_imgTipVisible = false;
_imgTipTarget = null;
}
};
// Public functions
return {
init: _init,
showImage: _showImage,
showElement: _showElement,
remove: _remove,
setParams: _setParams
};
}(jQuery, mw));
if (mw.config.get('wgAction', '') != 'history' || !(mw.config.get('wgNamespaceNumber', 0) == -1 && mw.config.get('wgCanonicalSpecialPageName', '') == 'Recentchanges')) {
$(window.Thickbox.init);
}