MediaWiki:Gadget-Thickbox.js: Difference between revisions

    From Hokuto no Ken Encyclopedia | HnKWiki
    No edit summary
    No edit summary
    Line 1: Line 1:
    /*
    /* <pre>
      * Thickbox4MediaWiki v3.12 - Based on Thickbox 3.1 By Cody Lindley (http://www.codylindley.com)
      * Thickbox4MediaWiki v3.13 - Based on Thickbox 3.1 By Cody Lindley (http://www.codylindley.com)
      * Copyright (c) 2010 - 2022 Jesús Martínez (User:Ciencia_Al_Poder), Original Thickbox Copyright (c) 2007 Cody Lindley
      * 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
      * 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',
    var _version = '3.12',
    // Minimum dimensions
    // Minimum dimensions
    Line 29: Line 30:
    _loaderTm = null,
    _loaderTm = null,
    _logger = null,
    _logger = null,
    // Private functions
    // Private methods
    _init = function() {
    _init = function() {
    // COMPAT
    // 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
    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 49: Line 47:
    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"
    // 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, '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;
    }
    }
    // Wikia 2 Gallery
    // MW < 1.40
    if (_isClass(a,'lightbox')) {
    if (_isClass(target,'thumbimage')) {
    target.blur();
    // Es thumb
    _getCaption = _getCaptionWikia;
    a.blur();
    _galleryData = $(target).closest('div.wikia-gallery').find('> div.wikia-gallery-item > div.thumb > div.gallery-image-wrapper > a.lightbox');
    _getCaption = _getCaptionThumb;
    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;
    }
    }
    if (_isClass(target,'thumbimage')) {
    // MW >= 1.40
    // Its thumbnail
    if (_isTag(a.parentNode,'figure')) {
    // Es thumb
    a.blur();
    a.blur();
    _getCaption = _getCaptionThumb;
    _getCaption = _getCaptionThumb140;
    _showImage(a);
    _showImage(a);
    return false;
    return false;
    }
    }
    var gb = a.parentNode.parentNode.parentNode.parentNode;
    var gb = $(a).closest('li.gallerybox').get(0);
    // MediaWiki gallery
    // MediaWiki gallery
    if (_isTag(gb,'li') && _isClass(gb,'gallerybox')) {
    if (gb) {
    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');
    _galleryData = $(t).find('div.thumb a.image,div.thumb a.mw-file-description'); // MW<1.40,MW>=1.40
    _galleryIndex = _galleryData.index(a);
    _galleryIndex = _galleryData.index(a);
    _showImage(a);
    _showImage(a);
    Line 87: Line 79:
    }
    }
    }
    }
    // Its generic thumbnail
    // Is 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 99: Line 91:
    target.blur();
    target.blur();
    _showElement(target);
    _showElement(target);
    return false;*/
    return false;
    }
    }
    return true;
    return true;
    Line 155: Line 147:
    descUrl = $a.attr('href');
    descUrl = $a.attr('href');
    if ($img.data('image-key')) {
    if ($img.data('image-key')) {
    // image-key is the name for the URL. Do not use image-name because it is encoded
    // image-key is the name for the URL. So not use image-name because it's encoded (& --> &amp;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="Go to the image\'s description page">File Page</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?
    // 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="See previous image [Left arrow]"></a></span>'+
    '<span id="TB_prev"><a href="#" title="See previous [A]">&lt; Prev.</a></span>'+
    '<span id="TB_next"><a href="#" title="See next image [Right arrow]"></a></span></div>';
    '<span id="TB_next"><a href="#" title="See next [S]">Next. &gt;</a></span></div>';
    }
    }
    $('#TB_window').append('<div id="TB_closeWindow"><a href="#" id="TB_closeWindowButton" title="Close [ESC]">close</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="Image" title="Close" />' + 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 177: Line 169:
    $('#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 192: Line 192:
    _imgPreloader.src = url;
    _imgPreloader.src = url;
    }
    }
    } catch(e) {
    } catch(e) {
    _log(e);
    _log(e);
    Line 205: Line 204:
    var baseurl = url.substr(0, idx),
    var baseurl = url.substr(0, idx),
    hash = decodeURIComponent(url.substr(idx + 1)),
    hash = decodeURIComponent(url.substr(idx + 1)),
    // We check that the URL is from the same document
    // 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 216: Line 215:
    $('#TB_overlay').click(_remove);
    $('#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>',
    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 228: Line 227:
    lw = elOffset.left,
    lw = elOffset.left,
    rw = $(document).width() - elOffset.left - tgEl.width(),
    rw = $(document).width() - elOffset.left - tgEl.width(),
    // We calculate the optimal dimensions. We calculate the area and determine that the ideal is ratio 3/2
    // 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
    // Minimum width correction if scroll occurs
    cd = $('#TB_ajaxContent')[0];
    cd = $('#TB_ajaxContent')[0];
    prefw += cd.scrollWidth-cd.clientWidth;
    prefw += cd.scrollWidth-cd.clientWidth;
    // The minimum width should not be reduced
    // Should not go below minimum
    if (prefw < _minWidth) {
    if (prefw < _minWidth) {
    prefw = _minWidth;
    prefw = _minWidth;
    Line 245: Line 244:
    } 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
    } 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) { // The available width of the major side is used
    } else if (rw > lw) { // Using the width of the larger side
    prefw = rw - margen;
    prefw = rw - margen;
    } else {
    } else {
    Line 252: Line 251:
    }
    }
    wnd.css({width: prefw, left: left});
    wnd.css({width: prefw, left: left});
    // Now the vertical position. it needs that we have assigned the width to calculate it well
    // 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 it does not fit above we place it below
    Line 294: Line 293:
    if (keycode == 27) { // close
    if (keycode == 27) { // close
    _remove();
    _remove();
    } else if (keycode == 37) { // 'Left arrow' display previous image
    } else if (keycode == 65) { // 'A' display previous image
    $('#TB_prev').click();
    $('#TB_prev').click();
    } else if (keycode == 39) { // 'Right arrow' display next image
    } else if (keycode == 83) { // 'S' display next image
    $('#TB_next').click();
    $('#TB_next').click();
    }
    }
    Line 336: Line 335:
    _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 361: Line 363:
    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;
    // 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
    // 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
    Line 376: Line 376:


    firstNav = (img.attr('src') || '') === '';
    firstNav = (img.attr('src') || '') === '';
    // Thickbox window dimensions to position
    // Thickbox window dimensions for positioning
    _width = imageWidth + _imageMarginWidth * 2; // 15px de espacio en cada lado
    _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
    // 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;
    Line 386: Line 386:


    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, without animation
    // 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 417: 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);
            // For SVG we already know its aspect ratio, although not its original dimensions
    // 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 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
    // 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 474: Line 474:
    return;
    return;
    }
    }
    if (_isTag(target,'img')) { // Gallery o thumb
    if (_isTag(target,'img')) { // Gallery or thumb
    a = target.parentNode;
    a = target.parentNode;
    if (!_isTag(a,'a') || !_isClass(a,'image') || _isClass(a,'link-internal')) {
    if (!_isTag(a,'a') || !(_isClass(a,'image') || _isClass(a,'mw-file-description')) || _isClass(a,'link-internal')) {
    _hideImgTip();
    _hideImgTip();
    return;
    return;
    Line 497: Line 497:
    },
    },
    _createImgTip = function() {
    _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 = $('<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 508: Line 508:
    display: 'block',
    display: 'block',
    left: of.left + target.width(),
    left: of.left + target.width(),
    top: of.top
    top: of.top + target.height()
    });
    });
    _imgTipVisible = true;
    _imgTipVisible = true;

    Revision as of 09:23, 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',
    	var _version = '3.12',
    	// 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;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]">&lt; Prev.</a></span>'+
    					'<span id="TB_next"><a href="#" title="See next [S]">Next. &gt;</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);
    }