Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
//<nowiki> /*****************************************************************************  * mapTools v2.1, 2024-10-06  * Several map creation and supporting tools  * Original author: Roland Unger  * Support of desktop and mobile views  * Documentation: https://de.wikivoyage.org/wiki/Wikivoyage:Gadget-MapTools.js  * License: GPL-2.0+, CC-by-sa 3.0  ****************************************************************************/ /* eslint-disable mediawiki/class-doc */  ( function( $, mw ) { 	'use strict';  	var mapTools = function() {  		// technical constants 		const ver = '2024-10-06', 			maxZoomLevel = 19, 			defaultMaplinkZoomLevel = 17, 			defaultMapZoomLevel = 14,  			defaultProperties = { 				'stroke-width': 2, 				'fill-opacity': 0.5 			},  			indicatorSelector = '.voy-coord-indicator', 			indicatorCoordsSelector = '.voy-coords a', 			indicatorGlobeImgSrc = 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Earth_-_The_Noun_Project.svg/20px-Earth_-_The_Noun_Project.svg.png', 			indicatorMapContainerId = 'voy-topMap',  			fullScreenContainerId = 'voy-fullScreenMap',  			mapframeContainerSelector = '.mw-kartographer-container', 			mapframeMapSelector = '.mw-kartographer-map',  			markerSelector = '.vcard', // wrapper selector of a single marker or listing 			kartographerSelector = '.mw-kartographer-maplink', 			nameClass = 'listing-name', 			imageClass = 'listing-image',  			footCaptionSelector = '.oo-ui-windowManager-fullscreen .mw-kartographer-captionfoot', 			captionMarkerClass = 'voy-caption-marker', 			captionInverseMarkerClass = 'voy-caption-marker-invers',  			minervaPageActionsSelector = '.page-actions-menu #page-actions-edit',  			dataLat = 'data-lat', 			dataLon = 'data-lon', 			dataZoom = 'data-zoom', 			dataName = 'data-name', 			dataColor = 'data-color', 			dataSymbol = 'data-symbol', 			dataNumber = 'data-number', 			dataGroup = 'data-group-translated', // other wikis: 'data-type' 			dataDialog = 'data-dialog', 			dataHeight = 'data-height', 			dataOverlays = 'data-overlays', 			fallbackLang = 'en'; 		 		// strings depending on page content language 		const wikiStrings = { 			de: { 				defaultShow:      '["Maske","Track","Aktivität","Anderes","Anreise","Ausgehen","Aussicht","Besiedelt","Fehler","Gebiet","Gesundheit","Kaufen","Küche","Natur","Religion","Sehenswert","Unterkunft","aquamarinblau","cosmos","gold","hellgrün","orange","pflaumenblau","rot","silber","violett"]', 				defaultGroupName: 'Karte', 				mask:             'Maske', 				track:            'Track' 			}, 			en: { 				defaultShow:      '["mask","around","buy","city","do","drink","eat","go","listing","other","see","sleep","vicinity","view","black","blue","brown","chocolate","forestgreen","gold","gray","grey","lime","magenta","maroon","mediumaquamarine","navy","orange","plum","purple","red","royalblue","silver","steelblue","teal"]', 				defaultGroupName: 'map', 				mask:             'mask', 				track:            'track' 			}, 			es: { 				defaultShow:      '["máscara","sendero","área","beber","comer","comprar","dormir","error","habitadas","hacer","ir","otro","ver","vista","aguamarina","ciruela","cosmos","oro","lima","naranja","violeta","plata","rojo"]', 				defaultGroupName: 'mapa', 				mask:             'máscara', 				track:            'sendero' 			}, 			fr: { 				defaultShow:      '["aller","destination","diplomatie","loger","manger","sortir","ville","voir","mask","around","buy","city","do","drink","eat","go","listing","other","see","sleep","vicinity","view","black","blue","brown","chocolate","forestgreen","gold","gray","grey","lime","magenta","maroon","mediumaquamarine","navy","orange","plum","purple","red","royalblue","silver","steelblue","teal"]', 				defaultGroupName: 'carte', 				mask:             'mask', 				track:            'piste' 			}, 			it: { 				defaultShow:      '["mask","around","buy","city","do","drink","eat","go","listing","other","see","sleep","vicinity","view","black","blue","brown","chocolate","forestgreen","gold","gray","grey","lime","magenta","maroon","mediumaquamarine","navy","orange","plum","purple","red","royalblue","silver","steelblue","teal"]', 				defaultGroupName: 'mappa', 				mask:             'mask', 				track:            'traccia' 			} 		};  		// strings depending on user language 		const userStrings = { 			de: { 				closeButtonTitle:     'Schließen', 				indicatorActionLabel: 'Karte', 				indicatorButtonTitle: 'Klick öffnet oder schließt die Karte für $1', 				magnifyButtonTitle:   'Karte vergrößern', 				mapCenter:            'Kartenzentrum', 				mapOf:                'Karte von $1' 			}, 			en: { 				closeButtonTitle:     'Close', 				indicatorActionLabel: 'Map', 				indicatorButtonTitle: 'Click to open or close the map of $1', 				magnifyButtonTitle:   'Enlarge map', 				mapCenter:            'Map center', 				mapOf:                'Map of $1' 			}, 			es: { 				closeButtonTitle:     'Cerrar', 				indicatorActionLabel: 'Mapa', 				indicatorButtonTitle: 'Haga clic para abrir o cerrar el mapa de $1', 				magnifyButtonTitle:   'Aumentar mapa', 				mapCenter:            'Centro del mapa', 				mapOf:                'Mapa de $1' 			}, 			fr: { 				closeButtonTitle:     'Fermer', 				indicatorActionLabel: 'Carte', 				indicatorButtonTitle: 'Cliquez pour ouvrir ou fermer le carte de $1', 				magnifyButtonTitle:   'Agrandir la carte', 				mapCenter:            'Centre de la carte', 				mapOf:                'Carte de $1' 			}, 			it: { 				closeButtonTitle:     'Chiudi', 				indicatorActionLabel: 'Mappa', 				indicatorButtonTitle: 'Clicca per aprire o chiudere la mappa di $1', 				magnifyButtonTitle:   'Ingrandisci mappa', 				mapCenter:            'Centro mappa', 				mapOf:                'Mappa di $1' 			} 		};  		// internal use 		const $body = $( 'body' ), 			pageLang = mw.config.get( 'wgPageContentLanguage' ), 			userLang = mw.config.get( 'wgUserLanguage' ), 			pageTitle = mw.config.get( 'wgTitle' ), 			articlePath = mw.config.get( 'wgArticlePath' ), 			thumbPath = '//upload.wikimedia.org/wikipedia/commons/thumb/', 			scriptUrl = mw.format( 'https://wikivoyage.toolforge.org/w/data/$1-articles.js', pageLang ), 			isMinerva = mw.config.get( 'skin' ) === 'minerva'; // mobile view 		var defaultShowArray, 			messages = {};  		// storing GeoJSON data 		var data = {};  		// array of objects: { name: group.name, attribution: attributions } 		var groups = [];  		// copying translation strings to messages depending on chain languages 		function addMessages( strings, chain ) { 			for ( var i = chain.length - 1; i >= 0; i-- ) { 				if ( strings.hasOwnProperty( chain[ i ] ) ) { 					$.extend( messages, strings[ chain[ i ] ] ); 				} 			} 		}  		// copying translation strings to messages 		function setupMessages() { 			addMessages( wikiStrings, [ pageLang, fallbackLang ] ); 			const chain = ( userLang == pageLang ) ? [ pageLang, fallbackLang ] : 				[ userLang, pageLang, fallbackLang ]; 			addMessages( userStrings, chain ); 		}  		// creating a Kartographer map 		function createMap( id, center, zoom, caption, options, color, isInvers ) { 			mw.loader.using( [ 'ext.kartographer.box' ] ).then( function() { 				var $id = $( '#' + id ), 					group, i, j, layerOptions;  				// for simple full-screen map 				if ( !options.withDialog && options.isFullScreen ) { 					$body.css( { overflow: 'hidden' } ); 					$id.css( { position: 'fixed', height: '100%', width: '100%', 						top: 0, left: 0, 'z-index': 101 } ); // vector skin 				}			  				// creating base map  				// fortunately ext.kartographer.box is not validating the 				// GeoJSON against the GeoJSON+simplestyle schema 				// as it is done by maplink/mapframe tags 				// https://github.com/mapbox/simplestyle-spec/tree/master/1.1.0 				// see also: phabricator task T181604  				var kartoBox = require( 'ext.kartographer.box' ); 				var map = kartoBox.map( { 					container: $id[ 0 ], 					center: center, 					zoom: zoom, 					allowFullScreen: options.allowFullScreen, 					alwaysInteractive: true, 					captionText: caption, 					fullscreen: options.isFullScreen, 					featureType: options.featureType 				} ); 				// following line is necessary for proper loading of 				// map-dialog sidebar 				map.initView( center, zoom );  				// adding markers by group names to separate layers 				if ( options.withData && groups.length ) { 					for ( i = 0; i < options.show.length; i++ ) { 						for ( j = 0; j < groups.length; j++ ) { 							group = groups[ j ]; 							if ( group.name === options.show[ i ] ) { 								layerOptions = { name: group.name }; 								if ( group.attribution !== '' ) { 									layerOptions.attribution = group.attribution; 								} 								map.addGeoJSONLayer( data[ group.name ], layerOptions ); 								break; 							} 						} 					} 				}  				// adding dialog to full-screen map 				if ( options.withDialog ) { 					$id.addClass( 'mw-kartographer-mapDialog-map' ); 					mw.loader.using( 'ext.kartographer.dialog' ).done( function() { 						map.doWhenReady( function() { 							require( 'ext.kartographer.dialog' ).render( map ); 						} ); 					} ); 				} else { 					// adding Close control to non-full-screen map if required 					if ( options.withClose ) { 						var controls = $( '.leaflet-top.leaflet-right', $id ), 							control = $( '<div class="leaflet-bar leaflet-control-static leaflet-control"></div>' ) 							.append( $( '<a class="voy-icon-close"></a>', 									{ title: messages.closeButtonTitle, 									role: 'button', 'aria-disabled': 'false' } ) 								.click( function() { 									$id.remove(); 									if ( options.isFullScreen ) { 										$body.css( { overflow: 'auto' } ); 									} 								} ) 							); 						controls.prepend( control ); 					}  					// adding Nearby and Layers controls using Kartographer.js 					if ( options.withControls ) { 						mw.hook( 'wikipage.maps' ).fire( map ); 					}  				} 				map.doWhenReady( function() { 					// remove inert attribute 					$id.removeAttr( 'inert' );  					if ( color && options.withDialog ) { 						setTimeout( function() { 							var footCaption = $( footCaptionSelector ); 							if ( footCaption.length ) { 								var	captionArray = footCaption.text().split("​:"), 									classes = captionMarkerClass + 										( isInvers ? ' ' + captionInverseMarkerClass : '' ); 								footCaption.html( mw.format( '<span class="$1" style="background-color: $2">$3</span>$4', 									classes, color, captionArray[ 0 ], captionArray[ 1 ] || '' ) ); 							} 						}, 700); 					} 				} ); 			} ); 		}  		// creating GeoJSON data separated by group 		function singleDataset( color, symbol, title, lat, lon, description, group ) { 			group = group || messages.defaultGroupName; 			if ( !data.hasOwnProperty( group ) ) { 				data[ group ] = []; 			} 		 			data[ group ].push( { 				'type': 'Feature', 				properties: { 					'marker-color': color, 					'marker-size': 'medium', 					'marker-symbol': symbol ? symbol.toLowerCase() : symbol, 					title: title, 					description: description 				}, 				geometry: { 					'type': 'Point', 					coordinates: [ lon, lat ] 				} 			} ); 		}  		// Getting GeoJSON data sets from external sources (OSM, Commons) 		function getGeoJSON( obj ) { 			var promise, coordinates, feature, geometry, i, j, 				world = [ [ [ 3600, -180 ], [ 3600, 180 ], [ -3600, 180 ], [ -3600, -180 ], [ 3600, -180 ] ] ], 				properties = obj.properties; // for all but not for 'page'  			promise = $.ajax( { // instead of $.getJSON 				dataType: 'json',     			url: obj.url,     			timeout: 3000 			} ).then( function( geoJSON ) { 				switch ( obj.service ) { 					case 'page': 						if ( geoJSON.jsondata && geoJSON.jsondata.data ) { 							$.extend( obj, geoJSON.jsondata.data ); 						} 						break;  					case 'geomask': 						coordinates = world; 						for ( i = 0; i < geoJSON.features.length; i++ ) { 							geometry = geoJSON.features[ i ].geometry; 							if ( !geometry ) { 								continue; 							}  							// push only first polygon 							switch ( geometry.type ) { 								case 'Polygon': 									coordinates.push( geometry.coordinates[ 0 ] ); 									break; 								case 'MultiPolygon': 									for ( j = 0; j < geometry.coordinates.length; j++ ) { 										coordinates.push( geometry.coordinates[ j ][ 0 ] ); 									} 							} 						} 						obj.type = 'Feature'; 						obj.geometry = { type: 'Polygon', coordinates: coordinates }; 						if ( !properties ) { 							properties = defaultProperties; 						} 						if ( $.isEmptyObject( obj.properties ) ) { 							obj.properties = properties; 						} else { 							obj.properties = $.extend( {}, properties, obj.properties ); 						} 						break;  					case 'geoline': 					case 'geoshape': 						$.extend( obj, geoJSON );  						if ( properties ) { 							for ( i = 0; i < obj.features.length; i++ ) { 								feature = obj.features[ i ]; 								if ( $.isEmptyObject( feature.properties ) ) { 									feature.properties = properties; 								} else { 									feature.properties = 										$.extend( {}, properties, feature.properties ); 								} 							} 						} 				} 			}, function() { 				// failed. Do nothing. 			} );  			return promise; 		}  		// Creating attribution strings 		function getAttribution( obj ) { 			var uri = new mw.Uri( obj.url ), link = '';  			switch ( obj.service ) { 				case 'page': 					link = mw.msg( 'project-localized-name-commonswiki' ) + ': ' + 						'<a target="_blank" href="' + 						'//commons.wikimedia.org/wiki/Data:' + encodeURI( uri.query.title ) + 						'">' + uri.query.title + '</a>'; 					break;  				default: // other services 			} 			 			return link; 		}  		// getting Kartographer live data 		function getKartographerLiveData() { 			var group, i, obj, 				promiseArray = [], 				attributions, link;  			data = mw.config.get( 'wgKartographerLiveData' ); 			if ( data ) { 				groups = []; // start with empty global array 				for ( group in data ) { 					// ignoring empty groups 					if ( data[ group ].length ) { 						attributions = []; 						for ( i = 0; i < data[ group ].length; i++ ) { 							obj = data[ group ][ i ]; 							// expand external data 							if ( obj.type === 'ExternalData' && obj.url ) { 								promiseArray.push( getGeoJSON( obj ) ); 								link = getAttribution( obj ); 								if ( link !== '' ) { 									attributions.push( link ); 								} 							} 						} 						attributions = attributions.join( ', ' ); 						groups.push( { name: group, attribution: attributions } ); 					} 				} 			}  			// wait for getting all external data 			// regardless of failures, addMapTools() will be executed 			if ( typeof Promise !== 'undefined' ) { 				Promise.all( promiseArray ) 					.then( function() { 						addMapTools(); 					} ) 					// initialization also in case of failures 					// maybe external data are not shown 					.catch( function() { 						addMapTools(); 					} ); 			} else { 				addMapTools(); // for really old browsers 			} 		}  		// getting all vCard/listing and marker information from article 		function getPOIsFromArticle() { 			// initally try to get wgKartographerLiveData because of masks 			// no marker(s): mw.config.get( 'wgKartographerLiveData' ) returns null 			// no map(s): all group arrays like see, do, etc. are empty 			// see phabricator task T183770  			// no wgKartographerLiveData or empty arrays 			data = {}; 			var markers = $( markerSelector ); 			if ( !markers.length ) { 				return; 			}  			var clone, color, desc, group, image, lat, link, lon, symbol, 				$this, title, wikiLink;  			markers.each( function() { 				$this = $( this ); 				link = $( kartographerSelector, $this ).first(); 				if ( link.length ) { 					lat = link.attr( dataLat ); 					lon = link.attr( dataLon ); 					color = $this.attr( dataColor ); 					group = $this.attr( dataGroup );  					// check if only marker number and no HTML tag 					symbol = $this.attr( dataSymbol ); 					if ( symbol ) { 						if ( symbol.charAt( 0 ) === '-' ) { 							symbol = link.text(); 						}  						// getting title 						title = $( '.' + nameClass, $this ).first(); 						clone = title.clone(); 						$( '.image', clone ).remove(); // remove images from title 						wikiLink = $( 'a', clone ).first(); 						clone.remove(); 						title = ( wikiLink.length ) ? wikiLink[ 0 ].outerHTML : 							$this.attr( dataName );  						// putting image to description 						desc = ''; 						image = $( '.' + imageClass, $this ); 						if ( image.length ) { 							desc = image.html() 								// for mobile view: show image from noscript instead of placeholder 								.replace( '<noscript>', '' ).replace( '</noscript>', '' ); 						}  						// adding to GeoJSON data table 						singleDataset( color, symbol, title, lat, lon, desc, group ); 					} 				} 			} );  			groups = []; // start with empty array 			for ( group in data ) { 				groups.push( { name: group, attribution: '' } ); 			} 		}  		// returning zoom parameter string as a valid number 		function getZoom( s, defaultValue ) { 			var zoom = ( typeof s == 'string' ) ? parseInt( s ) : -1; 			if ( zoom < 0 || zoom > maxZoomLevel ) { 				return defaultValue || defaultMapZoomLevel; 			} 			return zoom; 		}  		function makeContainer( id ) { 			return $( '<div></div>', { id: id, role: 'dialog', 'data-ver': ver } ); 		}  		// displaying a map by clicking the geo-indicator button 		function indicatorMap() { 			var indicator = $( indicatorSelector ).first(); 			if ( !indicator.length ) { 				return; 			} 			$( indicatorCoordsSelector ).attr( 'target', '_blank' );  			var id = indicatorMapContainerId; 			var options = { 				withClose: true, 				withControls: true, 				withData: true, 				show: defaultShowArray, 				withDialog: false, 				allowFullScreen: true, 				isFullScreen: false, 				featureType: 'mapframe' 			};  			var zoom = getZoom( indicator.attr( dataZoom ) ), 				lat = indicator.attr( dataLat ), 				lon = indicator.attr( dataLon ), 				center = [ lat, lon ];			  			// no POIs --> show blue map-center marker 			if ( !groups.length ) { 				singleDataset( '#3366cc', '', messages.mapCenter, lat, lon, '', 					messages.defaultGroupName ); 				groups = [ { name: messages.defaultGroupName, attribution: '' } ]; 			}  			// add or modify indicator action buttons 			var mapTitle = mw.format( messages.mapOf, pageTitle ); 			if ( isMinerva ) { // mobile view 				// add indicator action button and event handler  				var indicatorImg = $( '<img>', { 					class: 'voy-indicator-img', 					src: indicatorGlobeImgSrc, 					width: '20', height: '20' 				} ); 				indicator = $( '<a>', { 						id: 'mw-indicator-i3-geo', 						title: mw.format( messages.indicatorButtonTitle, pageTitle ), 						class: 'mw-indicator', // cdx-button 						href: '#' 					} ) 					.css( { display: 'inline-block' } ) 					.append( indicatorImg ) 					.append( $( `<span>${messages.indicatorActionLabel}</span>` ) ); 				indicator = $( '<li>', { 						id: 'page-actions-i3-geo', 						class: 'page-actions-menu__list-item' 					} ) 					.append( indicator ) 					.click( function() {  						var container = $( '#' + id ); 						if ( container.length ) { 							container.remove(); 						} else { 							$( '#bodyContent' ).prepend( makeContainer( id ) ); 							createMap( id, center, zoom, mapTitle, options ); 						} 					} ); 				$( minervaPageActionsSelector ).after( indicator ); 			} else { // desktop views 				// replace indicator image and add an event handler  				$( indicatorSelector + ' .voy-map-globe-default' ) 					.css( { display: 'none' } ); 				$( indicatorSelector + ' .voy-map-globe-js' ) 					.css( { display: 'inline', cursor: 'pointer' } ) 					.attr( 'title', mw.format( messages.indicatorButtonTitle, pageTitle ) ) 					.click( function() { 						var container = $( '#' + id ); 						if ( container.length ) { 							container.remove(); 						} else { 							$( '#contentSub' ).after( makeContainer( id ) ); 							createMap( id, center, zoom, mapTitle, options ); 						} 					} ); 			} 		}  		// returning show parameter string as an array 		function getShow( s ) { 			return ( s ) ? JSON.parse( s ) : defaultShowArray; 		}  		// replace the Maplink links by MapTools to show Wikivoyage controls 		// see also: phabricator T180909 		function replaceMaplinks() { 			var links = $( kartographerSelector ); 			if ( !links.length ) { 				return; 			}  			var id = fullScreenContainerId; 			var options = { 				withClose: true, 				withControls: true, 				withData: true, 				show: null, 				withDialog: true, 				allowFullScreen: false, 				isFullScreen: true, 				featureType: 'maplink' 			};  			var center, color, isInvers, lat, lon, name, symbolText, target, wrapper, zoom, $this;  			links.each( function() { 				$this = $( this );  				$this.attr( 'href', '#' ) 					.css( { cursor: 'pointer', 'pointer-events': 'auto', 						'text-decoration': 'none' } );  				$this.click( function( event ) { 					event.stopImmediatePropagation(); 					event.preventDefault();  					// marker could contain an image -> closest 					target = $( event.target ).closest( kartographerSelector ); 					wrapper = target.closest( markerSelector );  					lat = target.attr( dataLat ); 					lon = target.attr( dataLon ); 					center = [ lat, lon ]; 					zoom = getZoom( target.attr( dataZoom ), defaultMaplinkZoomLevel );  					name = wrapper.attr( dataName ) || ''; 					symbolText = target.text(); 					if ( symbolText !== '' ) { 						color = wrapper.attr( dataColor ); 						isInvers = target.closest( '.listing-map-inverse' ).length; 					} 					if ( name === '' ) { 						name = symbolText; 					} else if ( name !== '' && symbolText !== '' ) { 						name = symbolText + '​: ' + name; 					}  					options.show = getShow( target.attr( dataOverlays ) );  					$body.append( makeContainer( id ) ); 					createMap( id, center, zoom, name, options, color, isInvers );  					return false; // don't follow the link 				} ); 			} ); 		}  		// adding a magnify button to Kartographer container 		function addMagnifyButton() { 			var maps = $( mapframeContainerSelector ); 			if ( !maps.length ) { 				return; 			}  			var id = fullScreenContainerId; 			var options = { 				withClose: true, 				withControls: true, 				withData: true, 				show: null, 				withDialog: true, 				allowFullScreen: false, 				isFullScreen: true, 				featureType: 'maplink' 			};  			var caption, center, height, link, map, name, target, $this, zoom, 				zoomIncr;  			maps.each( function() { 				$this = $( this );  				// no magnify button if zoom is already maxZoomLevel 				// not in frameless mode 				map = $( mapframeMapSelector, $this ).first(); 				caption = $( '.thumbcaption', $this ).first(); 				zoom = getZoom( map.attr( dataZoom ) ); 				if ( map.length && caption.length && zoom < maxZoomLevel ) { 					link = $( '<a class="internal"></a>' ) 						.css( { cursor: 'pointer' } ) 						.attr( 'title', messages.magnifyButtonTitle ) 						.click( function( event ) { 							target = $( event.target ); 							map = target.closest( mapframeContainerSelector ); 							caption = $( '.thumbcaption', map ).first(); 							name = caption.text();  							// getting initial position from data if lat or lon 							// or zoom are undefined 							map = $( mapframeMapSelector, map ).first(); 							center = [ map.attr( dataLat ), map.attr( dataLon ) ]; 							zoom = Number( map.attr( dataZoom ) ); 							if ( isNaN( zoom ) ) { 								zoom = undefined; 							} else { 								zoomIncr = 1; 								height = screen.height / map.attr( dataHeight ); 								if ( height > 4 ) { 									zoomIncr++; 								} 								if ( height > 8 ) { 									zoomIncr++; 								} 								zoom += zoomIncr; 								if ( zoom > maxZoomLevel ) { 									zoom = maxZoomLevel; 								} 							}  							options.show = getShow( map.attr( dataOverlays ) );  							$body.append( makeContainer( id ) ); 							createMap( id, center, zoom, name, options ); 						} ); 					caption.prepend( $( '<div class="magnify"></div>' ).append( link ) ); 				} 			} ); 		}  		// adding all tools 		// called by getKartographerLiveData() 		function addMapTools() { 			// groups array is set by getKartographerLiveData() 			// if groups array is empty try to get data from article 			if ( !groups.length ) { 				getPOIsFromArticle(); 			}  			addMagnifyButton(); 			indicatorMap(); 			replaceMaplinks(); 		}  		function init() { 			setupMessages(); 			defaultShowArray = JSON.parse( messages.defaultShow ), 			getKartographerLiveData(); // calling addMapTools() 		}  		return { init: init }; 	} ();  	$( mapTools.init );  } ( jQuery, mediaWiki ) );  //</nowiki>