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)
- Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
/* A tool based on the original code as stated below, that helps searching for POIs and creating dynamic maps. */ //<nowiki> /***************************************************************************** * mapTools v2.0, 2023-06-16 * 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() { // https://www.mediawiki.org/wiki/Help:Extension:Kartographer/Icons const wdMakiMap = { "Q39816": "mountain", "Q8502": "mountain", "Q46831": "mountain", "Q43501": "zoo", "Q515": "city", "Q532": "village", "Q3957": "town", "Q2983893": "city", // quarter "Q40080": "beach", "Q44782": "harbor", "Q8072": "volcano", "Q3848936": "park", // protected area "Q473972": "park", // protected landscape "Q46169": "park", // national park "Q22746": "park", // urban park "Q23397": "water", // lake "Q35509": "tunnel", "Q34038": "waterfall", "Q16970": "religious-christian", "Q33506": "museum", "Q5487333": "beer", // microbrewery "Q131734": "beer", // brewery "Q4989906": "monument", "Q179700": "monument", // statue "Q6017969": "viewpoint", "Q12323": "dam", "Q751876": "castle", "Q483110": "stadium", "Q1007870": "art-gallery", "Q2281788": "aquarium", "Q45782": "aquarium", "Q4421": "natural", // forest "Q4022": "water", // river "Q55490": "rail", // through station "Q55488": "rail", // railway station "Q1268865": "rail", // light rail "Q3914": "school", "Q23413": "castle", "Q11166728": "communications-tower", "Q1798641": "communications-tower", "Q22698": "park", "Q24354": "theatre", "Q1060829": "theatre", // concert hall "Q108325": "religious-christian", // church "Q317557": "religious-christian", // parish church "Q1129743": "religious-christian", // filial church "Q56242275": "religious-christian", // lutheran church "Q623525": "religious-christian", // rotunda "Q131681": "water", // reservoir "Q34627": "religious-jewish", // synagogue "Q47521": "water", // stream "Q2977": "place-of-worship", // cathedral "Q1802963": "home", // cathedral }; // technical constants const 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', articlesMapId = 'voy-articles-map', useArticlesMap = true, 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', 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' const maxPOIsPerRequest = 500; // 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: { articlesMapTitle: 'Übersicht der Wikivoyage-Artikel', 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: { articlesMapTitle: 'Summary of Wikivoyage articles', 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: { articlesMapTitle: 'Resumen de los artículos de Wikivoyage', 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: { articlesMapTitle: 'Résumé des articles de Wikivoyage', 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: { articlesMapTitle: 'Sommario degli articoli di Wikivoyage', 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 ver = '2023-03-29', $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 prune cluster library var pruneClusterLib; // storing GeoJSON data var data = {}; var wikidataResponse = null; var osmResponse = null; var mapHandle; // 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 = mw.loader.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 } ); mapHandle = map; // following line is necessary for proper loading of // map-dialog sidebar map.initView( center, zoom ); // the following property is used by Kartographer.js if ( options.enableNearby ) { map.nearbyEnabled = true; if ( options.toggleNearby ) { map.toggleNearby = true; } } // 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; } if (data !== null) map.addGeoJSONLayer( data[ group.name ], layerOptions ); break; } } } } getPOIsFromWD(map); getPOIsFromOSM(map); // 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() { map.on('click', function(e){ $("#query-radius-center")[0].value = e.latlng.lat.toFixed(5) + "," + e.latlng.lng.toFixed(5); }); var dragf = function() { var bounds = map.getBounds(); var center = map.getCenter(); var zoom = map.getZoom(); $("#mapframe-info")[0].textContent = "{{mapframe|" + center.lat.toFixed(5) + "|" + center.lng.toFixed(5) + "|zoom=" + zoom + "|width=" + $("#voy-topMap").width() + "|height=" + $("#voy-topMap").height() + "}}"; $("#mapframe-size")[0].textContent = " (size: " + (map.distance(bounds._southWest, bounds._northEast) / 1000).toFixed(1) + "km)"; $("#query-sw")[0].value = bounds._southWest.lat.toFixed(5) + ',' + bounds._southWest.lng.toFixed(5); $("#query-ne")[0].value = bounds._northEast.lat.toFixed(5) + ',' + bounds._northEast.lng.toFixed(5); limitMaxQuery(); }; map.on('zoomend', dragf); map.on('dragend', dragf); // 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 ] } } ); } function extractCoordinates(item) { if (item.location && item.location.datatype === "http://www.opengis.net/ont/geosparql#wktLiteral") { var match = item.location.value.match(/Point\(([^ ]+) ([^)]+)\)/); if (match && match.length === 3) { var lon = parseFloat(match[1].trim()); var lat = parseFloat(match[2].trim()); return [lon, lat]; } } return null; } function convertWDToGeoJSON(wd) { var geoJSON = { type: "FeatureCollection", features: [] }; var bindings = wd.results.bindings; for (var i = 0; i < bindings.length; i++) { var item = bindings[i]; var coordinates = extractCoordinates(item); var markerSymbol = ""; var typeid = ""; if (item.instanceOf.value) { typeid = item.instanceOf.value.split('/').reverse()[0]; if (typeid in wdMakiMap) markerSymbol = wdMakiMap[typeid]; } if (coordinates) { var title = item.placeLabel ? escapeHtml(item.placeLabel.value) : "Untitled"; var wdid = item.place.value.split('/').reverse()[0]; var lang = $("#wd-language")[0].value; var imgStr = ""; if (item.image) { var img = "", imgThumb = ""; img = escapeHtml(item.image.value); //imgThumb = img.replace("/commons/", "/commons/thumb/"); //imgThumb += "320px-" + imgThumb.split('/').reverse()[0]; imgThumb = img.replace("http://", "https://"); imgStr= "<a href=\"" + img + "\">" + "<img style=\"width: 100%\" src=\"" + imgThumb + "\" />" + "</a><br/> "; } var feature = { type: "Feature", geometry: { type: "Point", coordinates: coordinates }, properties: { 'marker-color': '#999999', 'marker-size': 'medium', "marker-symbol": markerSymbol, "articleName": item.articleTitle ? escapeHtml(item.articleTitle.value) : "", "wikidataID": wdid, "listingName": title, "instanceOf": typeid, title: "<a href=\"" + escapeHtml(item.place.value) + "\">" + title + " / " + wdid + "</a><br/> ", description: (item.placeDescription ? (escapeHtml(item.placeDescription.value) + "<br/>") : "") + (item.articleTitle ? ("<a href=\"https://" + lang + ".wikipedia.org/wiki/" + escapeHtml(item.articleTitle.value) + "\">:" + lang + ":" + escapeHtml(item.articleTitle.value) + "</a>") : "No description available") + " " + imgStr } }; geoJSON.features.push(feature); } } return geoJSON; } function convertOSMToGeoJSON(osm) { var geoJSON = { type: "FeatureCollection", features: [] }; var elements = osm.elements; for (var i = 0; i < elements.length; i++) { var item = elements[i]; var coordinates; if ('center' in item) { coordinates = [item.center.lon, item.center.lat]; } else { coordinates = [item.lon, item.lat]; } var markerSymbol = ""; if ('tourism' in item.tags && item.tags.tourism == 'viewpoint') { markerSymbol = 'viewpoint'; } else if ('tourism' in item.tags && item.tags.tourism == 'museum') { markerSymbol = 'museum'; } else if ('historic' in item.tags) { markerSymbol = item.tags.historic; } if (coordinates) { var title = 'name' in item.tags ? escapeHtml(item.tags.name) : ""; var feature = { type: "Feature", geometry: { type: "Point", coordinates: coordinates }, properties: { 'marker-color': '#9999ff', 'marker-size': 'medium', "marker-symbol": markerSymbol, title: title, "listingName": title, description: '{{listing | name=' + title + ' | lat=' + coordinates[1] + " | long=" + coordinates[0] + "}}<br/>" + '<div style="width: 250px; word-break: break-all">' + escapeHtml(JSON.stringify(item.tags)).replace(/(Q[0-9]*)/, "<a href=\"https://www.wikidata.org/wiki/$1\">$1</a>") + '</div>' } }; geoJSON.features.push(feature); } } return geoJSON; } function getAverageViews(lang, articleName) { var d = new Date(); d.setMonth(-1); d.setDate(1); var to = d.toISOString().split('T')[0].replaceAll('-', ''); d.setMonth(-6); var from = d.toISOString().split('T')[0].replaceAll('-', ''); var url = "https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/" + lang + ".wikipedia/all-access/all-agents/" + articleName + "/monthly/" + from + "/" + to; return $.ajax({ url: url, method: 'GET', dataType: 'json', }); } function retrieveWPViews(lang, geoJSONResult) { var promises = geoJSONResult.features.map(function(entry) { var articleName = entry.properties.articleName; if (articleName != "" && !articleName.includes('/')) return getAverageViews(lang, articleName) .then(function(data) { var views = data.items.map(function(item) {return item.views;}); var averageViews = views.length ? (views.reduce(function(a, b) {return (a + b);}) / views.length) : 0; averageViews = Math.ceil(averageViews); entry.properties.views = averageViews; }).catch(function(error) { entry.properties.views = -1;}); }); return promises; } function dumpListings(geoJSONResult) { if (!$('#maptool-listings').length) $('#' + indicatorMapContainerId).after('<div id="maptool-listings"></div>'); $('#maptool-listings').append('<table border="1"><thead><tr><th>ID</th><th>WP name</th><th>views</th><th>symbol</th><th>listing</th></tr></thead><tbody></tbody></table>'); var tbody = $('#maptool-listings > table > tbody').last()[0]; var lang = $("#wd-language")[0].value; // Clear existing content tbody.innerHTML = ''; if (geoJSONResult.features.length >= maxPOIsPerRequest) { var tr = document.createElement('tr'); tr.setAttribute("style", "background: red") tr.innerHTML = "<td colspan='5'>More than " + maxPOIsPerRequest + "POIs found, scale down your query</td>"; tbody.append(tr) } // Loop through items and create rows geoJSONResult.features.forEach(function(item) { var lName = "| name = " + item.properties.listingName; var lAltName = ""; if (item.properties.articleName && (item.properties.listingName != item.properties.articleName)) lAltName = " | alt = " + item.properties.articleName; var tr = document.createElement('tr'); var wparticle = ( item.properties.articleName ? ("<a href=\"https://" + lang + ".wikipedia.org/wiki/" + item.properties.articleName + "\">:" + lang + ":" + item.properties.articleName + "</a>") : "No title available"); var wdStr = ""; var coordsStr = ""; if (item.properties.wikidataID) wdStr = " | wikidata = " + item.properties.wikidataID; else coordsStr = " | lat=" + item.geometry.coordinates[1] + " | long=" + item.geometry.coordinates[0]; tr.innerHTML = "\ <td>" + item.properties.title + "</td>\ <td>" + wparticle + "</td>\ <td>" + (item.properties.views ? item.properties.views : "") + "</td>\ <td>" + item.properties['marker-symbol'] + " | <a href=\"https://www.wikidata.org/wiki/" + item.properties.instanceOf + "\">" + item.properties.instanceOf + "</a></td>\ <td>{{listing " + lName + lAltName + wdStr + coordsStr + "}}</td>"; tbody.appendChild(tr); }); } function addMarkerColors(geoJSONResult) { var redShade; var redFrom = 0xff; var redTo = 0x99; for (var i = 0; i < geoJSONResult.features.length; i++) { redShade = ~~((geoJSONResult.features.length - i) * (redFrom - redTo) / geoJSONResult.features.length) + redTo; var redShadeStr = redShade.toString(16); if (redShadeStr.length == 1) redShadeStr = "0" + redShadeStr; if (geoJSONResult.features[i].properties.views >= 0) geoJSONResult.features[i].properties['marker-color'] = '#' + redShadeStr + '9999'; } } function getPOIsFromOSM(map) { if (!osmResponse) return; var geoJSONResult = convertOSMToGeoJSON(osmResponse); map.addGeoJSONLayer(geoJSONResult, {name: "OSM items"}); if ($("#osm-enable")[0].checked) { dumpListings(geoJSONResult); } } function getWDGeoJSON(lat, lon) { function makeSPARQLQuery( endpointUrl, sparqlQuery ) { var settings = { headers: { Accept: 'application/sparql-results+json' }, data: { query: sparqlQuery } }; return $.ajax( endpointUrl, settings ); } var radius = $("#query-radius-km")[0].value; var lang = $("#wd-language")[0].value; var auxFilter = $("#wd-filter")[0].value; var wikirule = (lang !== "") ? "?article schema:about ?place . \ ?article schema:isPartOf <https://" + lang + ".wikipedia.org/>. \ ?article schema:name ?articleTitle ." : ""; if (lang === "") lang = "en"; if (!$("#wd-filter-religious")[0].checked) { auxFilter += " MINUS{?place wdt:P31/wdt:P279* wd:Q24398318} "; // religious building } if (!$("#wd-filter-settlements")[0].checked) { auxFilter += " MINUS{?place wdt:P31/wdt:P279? wd:Q486972} "; // human settlement auxFilter += " MINUS{?place wdt:P31/wdt:P279* wd:Q15284} "; // municipality auxFilter += " MINUS{?place wdt:P31/wdt:P279? wd:Q56061} "; // administrative division } var areaQuery; if ($("#query-radius")[0].checked) { areaQuery = "SERVICE wikibase:around { \ ?place wdt:P625 ?location . \ bd:serviceParam wikibase:center \"Point(" + String(lon) + "," + String(lat) + ")\"^^geo:wktLiteral . \ bd:serviceParam wikibase:radius \"" + String(radius) + "\" . \ }"; } else { var sw = $("#query-sw")[0].value.split(","); var ne = $("#query-ne")[0].value.split(","); areaQuery = "SERVICE wikibase:box { \ ?place wdt:P625 ?location . \ bd:serviceParam wikibase:cornerSouthWest \"Point(" + String(sw[1]) + "," + String(sw[0]) + ")\"^^geo:wktLiteral .\ bd:serviceParam wikibase:cornerNorthEast \"Point(" + String(ne[1]) + "," + String(ne[0]) + ")\"^^geo:wktLiteral .\ }"; } var endpointUrl = 'https://query.wikidata.org/sparql', sparqlQuery = "\n" + "\ SELECT DISTINCT ?place ?placeDescription ?placeLabel ?articleTitle \ \ (SAMPLE(?location) as ?location) \ (SAMPLE(?image) AS ?image)\ (SAMPLE(?instanceOf) AS ?instanceOf)\ \ WHERE {\ " + areaQuery + auxFilter + "\ SERVICE wikibase:label { bd:serviceParam wikibase:language \"en," + lang + "\". } \ ?place wdt:P18 ?image. \ ?place wdt:P31 ?instanceOf. \ " + wikirule + "\ } \ GROUP BY ?place ?placeDescription ?placeLabel ?articleTitle \ LIMIT " + maxPOIsPerRequest + " \ "; return makeSPARQLQuery( endpointUrl, sparqlQuery).then(function(data){wikidataResponse = data;}); } function getPOIsFromWD(map) { if (!wikidataResponse) return; var geoJSONResult = convertWDToGeoJSON(wikidataResponse); if ($("#wd-sort-views")[0].checked) { var lang = $("#wd-language")[0].value; var promises = retrieveWPViews(lang, geoJSONResult); Promise.all( promises ).then( function() { // Sort the table data by views in descending order geoJSONResult.features.sort(function (a, b) {return (b.properties.views || 0) - (a.properties.views || 0);}); addMarkerColors(geoJSONResult); map.addGeoJSONLayer(geoJSONResult, {name: "wikidata items"}); if ($("#wd-table")[0].checked) { dumpListings(geoJSONResult); } }); } else { map.addGeoJSONLayer(geoJSONResult, {name: "wikidata items"}); if ($("#wd-table")[0].checked) { dumpListings(geoJSONResult); } } } function getOSMGeoJSON(lat, lon) { function makeOSMQuery( endpointUrl, query ) { var settings = { headers: { Accept: 'application/json' }, data: { data: query } // encodeURIComponent(query) }; return $.ajax( endpointUrl, settings ); } var auxFilter = ""; var bbox, jsonreq; var nodeFilterBase, wayFilterBase; if ($("#query-radius")[0].checked) { var radius = $("#query-radius-km")[0].value; nodeFilterBase = "node(around:" + String(radius * 1000) + ", " + String(lat) + ", " + String(lon) + ")"; wayFilterBase = "way(around:" + String(radius * 1000) + ", " + String(lat) + ", " + String(lon) + ")"; bbox = ""; jsonreq = '[out:json];' } else { bbox = "[bbox:" + $("#query-sw")[0].value + "," + $("#query-ne")[0].value + "];"; jsonreq = '[out:json]' nodeFilterBase = "node"; wayFilterBase = "way"; } if ($("#osm-filter")[0].value != "") { var f = $("#osm-filter")[0].value; auxFilter += nodeFilterBase + f + ";"; auxFilter += wayFilterBase + f + ";"; } if ($("#osm-filter-historic")[0].checked) { auxFilter += nodeFilterBase + '["historic"~"."]["name"~"."];'; auxFilter += wayFilterBase + '["historic"~"."]["name"~"."];'; } if ($("#osm-filter-viewpoint")[0].checked) { auxFilter += nodeFilterBase + '["tourism"~"viewpoint"];'; auxFilter += wayFilterBase + '["tourism"~"viewpoint"];'; } if ($("#osm-filter-museum")[0].checked) { auxFilter += nodeFilterBase + '["tourism"~"museum"];'; auxFilter += wayFilterBase + '["tourism"~"museum"];'; } var endpointUrl = 'https://overpass-api.de/api/interpreter', overpassQuery = jsonreq + bbox + "( " + auxFilter + "); out " + maxPOIsPerRequest + " tags center;"; return makeOSMQuery( endpointUrl, overpassQuery).then(function(data){osmResponse = data;}); } // 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 && 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, style="height: 500px" ) { return $( '<div></div>', { id: id, role: 'dialog', 'data-ver': ver, style: style } ); } // 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 lat, lon, zoom, center; var coords = getArticleCoords(); lat = coords[0]; lon = coords[1]; zoom = coords[2]; // 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>', { src: indicatorGlobeImgSrc, width: '20', height: '20' } ); indicator = $( '<a>', { id: 'mw-indicator-i3-geo', title: mw.format( messages.indicatorButtonTitle, pageTitle ), class: 'mw-indicator', href: '#' } ) .css( { display: 'inline-block' } ) .append( indicatorImg ) .append( document.createTextNode( ' ' + messages.indicatorActionLabel ) ); indicator = $( '<li>', { id: 'page-actions-i3-geo', class: 'page-actions-menu__list-item' } ) .append( indicator ) .click( function() { if (mapHandle) { var oldcenter = mapHandle.getCenter(); center = [oldcenter.lat, oldcenter.lng] zoom = mapHandle.getZoom(); } var container = $( '#' + id ); if ( container.length ) { container.remove(); if ($("#maptool-listings").length != 0) $("#maptool-listings")[0].remove(); } { $( '#bodyContent' ).prepend( makeContainer( id ) ); $('#' + id).css("resize", ($("#wd-map-resizable")[0].checked ? "both" : "none")); var qcenter = $("#query-radius-center")[0].value.split(','); var qlat = parseFloat(qcenter[0]); var qlon = parseFloat(qcenter[1]); wikidataResponse = null; osmResponse = null; var promiseArray = []; if ($("#wd-enable")[0].checked) promiseArray.push(getWDGeoJSON(qlat, qlon)); if ($("#osm-enable")[0].checked) promiseArray.push(getOSMGeoJSON(qlat, qlon)); Promise.all( promiseArray ) .then( function() { createMap( id, center, zoom, mapTitle, options ); } ) } } ); $( '#page-actions #page-actions-edit' ).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 style = "height: 500px"; if (mapHandle) { var oldcenter = mapHandle.getCenter(); center = [oldcenter.lat, oldcenter.lng] zoom = mapHandle.getZoom(); style = "width: " + $("#" + id).width() + "px;" + "height: " + $("#" + id).height() + "px;"; } var container = $( '#' + id ); if ( container.length ) { container.remove(); if ($("#maptool-listings")) $("#maptool-listings")[0].remove(); } { $( '#contentSub' ).after( makeContainer( id, style ) ); $('#' + id).css("resize", ($("#wd-map-resizable")[0].checked ? "both" : "none")); var qcenter = $("#query-radius-center")[0].value.split(','); var qlat = parseFloat(qcenter[0]); var qlon = parseFloat(qcenter[1]); wikidataResponse = null; osmResponse = null; var promiseArray = []; if ($("#wd-enable")[0].checked) promiseArray.push(getWDGeoJSON(qlat, qlon)); if ($("#osm-enable")[0].checked) promiseArray.push(getOSMGeoJSON(qlat, qlon)); Promise.all( promiseArray ) .then( function() { 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 ) ); } } ); } // showing all articles on an earth map function articlesMap() { var map = $( '#' + articlesMapId ).first(); if ( !map.length ) { return; } var options = { withClose: false, withControls: true, withData: false, withDialog: false, isFullScreen: false, allowFullScreen: false, // because Nearby mode cannot be toggled in full-screen mode enableNearby: true, toggleNearby: true, featureType: 'mapframe' }; var zoom = Math.floor( map.height() / 500 ); if ( zoom < 0 ) { zoom = 0; } else if ( zoom > maxZoomLevel ) { zoom = maxZoomLevel; } createMap( articlesMapId, [ 0, 0 ], zoom, messages.articlesMapTitle, options ); } function togglePopup(id, childs) { var next = $(id).is(":hidden"); childs.push(id); childs.forEach(function (i) { if (next) {$(i).show();} else {$(i).hide();} }); } function escapeHtml(text) { var escapedText = { '&': '&a;', //'"': '&q;', // this should be fine, we don't do eval //'\'': '&s;', '<': '&l;', '>': '&g;', }; //return text.replace(/[&"'<>]/g, function(s) {return escapedText[s];}); return text.replace(/[&<>]/g, function(s) {return escapedText[s];}); } function getArticleCoords() { // try to use {{geo}} var zoom = 13; var lat = RLCONF['wgCoordinates']['lat']; var lon = RLCONF['wgCoordinates']['lon']; // override by first mapframe if ($('.mw-kartographer-map').length > 0) { var firstmap = $('.mw-kartographer-map')[0]; var v; v = firstmap.getAttribute('data-lat'); if (v != null) lat = v; v = firstmap.getAttribute('data-lon'); if (v != null) lon = v; v = firstmap.getAttribute('data-zoom'); if (v != null) zoom = v; } return [lat, lon, zoom]; } function getDistance(origin, destination) { // return distance in meters; we don't always have the leaflet map, so we resort to this... var lon1 = toRadian(origin[1]), lat1 = toRadian(origin[0]), lon2 = toRadian(destination[1]), lat2 = toRadian(destination[0]); var deltaLat = lat2 - lat1; var deltaLon = lon2 - lon1; var a = Math.pow(Math.sin(deltaLat/2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(deltaLon/2), 2); var c = 2 * Math.asin(Math.sqrt(a)); var EARTH_RADIUS = 6371; return c * EARTH_RADIUS * 1000; } function toRadian(degree) { return degree*Math.PI/180; } function limitMaxQuery() { var disabled = false; try { if ($("#query-radius")[0].checked) { disabled = $("#query-radius-km")[0].value > 100; } else{ var sw = $("#query-sw")[0].value.split(","); var ne = $("#query-ne")[0].value.split(","); var distance = getDistance(sw, ne); if (isNaN(distance) || distance > 200000) disabled = true; } } catch (e) { disabled = true; } $(".voy-map-globe-js").prop("disabled", disabled); } function addMainQueryDialog() { var maptoolStr=`\ <table id="maptool" style="display: none; border: 1px solid black; width: 100%;background-color: #eee;"><tbody>\ <tr><td colspan="2">Show:\ <input type="checkbox" id="wd-map" checked="" disabled title="Show map with the items.">\ <label for="wd-map">map</label>\ (<input type="checkbox" id="wd-map-resizable" title="Enable resize handle for the map">\ <label for="wd-map-resizable">resizable</label>) \ <input type="checkbox" id="wd-table" checked="" title="Show a table containing the found data. If Wikipedia language is specified, also the respective wikipedia articles in that language.">\ <label for="wd-table">table</label>\ | <a href="https://en.wikivoyage.org/wiki/Wikivoyage:Maptool">help</a> \ </td></tr>\ <tr><td colspan="2" style="border-bottom: 1px solid black"><b>Query area:</b>\ <br/><span style="white-space: nowrap"><input type="radio" id="query-radius" name="query-type" checked /><label for="query-radius">Radius/km:</label>\ <input type="text" id="query-radius-km" value="10" style="width: 5em; box-sizing: border-box" title="Radius." />, center:<input type="text" id="query-radius-center" style="width: 20em; box-sizing: border-box" title="map center (lat,long)" /></span>\ <br/><span style="white-space: nowrap"><input type="radio" id="query-area" name="query-type" /><label for="query-area">Area:</label>\ SW:<input type="text" id="query-sw" style="width: 20em; box-sizing: border-box" title="SW corner (lat,long)" />\ NE:<input type="text" id="query-ne" style="width: 20em; box-sizing: border-box" title="NE corner (lat,long)" /></span>\ </td></tr>\ <tr style="vertical-align: top;"><td id="wd-cfg" style="border-right: 1px solid #ccc; padding: 0.5em; width: 50%">\ <h3><input type="checkbox" id="wd-enable" checked><label for="wd-enable">Wikidata</label></h3>\ <label for="wd-language">Wikipedia language:</label><input type="text" id="wd-language" class="wd-input" value="en" style="width: 5em; box-sizing: border-box" title="Enter wikipedia language shortcut (two or three letters). If left empty, just wikidata items are searched, with or without wikipedia articles.">\ <br /><input type="checkbox" id="wd-sort-views" checked="" title="If checked AND wikipedia article is found (see above), the average number of views in the past months is retrieved, and used to sort the items (descending)."><label for="wd-sort-views">Sort by wikipedia viewcount</label>\ \ <br/><br/><div style="margin-left: 1em; margin-left: 1em; background: #dddddd; padding: 0.25em;">\ <b>Filters</b><br/><input type="checkbox" class="wd-input" id="wd-filter-religious" title="Show religious buildings"><label for="wd-filter-religious">religious</label>\ <br><input type="checkbox" class="wd-input" id="wd-filter-settlements" title="Show human settlements buildings"><label for="wd-filter-settlements">settlements</label>\ <br><label for="wd-filter">SPARQL:</label><input type="text" id="wd-filter" class="wd-input" value="MINUS{?place wdt:P31/wdt:P279* wd:Q3839081}" style="width: 100%;box-sizing: border-box" title="Filters wikidata using also this SPARQL query - make sure the syntax is correct, if not empty. The default/example filters out all disaster events."></div>\ </td><td id="osm-cfg" style="padding: 0.5em">\ <h3><input type="checkbox" id="osm-enable"><label for="osm-enable"> OpenStreetMap</label></h3>\ <div style="margin-left: 1em; margin-left: 1em; background: #dddddd; padding: 0.25em;">\ <b>Filters</b><br/><input type="checkbox" id="osm-filter-viewpoint" checked=""><label for="osm-filter-viewpoint">viewpoint</label>\ <br><input type="checkbox" id="osm-filter-historic" checked=""><label for="osm-filter-historic">historic</label>\ <br><input type="checkbox" id="osm-filter-museum" checked=""><label for="osm-filter-museum">museum</label>\ <br><label for="osm-filter">AUX:</label><input type="text" id="osm-filter" value="[\'tourism\'~\'attraction\']" style="width: 100%;box-sizing: border-box" title="Filters OSM also uing this tags - make sure the syntax is correct, if not empty.">\ </div>\ </td></tr>\ \ <tr><td class="voy-coord-indicator" style="background: white">\ <button class="voy-map-globe-js" style="display: inline; cursor: pointer;" title="Click to open or close the map of Ruzomberok">Query and show</button>\ <span id="mapframe-size"></span> \ </td><td id="mapframe-info" style="text-align: right; background: white"></td></tr>\ </tbody></table>\ `; function enableForm(chkbox) { chkbox.parent().parent().find('input').not(chkbox).prop( 'disabled', !$(chkbox).prop('checked') ); } if ('wgCoordinates' in RLCONF) { var coords = getArticleCoords(); $('.mw-indicators').prepend( '<span id="maptool-button"> \ <span style="display: inline; cursor: pointer;"> \ <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Wikidata-logo.svg/32px-Wikidata-logo.svg.png"/> \ </span></span>' ); $('#maptool-button').click( function() {togglePopup('#maptool', ['#maptool-listings', '#voy-topMap']);}); $("#contentSub").append(maptoolStr); $("#query-radius-center")[0].value = coords[0] + "," + coords[1]; $("#wd-map-resizable").change(function() { $("#voy-topMap").css("resize", (this.checked ? "both" : "none"));}); enableForm($('#osm-enable')) $('#osm-enable').change(function() { enableForm($(this)); }); enableForm($('#wd-enable')) $('#wd-enable').change(function() { enableForm($(this)); }); $('#query-radius').change(function() { limitMaxQuery(); }); $('#query-radius-km').change(function() { limitMaxQuery(); }); $('#query-area').change(function() { limitMaxQuery(); }); $('#query-sw').change(function() { limitMaxQuery(); }); $('#query-ne').change(function() { limitMaxQuery(); }); } } // 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(); } addMainQueryDialog(); //addMagnifyButton(); indicatorMap(); //replaceMaplinks(); //if ( useArticlesMap ) { // articlesMap(); //} } function init() { setupMessages(); defaultShowArray = JSON.parse( messages.defaultShow ), getKartographerLiveData(); // calling addMapTools() } return { init: init }; } (); $( mapTools.init ); } ( jQuery, mediaWiki ) ); //</nowiki>