User:Magnus Manske/wikipic.js

From mediawiki.org

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/* wikipic
    Copyright (C) 2011 Magnus Manske <magnusmanske@googlemail.com>
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to
    
    Free Software Foundation, Inc.
    51 Franklin Street, Fifth Floor
    Boston, MA   02110-1301, USA.
    
    or see this page : https://www.gnu.org/licenses/gpl-2.0.txt
 */


if ( typeof ( $ ) === 'undefined' ) $ = $j ;

var wikipic = 
    /** @lends wikipic.prototype */
{

	/* Initialize some variables */
	
	// Misc settings
	api_local : mw.util.wikiScript( 'api' ) ,
	api_commons : '//commons.wikimedia.org/w/api.php?callback=?' , // Needs callback
	thumbsize : 100 , // px; 60 * 2 (thumb_zoom) makes this probably pre-rendered size of 120px
	max_files_gallery : 126 ,
	max_files_slideshow : 50 ,
	max_files : 0 ,
	thumb_zoom : 2.5 , // Basic large thumbnail size factor (times thumbsize)
	zoom_factor : 1 , // Additional zoom on large thumbnail
	slideshow_delay : 4000 , // ms
	min_files_threshold : 32 ,
	min_slideshow_image_size : 120 ,
	slide_width : 0 ,
	slide_height : 0 ,
	slideshow_fullscreen_only : true , // When true, "normal" slideshow will not be offered, and fullscreen slideshow will get the "normal" icon

	// Icon URLs
	icons : {
		gallery : '//upload.wikimedia.org/wikipedia/commons/thumb/5/59/Gnome-emblem-photos.svg/32px-Gnome-emblem-photos.svg.png' ,
		slideshow : '//upload.wikimedia.org/wikipedia/commons/7/74/Farm-Fresh_slideshow.png' ,
		info : '//upload.wikimedia.org/wikipedia/commons/thumb/0/07/Tango-style_info_icon.svg/32px-Tango-style_info_icon.svg.png' ,
		fullscreen : '//upload.wikimedia.org/wikipedia/commons/thumb/d/dc/View-fullscreen.svg/32px-View-fullscreen.svg.png' ,
		slideshow_play : '//upload.wikimedia.org/wikipedia/commons/thumb/9/93/Gnome-media-playback-start.svg/48px-Gnome-media-playback-start.svg.png' ,
		slideshow_pause : '//upload.wikimedia.org/wikipedia/commons/thumb/0/04/Gnome-media-playback-pause.svg/48px-Gnome-media-playback-pause.svg.png' ,
		slideshow_first : '//upload.wikimedia.org/wikipedia/commons/thumb/9/92/Gnome-media-skip-backward.svg/48px-Gnome-media-skip-backward.svg.png' ,
		slideshow_last : '//upload.wikimedia.org/wikipedia/commons/thumb/7/73/Gnome-media-skip-forward.svg/48px-Gnome-media-skip-forward.svg.png' ,
		slideshow_prev : '//upload.wikimedia.org/wikipedia/commons/thumb/5/5d/Gnome-media-seek-backward.svg/48px-Gnome-media-seek-backward.svg.png' ,
		slideshow_next : '//upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Gnome-media-seek-forward.svg/48px-Gnome-media-seek-forward.svg.png' ,
		slideshow_close : '//upload.wikimedia.org/wikipedia/commons/thumb/6/65/Gnome-window-close.svg/32px-Gnome-window-close.svg.png' ,
		public_domain : '//upload.wikimedia.org/wikipedia/commons/thumb/6/62/PD-icon.svg/32px-PD-icon.svg.png' ,
		creative_commons : '//upload.wikimedia.org/wikipedia/commons/thumb/7/79/CC_some_rights_reserved.svg/90px-CC_some_rights_reserved.svg.png' ,
		cc_by : '//upload.wikimedia.org/wikipedia/commons/thumb/1/11/Cc-by_new_white.svg/24px-Cc-by_new_white.svg.png' ,
		cc_sa : '//upload.wikimedia.org/wikipedia/commons/thumb/2/29/Cc-sa.svg/24px-Cc-sa.svg.png' ,
		gnu : '//upload.wikimedia.org/wikipedia/commons/thumb/2/22/Heckert_GNU_white.svg/32px-Heckert_GNU_white.svg.png' ,
		commons : '//upload.wikimedia.org/wikipedia/commons/thumb/4/4a/Commons-logo.svg/32px-Commons-logo.svg.png' ,
		spinning : '//upload.wikimedia.org/wikipedia/commons/8/85/Throbber_allbackgrounds_circledots_32.gif'
	} ,
	
	not_useful : [ // Categories that are not useful to display
    	/\blicense migration\b/i , 
    	/self-published work/i , 
    	/user-created/i , 
    	/^files by user:/i , 
    	/^media needing /i ,
    	/^\breviewed\b/i ,
    	/\bOTRS\b/i ,
        /images with annotations/i ,
        /\bwith missing\b/i ,
        /\buploadbot\b/i ,
        /\bflickr\b/i
    ] ,

	
	// I18n
	i18n_all : {
		en : {
			fullscreen : 'Full-screen slideshow' ,
			related_files : 'Show similar and related files' ,
			related_files_dialog_title : 'Similar and related files' ,
			looking_for_files : 'Looking for files...' ,
			slideshow : 'Start slideshow' ,
			slideshow_dialog_title : 'Slideshow' ,
			first_slide : 'Loading first slide' ,
			loading_desc : 'Loading description...' ,
			missing : 'Missing' ,
			author : 'Author' ,
			date : 'Date' ,
			description : 'Description' ,
			open_file_description_page : 'Open file description page' ,
			filesize : 'Size' ,
			categories : 'Categories' ,
			licenses : 'License(s)' ,
			commons : 'Wikimedia Commons' ,
			info : 'Information about this file' ,
			close_slideshow : 'Click or press escape to close the slideshow' ,
			hosted_on_commons : 'This file is hosted on<br/><a href="{1}">Wikimedia Commons</a>' ,
			info_dialog_title : 'File information'
		} ,
		de : {
			fullscreen : 'Full-screen Diashow' ,
			related_files : 'Zeige Àhnliche und verwandte Bilder' ,
			related_files_dialog_title : 'Ähnliche Bilder' ,
			looking_for_files : 'Suche nach Bildern...' ,
			slideshow : 'Starte Diashow' ,
			slideshow_dialog_title : 'Diashow' ,
			first_slide : 'Lade erstes Bild' ,
			loading_desc : 'Lade Beschreibung...' ,
			missing : 'Fehlt' ,
			author : 'Autor' ,
			date : 'Datum' ,
			description : 'Beschreibung' ,
			open_file_description_page : 'Bildbeschreibungsseite öffnen' ,
			filesize : 'GrĂ¶ĂŸe' ,
			categories : 'Kategorien' ,
			licenses : 'Lizenz(en)' ,
			commons : 'Wikimedia Commons' ,
			info : 'Informationen ĂŒber diese Datei' ,
			close_slideshow : 'Hier klicken oder Escape drĂŒcken, um die Diashow zu beenden' ,
			hosted_on_commons : 'Diese Datei befindet sich<br/>auf <a href="{1}">Wikimedia Commons</a>' ,
			info_dialog_title : 'Datei-Informationen'
		}
	} ,
	
	i18n : {} , // Filled by init_i18n()

	/* Constructor */
	init : function () {
		wikipic.init_i18n () ;

        // Process thumbnails
		if ( wikipic.isTouchDevice() ) {
			$('a.image').bind('touchstart', function(e) {
				if ( $('#wikipic_box').length > 0 ) $('#wikipic_box').remove() ;
				else wikipic.show_icon_bar ( $(this) ) ;
			} ) ;
		}
		$('a.image').hover ( wikipic.onmousein , wikipic.onmouseout ) ;
        
        // Process full file on file page
        if ( mw.config.get('wgNamespaceNumber') == 6 ) {
            $('#file a').hover ( wikipic.onmousein , wikipic.onmouseout ) ;
        }

		$.each ( wikipic.icons , function ( k , v ) { // Pre-load images
			$('body').append ( "<img src='" + v + "' style='display:none' />" ) ;
		} ) ;
	} ,
	
	init_i18n : function () {
		wikipic.lang = mw.config.get ( 'wgUserLanguage' ) ;
		var lang = wikipic.lang ;
		if ( wikipic.i18n_all[wikipic.lang] === undefined ) lang = 'en' ; // Fallback
		wikipic.i18n = wikipic.i18n_all[lang] ;
	} ,
	
	/* Event handler for "mouse over thumbnailed image"; invokes the context menu icon bar */
	onmousein : function () {
		var me = $(this) ;
		wikipic.show_icon_bar ( me ) ;
	} ,
	
	/* shows the context menu icon bar */
	show_icon_bar : function ( me ) {
		$('#wikipic_box').stop(true).fadeTo(0,1);
		wikipic.o = me ;
		var off = me.find('img').offset() ;
		if ( off === null ) return ;
		var h = 32 + 4 ;
		var top = parseInt ( off.top ) - 2 ;
		var left = parseInt ( off.left ) + 1 ;
		top -= h ;
		var h = "<div id='wikipic_box'>" ;
		
		h += "<div class='wikipic_button_container'>" ;
		h += "<a href='#' onclick='wikipic.show_info();return false' title='" + wikipic.i18n.info + "'>" ;
		h += "<img src='" + wikipic.icons.info + "' border=0 />" ;
		h += "</a></div>" ;
		
		h += "<div class='wikipic_button_container'>" ;
		h += "<a href='#' onclick='wikipic.show_gallery();return false' title='" + wikipic.i18n.related_files + "'>" ;
		h += "<img src='" + wikipic.icons.gallery + "' border=0 />" ;
		h += "</a></div>" ;

		if ( wikipic.slideshow_fullscreen_only ) {
			h += "<div class='wikipic_button_container'>" ;
			h += "<a href='#' onclick='wikipic.show_fullscreen();return false' title='" + wikipic.i18n.fullscreen + "'>" ;
			h += "<img src='" + wikipic.icons.slideshow + "' border=0 />" ;
			h += "</a></div>" ;
		} else {
			h += "<div class='wikipic_button_container'>" ;
			h += "<a href='#' onclick='wikipic.show_slideshow();return false' title='" + wikipic.i18n.slideshow + "'>" ;
			h += "<img src='" + wikipic.icons.slideshow + "' border=0 />" ;
			h += "</a></div>" ;
			
			h += "<div class='wikipic_button_container'>" ;
			h += "<a href='#' onclick='wikipic.show_fullscreen();return false' title='" + wikipic.i18n.fullscreen + "'>" ;
			h += "<img src='" + wikipic.icons.fullscreen + "' border=0 />" ;
			h += "</a></div>" ;
		}
		
		h += "</div>" ;
		$('#wikipic_box').remove() ;
		$('body').prepend(h);
		
//		while ( left + $('#wikipic_box').width() >= $(window).width() ) left-- ;
		
		$('#wikipic_box').css ( { top : top+'px' , left : left+'px' , height : h+'px' , width : 'auto' } ) ;
		if ( left + $('#wikipic_box').width() >= $(window).width() )  {
			$('#wikipic_box').css ( { left : 'auto' , right : me.find('img').attr('right') } ) ;
		}
		$('#wikipic_box').fadeIn ( 'fast' ) ;
		
		$('#wikipic_box').hover (
			function () { wikipic.remove_icon_bar = false ; $('#wikipic_box').stop(true).fadeTo(0,1); } ,
			function () { wikipic.start_box_fadeout() ; }
		) ;

	} ,

	/* Event handler for "mouse leaves thumbnailed image"; invokes context icon box fading */
	onmouseout : function () {
		wikipic.start_box_fadeout() ;
	} ,
	
	/* starts context icon box fading */
	start_box_fadeout : function () {
		wikipic.remove_icon_bar = true ;
		$('#wikipic_box').fadeOut('fast',function(){ if(wikipic.remove_icon_bar) $('#wikipic_box').remove(); });
	} ,
	
	show_fullscreen : function () {
		$('body').css ( { 'overflow' : 'hidden' } ) ; // Hack to get scrollbar-less window width
		wikipic.slide_width = parseInt ( $(window).width() ) ;
		wikipic.slide_height = parseInt ( $(window).height() ) ;
		$('body').css ( { 'overflow' : '' } ) ; // End hack
		wikipic.mode = 'fullscreen' ;
		wikipic.max_files = wikipic.max_files_slideshow ;
		wikipic.start_fullscreen ( wikipic.i18n.slideshow_dialog_title ) ;
	} ,
	
	show_slideshow : function () {
		wikipic.slide_width = 500 ;
		wikipic.slide_height = 500 ;
		wikipic.mode = 'slideshow' ;
		wikipic.max_files = wikipic.max_files_slideshow ;
		wikipic.start_dialog ( wikipic.i18n.slideshow_dialog_title ) ;
	} ,
	
	show_info : function () {
		wikipic.slide_width = 500 ;
		wikipic.slide_height = 500 ;
		wikipic.mode = 'info' ;
		wikipic.max_files = 1 ;
		wikipic.start_dialog ( wikipic.i18n.info_dialog_title ) ;
	} ,
	
	/* creates the "related and simliar images" dialog and starts API queries */
	show_gallery : function () {
		wikipic.mode = 'gallery' ;
		wikipic.max_files = wikipic.max_files_gallery ;
		wikipic.start_dialog ( wikipic.i18n.related_files_dialog_title ) ;
	} ,
	
	start_dialog : function ( dialog_title ) {
		$('#wikipic_dialog').remove() ;
		wikipic.show_description = true ;
        var filename ;
        if ( wikipic.o.hasClass('image') ) { // Thumbnail
    		filename = decodeURIComponent ( wikipic.o.attr('href') ) ;
		    filename = filename.replace ( /^\/wiki\/[^:]+:/ , '' ) ;
        } else { // File: page
            filename = $(wikipic.o.find('img')[0]).attr('alt') ;
            filename = filename.replace ( /^[^:]+:/ , '' ) ;
        }
		wikipic.file = filename ;
		var h = "<div id='wikipic_dialog' title='" + dialog_title + "'>" ;
		h += "<div id='wikipic_dialog_content'><span class='wikipic_faint'>" + wikipic.i18n.looking_for_files + "</span></div>" ;
		h += "</div>" ;
		$('body').append ( h ) ;
		wikipic.slideshow_timer_is_on = false ;
		$("#wikipic_dialog").dialog ( {
			reizable : false ,
			autoOpen: false,
			width : '800px' , 
			modal : true ,
			close: function () {
				if ( wikipic.slideshow_timer_is_on ) clearTimeout ( wikipic.slideshow_timer ) ;
				return true ;
			} ,
			create: function(event, ui) {
				$("body").css({ overflow: 'hidden' })
			},
			beforeClose: function(event, ui) {
				$("body").css({ overflow: 'inherit' })
			}
		} );
		$("#wikipic_dialog").dialog ( 'open' ) ;
		
		if ( wikipic.mode == 'gallery' ) $("#wikipic_dialog").css ( { 'max-height' : 510 } ) ;
		if ( wikipic.mode == 'info' || wikipic.mode == 'slideshow' ) $("#wikipic_dialog").css ( { height : 505 } ) ;
		if ( wikipic.mode == 'fullscreen' ) {
			$(".ui-dialog-titlebar").hide() ;
			$("#wikipic_dialog").dialog ( 'option' , 'position' , [ 0 , 0 ] ) ;
			$("#wikipic_dialog").dialog ( 'option' , 'width' , $(window).width() ) ;
			$("#wikipic_dialog").dialog ( 'option' , 'height' , $(window).height() + 35 ) ;
			$(".ui-dialog").css ( { 'padding' : '0px' , 'margin' : '0px' , 'left' : '-5px' , 'top' : '-20px' } ) ;
		} else {
			if ( $(window).height()-50 < 600 ) $("#wikipic_dialog").css ( { 'max-height' : $(window).height()-50 } ) ;
			$('#wikipic_dialog').dialog('option', 'position', 'center');
		}
		
		$("#wikipic_dialog_content").css ( { 'overflow-y' : 'auto' } ) ;
		wikipic.candidate_images = new Object() ;
		
		if ( wikipic.mode == 'info' ) {
			var s = wikipic.file ;
			s = s.replace ( /^.+\/wiki\/[^:]+:/ , '' ) ;
			s = s.replace ( /_/g , ' ' ) ;
			wikipic.tried_extended = true ; // A blatant lie!
			wikipic.running_count = 1 ;
			wikipic.candidate_images[s] = 1000 ;
			wikipic.running ( -1 ) ;
			return ;
		}
		
		wikipic.tried_extended = false ;
		wikipic.running_count = 0 ;
		wikipic.imageinfo ( filename , 'galleries' , false ) ;
		wikipic.imageinfo ( filename , 'categories' , false ) ;
	} ,

	start_fullscreen : function ( dialog_title ) {
		$('#wikipic_dialog').remove() ;
		$('#wikipic_box').remove() ;
		wikipic.show_description = true ;
        var filename ;
        if ( wikipic.o.hasClass('image') ) { // Thumbnail
    		filename = decodeURIComponent ( wikipic.o.attr('href') ) ;
		    filename = filename.replace ( /^\/wiki\/[^:]+:/ , '' ) ;
        } else { // File: page
            filename = $(wikipic.o.find('img')[0]).attr('alt') ;
            filename = filename.replace ( /^[^:]+:/ , '' ) ;
        }
		wikipic.file = filename ;
		var h = "<div id='wikipic_fullscreen' style='background-color:black'>" ;
		h += "<div id='wikipic_dialog_content'><span class='wikipic_faint'>" + wikipic.i18n.looking_for_files + "</span></div>" ;
		h += "</div>" ;
		$("body").css({ overflow: 'hidden' })
		$('body').append ( h ) ;
		
		$(document).keyup(function(e) {
			if (e.keyCode == 27) { wikipic.close_fullscreen() ; }
		});
		
		wikipic.slideshow_timer_is_on = false ;
		
		$("#wikipic_dialog_content").css ( { 'overflow-y' : 'auto' } ) ;
		wikipic.candidate_images = new Object() ;
		
		if ( wikipic.mode == 'info' ) {
			var s = wikipic.file ;
			s = s.replace ( /^.+\/wiki\/[^:]+:/ , '' ) ;
			s = s.replace ( /_/g , ' ' ) ;
			wikipic.tried_extended = true ; // A blatant lie!
			wikipic.running_count = 1 ;
			wikipic.candidate_images[s] = 1000 ;
			wikipic.running ( -1 ) ;
			return ;
		}
		
		wikipic.tried_extended = false ;
		wikipic.running_count = 0 ;
		wikipic.imageinfo ( filename , 'galleries' , false ) ;
		wikipic.imageinfo ( filename , 'categories' , false ) ;
	} ,
	
	close_fullscreen : function () {
		$("body").css({ overflow: 'inherit' })
		if ( wikipic.slideshow_timer_is_on ) clearTimeout ( wikipic.slideshow_timer ) ;
		$('#wikipic_fullscreen').remove() ;
	} ,
		
	try_extended : function () {
		if ( wikipic.tried_extended ) return ;
		wikipic.tried_extended = true ;
		wikipic.follow_links ( mw.config.get( 'wgPageName' ) ) ;
		wikipic.follow_backlinks ( mw.config.get( 'wgPageName' ) ) ;
	} ,
	
	/* initial API query layer. Calls itself again for files on Commons */
	imageinfo : function ( filename , mode , commons ) {
		wikipic.running ( 1 ) ;
		var api = commons ? wikipic.api_commons : wikipic.api_local ;
		$.getJSON ( api , { 
			action : 'query' ,
			titles : 'File:'+filename ,
			prop : 'imageinfo' ,
			iiprop : 'url|size' ,
			iiurlwidth : wikipic.thumbsize ,
			iiurlheight : wikipic.thumbsize ,
			format : 'json'
		} , function ( data ) {
			$.each ( data.query.pages , function ( k , v ) {
				v.is_commons = commons ;
				v.name = filename ;
				if ( v.imagerepository == 'shared' && commons == false ) {
					if ( mode == 'galleries' ) wikipic.get_images_from_galleries ( v ) ; // Try local uses anyway
					wikipic.imageinfo ( filename , mode , true ) ;
					wikipic.running ( -1 ) ;
					return ;
				}
				if ( k == -1 ) {
					wikipic.running ( -1 ) ;
					return ;
				}
				if ( mode == 'galleries' ) wikipic.get_images_from_galleries ( v ) ;
				if ( mode == 'categories' ) wikipic.get_images_from_categories ( v ) ;
				wikipic.running ( -1 ) ;
			} ) ;
		} ) ;
	} ,
	
	follow_links : function ( title ) {
		wikipic.running ( 1 ) ;
		var api = wikipic.api_local ; // Page is always local
		$.getJSON ( api , { 
			action : 'query' ,
			generator : 'links' ,
			titles : title ,
			prop : 'images' ,
			gpllimit : 500 ,
			gplnamespace : 0 ,
			imlimit : 500 ,
			format : 'json'
		} , function ( data ) {
			if ( data.query === undefined ) return wikipic.running ( -1 ) ;
			if ( data.query.pages === undefined ) return wikipic.running ( -1 ) ;
			$.each ( data.query.pages , function ( page , v ) {
				if ( v.images === undefined ) return ;
				$.each ( v.images , function ( k1 , v1 ) {
					if ( !wikipic.is_same_filetype ( wikipic.file , v1.title ) ) return ;
					wikipic.add_candidate ( v1.title ) ;
				} ) ;
			} ) ;
			wikipic.running ( -1 ) ;
		} ) ;
		
	} ,
	
	follow_backlinks : function ( title ) {
		wikipic.running ( 1 ) ;
		var api = wikipic.api_local ; // Page is always local
		$.getJSON ( api , { 
			action : 'query' ,
			generator : 'backlinks' ,
			gbltitle : title ,
			prop : 'images' ,
			gbllimit : 500 ,
			gblnamespace : 0 ,
			imlimit : 500 ,
			format : 'json'
		} , function ( data ) {
			if ( data.query === undefined ) return wikipic.running ( -1 ) ;
			if ( data.query.pages === undefined ) return wikipic.running ( -1 ) ;
			$.each ( data.query.pages , function ( page , v ) {
				if ( v.images === undefined ) return ;
				$.each ( v.images , function ( k1 , v1 ) {
					if ( !wikipic.is_same_filetype ( wikipic.file , v1.title ) ) return ;
					wikipic.add_candidate ( v1.title ) ;
				} ) ;
			} ) ;
			wikipic.running ( -1 ) ;
		} ) ;
		
	} ,
	
	get_images_from_categories : function ( io ) {
		wikipic.running ( 1 ) ;
		var api = io.is_commons ? wikipic.api_commons : wikipic.api_local ;
		$.getJSON ( api , { 
			action : 'query' ,
			prop : 'categories' ,
			titles : 'File:'+io.name ,
			'clshow' : '!hidden' ,
			cllimit : 500 ,
			format : 'json'
		} , function ( data ) {
			if ( data.query === undefined ) return wikipic.running ( -1 ) ;
			if ( data.query.pages === undefined ) return wikipic.running ( -1 ) ;
			$.each ( data.query.pages , function ( k1 , v1 ) {
				if ( v1.categories === undefined ) return ;
				$.each ( v1.categories , function ( k2 , v2 ) {
					wikipic.add_files_from_category ( v2.title , io.is_commons ) ;
				} ) ;
			} ) ;
			wikipic.running ( -1 ) ;
		} ) ;
	} ,
	
	add_files_from_category : function ( cat , is_commons ) {
		wikipic.running ( 1 ) ;
		var api = is_commons ? wikipic.api_commons : wikipic.api_local ;
		$.getJSON ( api , { 
			action : 'query' ,
			list : 'categorymembers' ,
			cmtitle : cat ,
			cmtype : 'file' ,
			cmlimit : 500 ,
			format : 'json'
		} , function ( data ) {
			if ( data.query === undefined ) return wikipic.running ( -1 ) ;
			if ( data.query.categorymembers === undefined ) return wikipic.running ( -1 ) ;
			$.each ( data.query.categorymembers , function ( k1 , v1 ) {
				if ( !wikipic.is_same_filetype ( wikipic.file , v1.title ) ) return ;
				wikipic.add_candidate ( v1.title ) ;
			} ) ;
			wikipic.running ( -1 ) ;
		} ) ;
	} ,
	
	/* gets images that are displayed on the same pages as the "source" image; single project only */
	get_images_from_galleries : function ( io ) {
		wikipic.running ( 1 ) ;
		var api = io.is_commons ? wikipic.api_commons : wikipic.api_local ;
		$.getJSON ( api , {
			action : 'query' ,
			generator : 'imageusage' ,
			giutitle : io.title ,
			prop : 'images' ,
			imlimit : 500 ,
			giunamespace : 0 ,
			giulimit : 50 ,
			format : 'json'
		} , function ( data ) {
			if ( data.query === undefined ) return wikipic.running ( -1 ) ;
			if ( data.query.pages === undefined ) return wikipic.running ( -1 ) ;
			$.each ( data.query.pages , function ( page , v ) {
				if ( v.images === undefined ) return ;
				$.each ( v.images , function ( k2 , v2 ) {
					if ( !wikipic.is_same_filetype ( wikipic.file , v2.title ) ) return ;
					wikipic.add_candidate ( v2.title ) ;
				} ) ;
			} ) ;
			wikipic.running ( -1 ) ;
		} ) ;
	} ,
	
	/* handles the "running API query" counter, and invokes image display when counter reaches zero */
	running : function ( add ) {
		wikipic.running_count += add ;
		if ( add != -1 || wikipic.running_count != 0 ) return ;
		
		var a = [] ;
		var cnt = 0 ;
		$.each ( wikipic.candidate_images , function ( k , v ) {
			cnt++ ;
			if ( a[v] === undefined ) a[v] = [] ;
			a[v].push ( k ) ;
		} ) ;
		
		if ( cnt < wikipic.min_files_threshold && !wikipic.tried_extended ) { // Get more images
			$.each ( wikipic.candidate_images , function ( k , v ) { wikipic.candidate_images[k] += 100 ; } ) ; // Give existing files priority
			wikipic.try_extended() ;
			return ;
		}
		
		$('#wikipic_dialog_content').html ( '' ) ;
		
		if ( wikipic.mode == 'slideshow' || wikipic.mode == 'fullscreen' ) {
			wikipic.init_slideshow () ;
		}
		if ( wikipic.mode == 'info' ) {
			wikipic.init_info () ;
		}

		wikipic.files = new Array() ;
		while ( a.length > 0 ) {
			var b = a.pop() ;
			if ( b === undefined ) continue ;
			b = b.sort ( wikipic.randomSort ) ;
			$.each ( b , function ( k2 , v2 ) {
				if ( wikipic.files.length >= wikipic.max_files ) return ;
				wikipic.add_file ( v2 ) ;
			} ) ;
			if ( wikipic.files.length >= wikipic.max_files ) break ;
		}

	} ,
	
	toggle_slide_background : function () {
		var bgcol = $('#wikipic_slide').css ( 'backgroundColor' ) ;
		$('#wikipic_slide').css ( 'backgroundColor' , ( bgcol == 'transparent' ? 'black' : 'transparent' ) ) ;
	} ,
	
	init_slideshow : function () {
		wikipic.ffc_timer_on = false ;
		var h = '' ;
		h += "<div id='wikipic_slideshow_spinning'><img width='16px' src='" + wikipic.icons.spinning + "' /></div>" ;
		h += "<div id='wikipic_slide' onclick='wikipic.toggle_slide_background();return false'></div>" ;
		h += "<div id='wikipic_slide_desc'></div>" ; // class='wikipic_slideshow_chrome' 
		
		if ( wikipic.mode == 'slideshow' || wikipic.mode == 'fullscreen' ) {
			h += "<div id='wikipic_slide_controls' class='wikipic_slideshow_chrome'>" ;
			$.each ( [ 'first' , 'prev' , 'play' , 'pause' , 'next' , 'last' ] , function ( k , v ) {
				h += "<span id='wikipic_slideshow_button_" + v + "'>" ;
				h += "<a href='#' onclick='wikipic.on_slideshow_button(\"" + v + "\");return false'>" ;
				h += "<img src='" + wikipic.icons['slideshow_'+v]  + "' class='wikipic_slideshow_button' />" ;
				h += "</a></span>" ;
			} ) ;
			h += "</div>" ;
			
			if ( wikipic.mode == 'fullscreen' ) {
				h += "<div class='wikipic_slideshow_chrome' id='wikipic_slideshow_close'><a href='#' onclick='wikipic.close_dialog();return false' title='" + wikipic.i18n.close_slideshow + "'>" ;
				h += "<img src='" + wikipic.icons['slideshow_close']  + "' class='wikipic_slideshow_button' />" ;
				h += "</a></div>" ;
				
				// slideshow_close
			}
		}
		
		$('#wikipic_dialog_content').html ( h ) ;
		$('#wikipic_dialog').dialog('option', 'position', 'center');
		$('#wikipic_slide').width ( wikipic.slide_width ) ;
		$('#wikipic_slide').height ( wikipic.slide_height ) ;
		if ( wikipic.mode == 'fullscreen' ) {
			$('#wikipic_slideshow_spinning').css ( { 'top' : '5px' , 'right' : '10px' } ) ;
			$('#wikipic_slide').css ( { 'top' : '-1px' , 'left' : '0px' , 'margin' : '0px' } ) ;
			$('#wikipic_slide_controls').css ( { 'bottom' : '5px' } ) ;
			if ( 1 ) { // !wikipic.isTouchDevice() ) {
				wikipic.fadeFullscreenChrome ( false , false ) ;
				$('#wikipic_slide').mousemove ( function () { wikipic.fadeFullscreenChrome ( false , false ) } ) ;
				$('#wikipic_slide_controls').hover (
					function () { wikipic.fadeFullscreenChrome ( false , true ) } ,
					function () { wikipic.fadeFullscreenChrome ( false , false ) }
				) ;
			}
		} else {
			$('#wikipic_slideshow_spinning').css ( { 'top' : '5px' , 'right' : '40px' } ) ;
		}
	} ,
	
	fadeFullscreenChrome : function ( do_fade , no_timeout ) {
		if ( wikipic.ffc_timer_on ) {
			clearTimeout ( wikipic.ffc_timer ) ;
			wikipic.ffc_timer_on = false ;
		}
		if ( do_fade ) {
			$('.wikipic_slideshow_chrome').fadeOut ( 4000 ) ;
		} else {
			$('.wikipic_slideshow_chrome').stop(true,true).fadeIn() ;
			if ( !no_timeout ) {
				wikipic.ffc_timer_on = true ;
				wikipic.ffc_timer = setTimeout ( "wikipic.fadeFullscreenChrome(true,false)" , 3000 ) ;
			}
		}
	} ,
	
	close_dialog : function () {
		if ( wikipic.mode == 'fullscreen' ) wikipic.close_fullscreen() ;
		else $("#wikipic_dialog").dialog ( 'close' ) ;
	} ,
	
	init_info : function () {
		wikipic.init_slideshow() ;
		$('#wikipic_slideshow_spinning').show() ;
	} ,
	
	show_slideshow_play_pause : function ( show_play ) {
		if ( show_play ) {
			$('#wikipic_slideshow_spinning').hide() ; // Waiting for the user...
			$('#wikipic_slideshow_button_pause').hide() ;
			$('#wikipic_slideshow_button_play').show() ;
		} else {
			$('#wikipic_slideshow_button_pause').show() ;
			$('#wikipic_slideshow_button_play').hide() ;
		}
	} ,
	
	on_slideshow_button : function ( cmd ) {
		if ( wikipic.slideshow_timer_is_on ) clearTimeout ( wikipic.slideshow_timer ) ;
		wikipic.slideshow_timer_is_on = false ;
		
		if ( cmd == 'pause' ) {
			wikipic.show_slideshow_play_pause ( true ) ;
			return ;
		}
		
		if ( cmd == 'play' ) {
			wikipic.show_slideshow_play_pause ( false ) ;
			wikipic.next_slide ( false ) ;
			return ;
		} else if ( cmd == 'next' ) {
//			wikipic.slide_counter++ ;
			if ( wikipic.slide_counter >= wikipic.files.length ) wikipic.slide_counter = 0 ;
			wikipic.show_slideshow_play_pause ( true ) ;
		} else if ( cmd == 'prev' ) {
			wikipic.slide_counter-- ;
			wikipic.slide_counter-- ;
			if ( wikipic.slide_counter < 0 ) wikipic.slide_counter = wikipic.files.length - 1 ;
			wikipic.show_slideshow_play_pause ( true ) ;
		} else if ( cmd == 'first' ) {
			wikipic.slide_counter = 0 ;
			wikipic.show_slideshow_play_pause ( true ) ;
		} else if ( cmd == 'last' ) {
			wikipic.slide_counter = wikipic.files.length - 1 ;
			wikipic.show_slideshow_play_pause ( true ) ;
		}
		$('#wikipic_slideshow_spinning').show() ;
		wikipic.next_slide ( false , true ) ;
	} ,
	
	next_slide : function ( is_first_slide , prevent_timer_start ) {
		if ( wikipic.slideshow_timer_is_on ) {
			clearTimeout ( wikipic.slideshow_timer ) ;
			wikipic.slideshow_timer_is_on = false ;
		}
		
		if ( is_first_slide ) {
			wikipic.slide_counter = 0 ;
		}
		var o = wikipic.files[wikipic.slide_counter] ;
		
		if ( o.imageinfo === undefined ) {
			wikipic.slideshow_timer_is_on = true ;
			wikipic.slideshow_timer = setTimeout ( "wikipic.next_slide("+is_first_slide+")" , 250 ) ;
			return ;
		}
		
		wikipic.set_slide_description ( wikipic.slide_counter ) ;
		$('#wikipic_loading_first_slide').remove() ;
		var h = '' ;
		
		if ( is_first_slide ) h += "<div id='wikipic_loading_first_slide' class='wikipic_faint'>" + wikipic.i18n.first_slide + "</div>" ;
		h += "<a href='" + o.imageinfo[0].descriptionurl + "' target='_blank' onclick='wikipic.on_slideshow_button(\"pause\");wikipic.open_url(\"" + o.imageinfo[0].descriptionurl + "\");return true'>" ;
		h += "<img id='wikipic_slide_2' src='" + o.real_thumburl + "' style='position:relative;left:0px;" ;
		
		if ( o.imageinfo[0].width > o.imageinfo[0].height ) {
			var y = Math.floor ( ( wikipic.slide_height - o.imageinfo[0].thumbheight ) / 2 ) ;
			h += "top:"+y+"px;" ;
			h += "max-width:" + wikipic.slide_width + "px;" ;
		} else {
			var y = Math.floor ( ( wikipic.slide_height - o.imageinfo[0].thumbheight ) / 2 ) ;
			h += "top:"+y+"px;" ;
			h += "max-height:" + wikipic.slide_height + "px;" ;
		}
		
		h += "z-index:2' border=0 />" ;
		h += "</a>" ;
		$('#wikipic_slide').append ( h ) ;
		
		$('#wikipic_slide_1').remove() ;
		$('#wikipic_slide_2').attr ( 'id' , 'wikipic_slide_1' ) ;
		$('#wikipic_slide_1').css ( 'z-index' , '1' ) ;
		
		if ( wikipic.mode == 'info' ) {
			if ( $('#wikipic_slide_1').get(0).complete ) {
				$('#wikipic_slideshow_spinning').hide() ;
			} else {
				$('#wikipic_slide_1').load ( function () { $('#wikipic_slideshow_spinning').hide() } ) ;
			}
		}

		wikipic.slide_counter++ ;
		if ( wikipic.slide_counter >= wikipic.files.length ) wikipic.slide_counter = 0 ;

		if ( wikipic.mode == 'info' ) {
			$('#wikipic_loading_first_slide').remove() ;
			return ;
		}
		
		if ( prevent_timer_start === undefined ) {
			$('#wikipic_slideshow_spinning').show() ;
			if ( is_first_slide ) wikipic.first_slide_hack ( wikipic.slide_counter ) ;
			else wikipic.preload_slideshow_image ( wikipic.slide_counter , false ) ;
		} else {
			$('#wikipic_slideshow_spinning').show() ;
			setTimeout ( wikipic.slideshow_clear_spinning , 250 ) ;
		}
		
		
	} ,
	
	slideshow_clear_spinning : function () {
		if ( !$('#wikipic_slide_1').get(0).complete ) {
			setTimeout ( wikipic.slideshow_clear_spinning , 250 ) ;
			return ;
		}
		$('#wikipic_slideshow_spinning').hide() ;
	} ,
	
	set_slide_description : function ( counter ) {
		var o = wikipic.files[counter] ;
		var desc_id = 'wikipic_slide_desc_' + counter ;
		var h = "<div id='wikipic_slideshow_info_wrapper'>" ;
		if ( wikipic.mode == 'slideshow' || wikipic.mode == 'fullscreen' ) {
			h += "<div class='wikipic_faint'" ;
			h += ">" + (counter+1) + " / " + wikipic.files.length + "</div>" ;
		} else {
			h += "<br/>" ;
		}
		h += "<div style='" ;
		h += "'><b>" + o.name + "</b></div>" ;
		if ( wikipic.show_description ) h += "<div id='" + desc_id + "'><span class='wikipic_faint'>" + wikipic.i18n.loading_desc + "</span></div>" ;
		h += "</div>" ;
		$('#wikipic_slide_desc').html ( h ) ;
		
		if ( wikipic.mode == 'info' ) {
			$('#wikipic_slideshow_info_wrapper').css ( { 'max-height' : wikipic.slide_height } ) ;
		} else if ( wikipic.mode == 'fullscreen' ) {
			$('#wikipic_slideshow_info_wrapper').css ( { 'top' : '2px' , 'width' : 'auto' , 'max-width' : '' } ) ;
			$('#wikipic_slideshow_info_wrapper div').css ( { 'color' : '#999999' } ) ;
		} else {
			$('#wikipic_slideshow_info_wrapper').css ( { 'max-height' : 450 } ) ;
		}
		
		//if ( wikipic.mode != 'fullscreen' ) 
		wikipic.update_slide_description ( counter ) ;
	} ,

	precache_file_desc : function ( o ) {
		// Load description
		var api = o.is_commons ? wikipic.api_commons : wikipic.api_local ;
		$.getJSON ( api , {
			action : 'parse' ,
			page : 'File:'+o.name ,
			prop : 'text|categories|externallinks' , //|langlinks|links|templates|images|sections|revid|displaytitle
			format : 'json'
		} , function ( data ) {
			o.html_desc = data ;
		} ) ;
	} ,
	
	update_slide_description : function ( counter ) {
		if ( wikipic.files[counter] === undefined || wikipic.files[counter].html_desc === undefined ) {
			setTimeout ( "wikipic.update_slide_description(" + counter + ")" , 250 ) ;
			return ;
		}

		var o = wikipic.files[counter] ;
		var desc_id = 'wikipic_slide_desc_' + counter ;
		var data = wikipic.files[counter].html_desc ;
		
		var t = $( '<div>' + data.parse.text['*'] + '</div>' ) ;
		$.each ( [ 'layouttemplate' , 'licensetpl' , 'editsection' ] , function ( k , v ) {
			t.find('.'+v).remove() ;
		} ) ;
		$.each ( [ 1 , 2 , 3 , 4 , 5 , 6 ] , function ( k , v ) {
			t.find('h'+v).remove() ;
		} ) ;
		t.find('ul').remove() ;
		
		
		var onclick_pause_start = " onclick='wikipic.on_slideshow_button(\"pause\");" ;
		var onclick_pause = onclick_pause_start + "return true' " ;
		var missing = "<span class='wikipic_faint'>" + wikipic.i18n.missing + "</span>" ;
		
		var desc ;
		var desc_en ; // Fallback
		var desc_last = missing ;

		if ( t.find('#fileinfotpl_desc').length == 0 ) { // Presumably, no {{Information}} template
			if ( $('#rationale_purp').length == 0 ) { // Not a non-free one
				var s = t.text() ; // Use the entire page
				if ( s != '' ) desc_last = s ;
			}
		} else {
			var x = $($(t.find('#fileinfotpl_desc').get(0)).next()) ;
			if ( x.length > 0 ) desc_last = x.text() ;
		}
		
		var dx = $(t.find('#fileinfotpl_art_title')) ;
		if ( dx.length > 0 ) {
			dx = $($(dx.get(0)).next()) ;
			if ( dx.length > 0 ) desc_last = $(dx.get(0)).text() ;
		}
		
		$.each ( $(t.find('div.description')) , function ( k , v ) {
			var d = $(v) ;
			d.find('span.language').remove() ;
			desc_last = d.text() ;
			var al = d.attr('xml:lang') ;
			if ( al === undefined ) return ;
			if ( al == 'en' ) desc_en = desc_last ;
			if ( al == wikipic.lang ) desc = desc_last ;
		} ) ;
		
		
		if ( desc === undefined ) {
			if ( desc_en === undefined ) desc = desc_last ;
			else desc = desc_en ;
		}
		
		var author = $(t.find('#creator')) ;
		if ( author.length > 0 ) {
			author = $(author.get(0)).text().toString() ;
		} else {
			author = $(t.find('#fileinfotpl_aut')) ;
			if ( author.length > 0 ) author = $(author.next()) ;
			if ( author.length > 0 ) author = author.text() ;
		}
		
		if ( typeof author == 'string' ) {}
		else if ( author.length == 0 ) author = '' ;
		else author = author.text() ;
		if ( author == '' ) author = missing ;
		
		var date = $(t.find('#fileinfotpl_date')) ;
		if ( date.length == 0 ) date = '' ;
		else {
			date = $(date.next()) ;
			if ( date.length == 0 ) date = '' ;
			else date = date.text() ;
		}
		if ( date == '' ) date = missing ;
		
		var categories = [] ;
		var licenses = [] ;
		if ( data.parse.categories !== undefined ) {
		
			$.each ( data.parse.categories , function ( k , v ) {
				var is_license = false ;
				var is_useful = true ;
				var cn = v['*'] + '' ;
				cn = cn.replace ( /_/g , ' ' ) ;

				$.each ( [ /^CC-/i , /^PD\b/i , /^GFDL\b/i , /copyright/i ] , function ( k2 , v2 ) {
					if ( cn.match ( v2 ) ) is_license = true ;
				} ) ;

				$.each ( wikipic.not_useful , function ( k2 , v2 ) {
					if ( cn.match ( v2 ) ) is_useful = false ;
				} ) ;
				
				var cn_url = '/wiki/Category:' + encodeURIComponent ( cn ) ;
				if ( o.is_commons ) cn_url = '//commons.wikimedia.org' + cn_url ;
				var link_fix = onclick_pause_start + "wikipic.open_url(\"" + cn_url + "\");return false' href='" + cn_url + "'" ;
				
				if ( is_license ) {
					var h = '' ;
					if ( cn.match ( /^PD\b/ ) || cn.match ( /^CC-PD-Mark$/i ) ) h = "<img border=0 src='" + wikipic.icons.public_domain + "' />" ;
					else if ( cn.match ( /^GFDL\b/i ) ) h = "<img border=0 src='" + wikipic.icons.gnu + "' />" ;
					else if ( cn.match ( /^CC\b/i ) ) {
						h = "<img border=0 src='" + wikipic.icons.creative_commons + "' />";
						var h2 = '' ;
						if ( cn.match ( /\bBY\b/ ) ) h2 += "<img border=0 src='" + wikipic.icons.cc_by + "' />" ;
						if ( cn.match ( /\bSA\b/ ) ) h2 += "<img border=0 src='" + wikipic.icons.cc_sa + "' />" ;
						if ( h2 != '' ) h += "<br/>" + h2 ;
					}
					if ( h == '' ) {
						licenses.push ( "<tr><td></td><td><a " + link_fix + " target='_blank'>" + cn + "</a></td></tr>" ) ;
					} else {
						licenses.push ( "<tr><td style='text-align:center'><a " + link_fix + " target='_blank'>" + h + "</a></td><td>" + cn + "</td></tr>" ) ;
					}
				} else if ( is_useful ) {
					categories.push ( "<div><a " + link_fix + " target='_blank'>" + cn + "</a></div>" ) ;
				}
			} ) ;
		}
		
		// Generate HTML
		var h = '' ;
		
		var h2 = "<div style='float:right'><a href='#' onclick='wikipic.hide_description();return false'><img src='" + wikipic.icons.slideshow_close + "' style='width:16px' border=0 /></a></div>" ;
		
		h += "<table id='wikipic_slide_desc_table'>" ;
		h += "<tr><th>" + wikipic.i18n.author + "</th><td>" + h2 + author + "</td></tr>" ;
		h += "<tr><th>" + wikipic.i18n.date + "</th><td>" + date + "</td></tr>" ;
		h += "<tr><th>" + wikipic.i18n.filesize + "</th><td>" ;
		h += "<a target='_blank' onclick='wikipic.on_slideshow_button(\"pause\");wikipic.open_url(\"" + o.imageinfo[0].url + "\");return false' href='" + o.imageinfo[0].url + "'>" ;
		h += o.imageinfo[0].width + "&times;" + o.imageinfo[0].height + "px / " ;
		if ( o.imageinfo[0].size >= 1000000 ) {
			h += ( parseInt ( o.imageinfo[0].size / 1024 / 1024 * 10 ) / 10 ) + 'MB' ;
		} else if ( o.imageinfo[0].size >= 1000 ) {
			h += ( parseInt ( o.imageinfo[0].size / 1024 * 10 ) / 10 ) + 'KB' ;
		} else {
			h += o.imageinfo[0].size + 'byte' ;
		}
		h += "</a></td></tr>" ;

		h += "<tr><th colspan=2>" + wikipic.i18n.description + "</th></tr>" ;
		h += "<tr><td colspan=2><div>" + desc + "</div></td></tr>" ;

		if ( categories.length > 0 ) {
			h += "<tr><th colspan='2'>" + wikipic.i18n.categories + "</th></tr>" ;
			h += "<tr><td colspan='2'>" + categories.join('') + "</td></tr>" ;
		}

		if ( licenses.length > 0 ) {
			h += "<tr><th colspan='2'>" + wikipic.i18n.licenses + "</th></tr>" ;
			h += "<tr><td colspan='2'><table border=0 cellspacing=0 cellpadding=1>" + licenses.join('') + "</table></td></tr>" ;
		}

		if ( o.is_commons ) {
			var url = '//commons.wikimedia.org' ;
			var onclick_pause = " onclick='wikipic.on_slideshow_button(\"pause\");wikipic.open_url(\"" + url + "\");return true' " ;
			h += "<tr><td colspan=2>" ;
			h += "<table><tr><td>" ;
			h += "<a " + onclick_pause ;
			h += " href='" + url + "' target='_blank' title='" + wikipic.i18n.commons + "'><img border=0 src='" + wikipic.icons.commons + "' /></a>" ;
			h += "</td><td>" ;
			h += wikipic.i18n.hosted_on_commons.replace ( '{1}' , url ) ;
			h += "</td></tr></table>" ;
			h += "</td></tr>" ;
		}

		h += "</table>" ;
		
		h += "<br/>" ;
		h += "<a onclick='wikipic.on_slideshow_button(\"pause\");wikipic.open_url(\"" + o.imageinfo[0].descriptionurl + "\");return false' href='" + o.imageinfo[0].descriptionurl + "' target='_blank' " + onclick_pause + ">" + wikipic.i18n.open_file_description_page + "</a>" ;
		
		h = "<div class='wikipic_desc_html'>" + h + "</div>" ;
		
		if ( $('#'+desc_id).get(0) && wikipic.show_description ) {
			$('#'+desc_id).html ( h ) ;
		}

	} ,
	
	hide_description : function () {
		wikipic.show_description = false ;
		$('.wikipic_desc_html').fadeOut();
	} ,
	
	/* adds a file to the dialog */
	add_file : function ( title ) {
		if ( wikipic.mode == 'gallery' ) wikipic.add_file2gallery ( title ) ;
		if ( wikipic.mode == 'fullscreen' ) wikipic.add_file2fullscreen ( title ) ;
		if ( wikipic.mode == 'slideshow' ) wikipic.add_file2slideshow ( title ) ;
		if ( wikipic.mode == 'info' ) wikipic.add_file2slideshow ( title ) ;
	} ,
	
	add_file2fullscreen : function ( title ) {
		wikipic.add_file2slideshow ( title ) ;
	} ,

	add_file2slideshow : function ( title ) {
		var id = wikipic.files.length ;
		var o = { name : title } ;
		wikipic.files.push ( o ) ;
		
		var wsw = wikipic.slide_width ;
		var wsh = wikipic.slide_height ;
		
		if ( wikipic.mode == 'fullscreen' ) { // Round to nearest 100 in fullscreen mode
			wsw -= wsw % 100 ;
			wsh = Math.floor ( wsh / wikipic.slide_width * wsw ) ;
//			wsh -= wsh % 100 ;
		}
		
		var api = wikipic.api_local ; // Can always be local
		$.getJSON ( api , { 
			action : 'query' ,
			titles : 'File:'+title ,
			prop : 'imageinfo' ,
			iiprop : 'url|size' ,
			iiurlwidth : wsw ,
			iiurlheight : wsh ,
			format : 'json'
		} , function ( data ) {
			$.each ( data.query.pages , function ( k , v ) {
				if ( v.imageinfo[0].width <= wikipic.min_slideshow_image_size && v.imageinfo[0].height <= wikipic.min_slideshow_image_size ) return ;
				v.name = o.name ;
				v.id = id ;
				v.is_commons = v.imagerepository == 'shared' ;
				
				var use_real_image_factor = 1.2 ; // If the full image is only this much bigger, don't generate a thumbnail
				if ( wsw * use_real_image_factor >= v.imageinfo[0].width &&
					wsh * use_real_image_factor >= v.imageinfo[0].height ) { // Just use real image, no need for thumbnailing
					v.real_thumbheight = v.imageinfo[0].height ;
					v.real_thumburl = v.imageinfo[0].url ;
				} else {
					v.real_thumbheight = v.imageinfo[0].thumbheight ;
					v.real_thumburl = v.imageinfo[0].thumburl ;
				}
				
				
				wikipic.files[id] = v ;
				
				wikipic.precache_file_desc ( wikipic.files[id] ) ;
				
				if ( id == 0 ) wikipic.preload_slideshow_image ( 0 , true ) ;
			} ) ;
		} ) ;
	} ,
	
	first_slide_hack : function ( counter ) {
		if ( !$('#wikipic_slide_1').get(0).complete ) {
			$('#wikipic_slideshow_spinning').show() ;
			wikipic.slideshow_timer_is_on = true ;
			wikipic.slideshow_timer = setTimeout ( 'wikipic.first_slide_hack('+counter+')' , 250 ) ;
		} else {
			$('#wikipic_slideshow_spinning').hide() ;
			$('#wikipic_loading_first_slide').remove() ;
			wikipic.slideshow_timer_is_on = false ;
			wikipic.preload_slideshow_image ( counter , false ) ;
		}
	} ,
	
	wait_for_slideshow_image_to_load : function () {
		wikipic.slideshow_timer_is_on = true ;

		if ( !$('#wikipic_slide_preload').get(0).complete ) {
			wikipic.slideshow_timer = setTimeout ( 'wikipic.wait_for_slideshow_image_to_load()' , 250 ) ;
			return ;
		}

		$('#wikipic_slideshow_spinning').hide() ;
		
		var d = new Date() ;
		var timeDiff = d.getTime() - wikipic.start_time.getTime() ;
		if ( timeDiff < wikipic.slideshow_delay ) {
			wikipic.slideshow_timer = setTimeout ( 'wikipic.wait_for_slideshow_image_to_load()' , 250 ) ;
			return ;
		}
		
		wikipic.slideshow_timer_is_on = false ;
		wikipic.next_slide ( false ) ;
	} ,
	
	preload_slideshow_image : function ( id , is_first_slide ) {
		var o = wikipic.files[id] ;
		
		// Just in case the metadata hasn't loaded yet...
		if ( o.imageinfo === undefined ) {
			setTimeout ( 'wikipic.preload_slideshow_image('+id+','+is_first_slide+')' , 250 ) ;
			return ;
		}
//		$('#wikipic_slideshow_spinning').hide() ;
		$('#wikipic_slide_preload').remove() ;
		
		h = "<img id='wikipic_slide_preload' src='" + o.real_thumburl  + "' style='display:none' />" ;
		$('#wikipic_dialog_content').prepend ( h ) ;
		

		if ( is_first_slide ) {
			wikipic.next_slide ( true ) ;
		} else {
			wikipic.start_time = new Date() ;
			wikipic.slideshow_timer_is_on = true ;
			wikipic.wait_for_slideshow_image_to_load() ;
//			wikipic.slideshow_timer = setTimeout ( "wikipic.wait_for_slideshow_image_to_load()" , 250 ) ;
		}

	} ,
		
	add_file2gallery : function ( title ) {
		var id = wikipic.files.length ;
		var o = { name : title } ;
		wikipic.files.push ( o ) ;
		
		var api = wikipic.api_local ; // Can always be local
		$.getJSON ( api , { 
			action : 'query' ,
			titles : 'File:'+title ,
			prop : 'imageinfo' ,
			iiprop : 'url|size' ,
			iiurlwidth : wikipic.thumbsize*wikipic.thumb_zoom,
			iiurlheight : wikipic.thumbsize*wikipic.thumb_zoom ,
			format : 'json'
		} , function ( data ) {
			$.each ( data.query.pages , function ( k , v ) {
				v.name = o.name ;
				v.id = id ;
				wikipic.files[id] = v ;
				var h = wikipic.get_thumbnail ( v ) ;
				$('#wikipic_dialog_content').append ( h ) ;
				$('#wikipic_dialog').dialog('option', 'position', 'center');
			} ) ;
		} ) ;
	} ,
	
	/* creates small and zoomed thumbnail, hiding zoomed version by default */
	get_thumbnail : function ( o ) {
		var tw = Math.floor(parseInt(o.imageinfo[0].thumbwidth)/wikipic.thumb_zoom) ; // Normalized thumbnail width
		var th = Math.floor(parseInt(o.imageinfo[0].thumbheight)/wikipic.thumb_zoom) ; // Normalized thumbnail height

		var h = "" ;
		h += "<div class='wikipic_thumb' id='wikipic_thumb_" + o.id + "' style='" ;
		h += "width:" + (wikipic.thumbsize+4) + "px;height:" + (wikipic.thumbsize+4) + "px;"
		if ( tw < wikipic.thumbsize ) {
			var d1 = Math.floor ( ( wikipic.thumbsize - tw ) / 2 ) ;
			var d2 = wikipic.thumbsize - tw - d1 ;
			h += "padding-left:" + d1 + "px;padding-right:" + d2 + "px;" ;
		} else {
			var d1 = Math.floor ( ( wikipic.thumbsize - th ) / 2 ) ;
			var d2 = wikipic.thumbsize - th - d1 ;
			h += "padding-top:" + d1 + "px;padding-bottom:" + d2 + "px;" ;
		}
		h += "'>" ;

		h += "<img id='wikipic_small_thumb_img_" + o.id + "' src='" + o.imageinfo[0].thumburl + "' style='background-color:white;width:"+tw+"px;height:"+th+"px;margin:2px' border=0 " ;

		if ( wikipic.isTouchDevice() ) {
			h += " ontouchstart='wikipic.show_large_thumbnail(" + o.id + ")' " ;
		} else {
			h += " onmouseover='wikipic.show_large_thumbnail(" + o.id + ")' " ;
		}
		
		h += " />" ;
		h += "</div>" ;

		var h2 = '' ;
		h2 += "<div class='wikipic_large_thumb' id='wikipic_large_thumb_" + o.id + "' style='display:none;position:absolute;z-index:2;min-width:80px'" ;
		h2 += " onmouseout='wikipic.hide_large_thumbnail(" + o.id + ")' >" ;
		h2 += "<a href='" + o.imageinfo[0].descriptionurl + "' onclick='wikipic.open_url(\"" + o.imageinfo[0].descriptionurl + "\");return false'>" ;
		h2 += "<img src='" + o.imageinfo[0].thumburl + "'" ;
		if ( wikipic.zoom_factor != 1 ) h2 += " width='" + Math.floor ( o.imageinfo[0].thumbwidth*wikipic.zoom_factor ) + "px' " ;
		h2 += " />" ;
		h2 += "</a>" ;
		h2 += "<div style='max-width:" + o.imageinfo[0].thumbwidth + "px;margin-top:2px;'>" ;
		h2 += "<div class='wikipic_thumb_title_span'>" + o.name.replace(/\.[^.]+$/,'') + "</div>" ;
		h2 += "<div class='wikipic_thumb_meta_span'>(" + o.imageinfo[0].width + "&times;" + o.imageinfo[0].height + "px)</div>" ;
		h2 += "</div>" ;
		h2 += "</div>" ;
		$('#wikipic_dialog_content').prepend ( h2 ) ;

		return h ;
	} ,
	
	/* Calculates the position of a zoomed thumbnail and shows it */
	show_large_thumbnail : function ( id ) {
		$('.wikipic_large_thumb').fadeOut('fast') ;
		var off = $('#wikipic_small_thumb_img_'+id).position() ;
		var tw = parseInt ( $('#wikipic_small_thumb_img_'+id).width() ) ;
		var th = parseInt ( $('#wikipic_small_thumb_img_'+id).height() ) ;
		var w = parseInt ( wikipic.files[id].imageinfo[0].thumbwidth ) ;
		var h = parseInt ( wikipic.files[id].imageinfo[0].thumbheight ) ;
		var x = off.left - Math.floor ( ( w - tw ) / 2 ) ;
		var y = off.top - Math.floor ( ( h - th ) / 2 ) ;
		y -= 20 ; // Compensate for title and size - roughly...
		$('#wikipic_large_thumb_'+id).css ( { left : x , top : y } ) ;
		$('#wikipic_large_thumb_'+id).fadeIn ( 'fast' ) ;
	} ,

	/* hides a specific zoomed thumbnail */
	hide_large_thumbnail : function ( id ) {
		$('#wikipic_large_thumb_'+id).fadeOut ( 'fast' ) ;
	} ,
	
	/* adds a file to the candidate list, and increases its usage counter */
	add_candidate : function ( title ) {
		title = wikipic.remove_file_namespace ( title ) ;
		if ( title.replace(/ /g,'_') == wikipic.file.replace(/ /g,'_') ) return ; // Don't add the start image
		if ( wikipic.candidate_images[title] === undefined ) wikipic.candidate_images[title] = 1 ;
		else wikipic.candidate_images[title]++ ;
	} ,
	
	/* compares the type of two files by ending; allows for JPG/JPEG etc. */
	is_same_filetype : function ( f1 , f2 ) {
		var m1 = f1.match ( /\.[^.]+$/ ) ;
		var m2 = f2.match ( /\.[^.]+$/ ) ;
		if ( m1 == null || m2 == null ) return false ;
		m1 = m1[0].toUpperCase() ;
		m2 = m2[0].toUpperCase() ;
		m1 = m1.replace ( /JPEG/ , 'JPG' ) ;
		m2 = m2.replace ( /JPEG/ , 'JPG' ) ;
		return m1 == m2 ;
	} ,
	
	remove_file_namespace : function ( filename ) {
		return filename.replace ( /^[^:]+:/ , '' ) ;
	} ,
	
	myescape : function ( t ) {
		return t.replace ( "'" , '%27' ) . replace ( '"' , '%22' ) ;
	} ,
	
	randomSort : function (a,b) {
		return( parseInt( Math.random()*10 ) %2 );
	} ,
	
	open_url : function ( url ) {
		window.open(url,'_blank');
//		window.location = url ;
	} ,
	
	isTouchDevice : function () {
	    return "ontouchstart" in window;
	} ,

	the_end_of_the_object : '' // To avoid worrying about the final comma...

} ;


$( function() {
	wikipic.init () ;
});

if(typeof importStylesheetURI !== 'undefined') {
	importStylesheetURI('//www.mediawiki.org/w/index.php?title=User:Magnus_Manske/wikipic.css&action=raw&ctype=text/css');
}
mw.loader.load( ['jquery.ui'] ) ;