/*
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>