diff options
Diffstat (limited to 'www/wiki/extensions/Maps/resources/leaflet/jquery.leaflet.js')
-rw-r--r-- | www/wiki/extensions/Maps/resources/leaflet/jquery.leaflet.js | 567 |
1 files changed, 232 insertions, 335 deletions
diff --git a/www/wiki/extensions/Maps/resources/leaflet/jquery.leaflet.js b/www/wiki/extensions/Maps/resources/leaflet/jquery.leaflet.js index 3483ec3a..5012c766 100644 --- a/www/wiki/extensions/Maps/resources/leaflet/jquery.leaflet.js +++ b/www/wiki/extensions/Maps/resources/leaflet/jquery.leaflet.js @@ -4,423 +4,321 @@ * * @author Pavel Astakhov < pastakhov@yandex.ru > * @author Peter Grassberger < petertheone@gmail.com > + * @author Jeroen De Dauw */ -(function ($, mw, L, MQ) { - $.fn.leafletmaps = function ( options ) { - var _this = this; - this.map = null; - this.options = options; - this.markers = []; - this.markercluster = null; - var apikeys = mw.config.get('egMapsLeafletLayersApiKeys') ; - - /** - * array point of all map elements (markers, lines, polygons, etc.) - * for map fit - */ - this.points = []; - - /** - * Creates a new marker with the provided data and returns it. - * @param {Object} properties Contains the fields lat, lon, title, text and icon - * @return {L.Marker} - */ - this.createMarker = function (properties) { - this.points.push( new L.LatLng(properties.lat, properties.lon) ); - - var markerOptions = { - title:properties.title +(function ($, mw, L, maps, sm) { + + function getMapOptions(options) { + let mapOptions = {}; + if (options.minzoom !== false) mapOptions.minZoom = options.minzoom; + if (options.maxzoom !== false) mapOptions.maxZoom = options.maxzoom; + + if (options.fullscreen) { + mapOptions.fullscreenControl = true; + mapOptions.fullscreenControlOptions= { + position: 'topleft' }; + } - var marker = L.marker( [properties.lat, properties.lon], markerOptions ); - - if (properties.hasOwnProperty('icon') && properties.icon !== '') { - marker.setOpacity(0); - - var img = new Image(); - img.onload = function() { - var icon = new L.Icon({ - iconUrl: properties.icon, - iconSize: [ img.width, img.height ], - iconAnchor: [ img.width / 2, img.height ], - popupAnchor: [ -img.width % 2, -img.height*2/3 ] - }); - - marker.setIcon(icon); - marker.setOpacity(1); - }; - img.src = properties.icon; - } + mapOptions.scrollWheelZoom = options.scrollwheelzoom; - if( properties.hasOwnProperty('text') && properties.text.length > 0 ) { - marker.bindPopup( properties.text ); - } + if (options.static) { + mapOptions.scrollWheelZoom = false; + mapOptions.doubleClickZoom = false; + mapOptions.touchZoom = false; + mapOptions.boxZoom = false; + mapOptions.tap = false; + mapOptions.keyboard = false; + mapOptions.zoomControl = false; + mapOptions.dragging = false; + } - if ( options.copycoords ) { - marker.on( - 'contextmenu', - function( e ) { - prompt(mw.msg('maps-copycoords-prompt'), e.latlng.lat + ',' + e.latlng.lng); - } - ); - } - - return marker; - }; + return mapOptions; + } - /** - * Creates a new marker with the provided data, adds it to the map - * and returns it. - * @param {Object} properties Contains the fields lat, lon, title, text and icon - * @return {L.Marker} - */ - this.addMarker = function (properties) { - var marker = this.createMarker(properties); - if (!this.options.markercluster) { - marker.addTo( this.map ); - } - this.markers.push( marker ); - return marker; - }; + $.fn.leafletmaps = function ( options ) { + let _this = this; + _this.options = options; // needed by LeafletAjax.js - this.removeMarker = function (marker) { - this.map.removeLayer(marker); - this.points = []; - this.markers = this.markers.filter(function(object) { - return object !== marker; - }); - }; + this.setup = function() { + this.map = L.map( this.get(0), getMapOptions(options) ); + this.mapContent = maps.leaflet.FeatureBuilder.contentLayerFromOptions(options).addTo(this.map); - this.removeMarkers = function () { - if (this.markercluster) { - this.map.removeLayer(this.markercluster); - this.markercluster = null; - } - var map = this.map; - $.each(this.markers, function(index, marker) { - map.removeLayer(marker); - }); + this.hideLoadingMessage(); + this.addLayersAndOverlays(this.map); + this.centerAndZoomMap(); + this.bindClickTarget(); + this.applyResizable(); + this.bindAjaxEvents(); - this.points = []; - this.markers = []; + this.maybeAddEditButton(); }; - this.addLine = function (properties) { - var options = { - color: properties.strokeColor, - weight:properties.strokeWeight, - opacity:properties.strokeOpacity - }; + this.shouldLoadEditorJs = function() { + if ( options.geojson === '' || options.GeoJsonSource === null ) { + return false; + } - var latlngs = []; - for (var x = 0; x < properties.pos.length; x++) { - latlngs.push([properties.pos[x].lat, properties.pos[x].lon]); - this.points.push( new L.LatLng(properties.pos[x].lat, properties.pos[x].lon) ); + if (mw.config.get('wgCurRevisionId') !== mw.config.get('wgRevisionId')) { + return false; } - var line = L.polyline(latlngs, options).addTo(this.map); + return true; + }; - if( properties.hasOwnProperty('text') && properties.text.trim().length > 0 ) { - line.bindPopup( properties.text ); + this.maybeAddEditButton = function() { + if ( this.shouldLoadEditorJs() ) { + maps.api.canEditPage('GeoJson:' + options.GeoJsonSource).done( + function(canEdit) { + if (canEdit) { + _this.addEditButton(); + } + } + ); } }; - this.addPolygon = function (properties) { - properties.pos.forEach(function(position) { - _this.points.push( new L.LatLng(position.lat, position.lon) ); - }); + this.addEditButton = function() { + this.editButton = L.easyButton( + '<img src="' + mw.config.get('egMapsScriptPath') + 'resources/leaflet/images/edit-solid.svg">', + this.startEditMode, + mw.msg('maps-editor-edit-geojson') + ).addTo(this.map); + }; + + this.startEditMode = function() { + _this.removeEditButton(); + _this.mapContent.remove(); - var polygon = L.polygon( - properties.pos.map(function(position) { - return [position.lat, position.lon]; - }), - { - color: properties.strokeColor, - weight:properties.strokeWeight, - opacity:properties.strokeOpacity, - fillColor:properties.fillColor, - fillOpacity:properties.fillOpacity + maps.api.getLatestRevision('GeoJson:' + options.GeoJsonSource).done( + function(revision) { + if (revision.revid === options.GeoJsonRevisionId) { + _this.initializeEditor(options.geojson); + } + else { + _this.purgePage(); + _this.initializeEditor(JSON.parse(revision['*'])); + } } ); + }; - polygon.addTo(this.map); + this.initializeEditor = function(geoJson) { + let editor = _this.getEditor(); + editor.initialize(geoJson); - if( properties.hasOwnProperty('text') && properties.text.trim().length > 0 ) { - console.log(properties.text); - polygon.bindPopup( properties.text ); - } - }; + editor.onSaved(function() { + _this.purgePage(); - this.addCircle = function (properties) { - var circle = L.circle( - [properties.centre.lat, properties.centre.lon], - { - radius: properties.radius, - color: properties.strokeColor, - weight:properties.strokeWeight, - opacity:properties.strokeOpacity, - fillColor:properties.fillColor, - fillOpacity:properties.fillOpacity, - } - ).addTo(this.map); + editor.remove(); + options.geojson = editor.getLayer().toGeoJSON(); + _this.mapContent = maps.leaflet.FeatureBuilder.contentLayerFromOptions(options).addTo(_this.map); - this.points.push( new L.LatLng(properties.centre.lat, properties.centre.lon) ); + alert(mw.msg('maps-json-editor-changes-saved')); + _this.addEditButton(); + }); + }; - if( properties.hasOwnProperty('text') && properties.text.trim().length > 0 ) { - circle.bindPopup( properties.text ); + this.getEditor = function() { + if (!this.editor) { + this.editor = maps.leaflet.LeafletEditor( + _this.map, + new maps.MapSaver('GeoJson:' + options.GeoJsonSource) + ); } + + return this.editor; }; - this.addRectangle = function (properties) { - this.points.push( new L.LatLng(properties.sw.lat, properties.sw.lon) ); - this.points.push( new L.LatLng(properties.ne.lat, properties.ne.lon) ); + this.purgePage = function() { + new mw.Api().post({ + action: 'purge', + titles: mw.config.get( 'wgPageName' ) + }).then(function(response) { - var options = { - color: properties.strokeColor, - weight:properties.strokeWeight, - opacity:properties.strokeOpacity, - fillColor:properties.fillColor, - fillOpacity:properties.fillOpacity - }; + }); + }; - var bounds = [[properties.sw.lat, properties.sw.lon], [properties.ne.lat, properties.ne.lon]]; + this.removeEditButton = function() { + if (this.editButton) { + this.editButton.remove(); + this.editButton = null; + } + }; - var rectangle = L.rectangle( bounds, options ).addTo(this.map); + this.hideLoadingMessage = function() { + this.map.on( + 'load', + function() { + $(_this).find('div.maps-loading-message').hide(); + } + ); + }; - if( properties.hasOwnProperty('text') && properties.text.trim().length > 0 ) { - rectangle.bindPopup( properties.text ); + this.applyResizable = function() { + if (options.resizable) { + _this.resizable(); } }; - this.createMarkerCluster = function () { - if ( !options.markercluster ) { - return; - } - var markers = this.markers; - - var markercluster = new L.MarkerClusterGroup({ - maxClusterRadius: options.clustermaxradius, - disableClusteringAtZoom: options.clustermaxzoom + 1, - zoomToBoundsOnClick: options.clusterzoomonclick, - spiderfyOnMaxZoom: options.clusterspiderfy, - iconCreateFunction: function(cluster) { - var childCount = cluster.getChildCount(); - - var imagePath = mw.config.get( 'egMapsScriptPath' ) + '/resources/leaflet/cluster/'; - - var styles = [ - { - iconUrl: imagePath + 'm1.png', - iconSize: [53, 52] - }, - { - iconUrl: imagePath + 'm2.png', - iconSize: [56, 55] - }, - { - iconUrl: imagePath + 'm3.png', - iconSize: [66, 65] - }, - { - iconUrl: imagePath + 'm4.png', - iconSize: [78, 77] - }, - { - iconUrl: imagePath + 'm5.png', - iconSize: [90, 89] - } - ]; + // Caution: used by ajaxUpdateMarker + this.addMarker = function (properties) { + this.mapContent.markerLayer.addLayer(maps.leaflet.FeatureBuilder.createMarker(properties, options)); + }; - var index = 0; - var dv = childCount; - while (dv !== 0) { - dv = parseInt(dv / 10, 10); - index++; - } - var index = Math.min(index, styles.length); - index = Math.max(0, index - 1); - index = Math.min(styles.length - 1, index); - var style = styles[index]; - - return new L.divIcon({ - iconSize: style.iconSize, - className: '', - html: '<img style="' + - '" src="' + style.iconUrl + '" />' + - '<span style="' + - 'position: absolute; font-size: 11px; font-weight: bold; text-align: center; ' + - 'top: 0; left: 0; ' + - 'line-height: ' + style.iconSize[1] + 'px;' + - 'width: ' + style.iconSize[0] + 'px;' + - '">' + childCount + '</span>' - }); - } - }); - $.each(this.markers, function(index, marker) { - markercluster.addLayer(marker); - }); - if (this.markercluster) { - this.map.removeLayer(this.markercluster); - this.markercluster = null; - } - this.map.addLayer(markercluster); - this.markercluster = markercluster; + // Caution: used by ajaxUpdateMarker + this.removeMarkers = function () { + this.mapContent.markerLayer.clearLayers(); }; - this.addGeoJson = function(options) { - if (options.geojson !== '') { - var geoJson = options.geojson; - var geoJsonLayer = L.geoJSON( geoJson ).addTo( this.map ); + this.bindClickTarget = function() { + function newClickTargetUrl(latlng) { + return options.clicktarget + .replace( /%lat%/g, latlng.lat ) + .replace( /%long%/g, latlng.lng ); + } - this.points.push( geoJsonLayer.getBounds().getNorthEast() ); - this.points.push( geoJsonLayer.getBounds().getSouthWest() ); + if (options.clicktarget !== '') { + this.map.on( + 'click', + function(e) { + window.location.href = newClickTargetUrl(e.latlng); + } + ); } }; - this.setup = function () { - - var mapOptions = {}; - if (options.minzoom !== false ) mapOptions.minZoom = options.minzoom; - if (options.maxzoom !== false ) mapOptions.maxZoom = options.maxzoom; + this.isUserUsesDarkMode = function () { + return window.matchMedia( '(prefers-color-scheme: dark)' ).matches; + }; - if (options.enablefullscreen) { - mapOptions.fullscreenControl = true; - mapOptions.fullscreenControlOptions= { - position: 'topleft' - }; - } - - mapOptions.scrollWheelZoom = options.scrollwheelzoom; - - if (options.static) { - mapOptions.scrollWheelZoom = false; - mapOptions.doubleClickZoom = false; - mapOptions.touchZoom = false; - mapOptions.boxZoom = false; - mapOptions.tap = false; - mapOptions.keyboard = false; - mapOptions.zoomControl = false; - mapOptions.dragging = false; + this.getLayerNames = function () { + if ( this.isUserUsesDarkMode() ) { + return mw.config.get('egMapsLeafletLayersDark'); } - var map = L.map( this.get(0), mapOptions ).fitWorld(); - this.map = map; + return options.layers; + }; + + this.addLayers = function() { + let apiKeys = mw.config.get('egMapsLeafletLayersApiKeys'); + let layers = {}; - var layers = {}; - $.each(options.layers.reverse(), function(index, layerName) { + $.each( this.getLayerNames().reverse(), function(index, layerName) { var options = {} ; var providerName = layerName.split('.')[0] ; - if (apikeys.hasOwnProperty(providerName) && apikeys[providerName] !== '') { - options.apikey = apikeys[providerName] ; - } + if (apiKeys.hasOwnProperty(providerName) && apiKeys[providerName] !== '') { + options.apikey = apiKeys[providerName] ; + } if (layerName === 'MapQuestOpen') { - layers[layerName] = new MQ.TileLayer().addTo(map); + layers[layerName] = new window.MQ.TileLayer().addTo(_this.map); } else { - layers[layerName] = new L.tileLayer.provider(layerName,options).addTo(map); + layers[layerName] = new L.tileLayer.provider(layerName,options).addTo(_this.map); } }); - var overlaylayers = {}; - $.each(options.overlaylayers, function(index, overlaylayerName) { - overlaylayers[overlaylayerName] = new L.tileLayer.provider(overlaylayerName).addTo(_this.map); + return layers; + }; + + this.addOverlays = function() { + let overlays = {}; + + $.each(options.overlays, function(index, overlayName) { + overlays[overlayName] = new L.tileLayer.provider(overlayName).addTo(_this.map); }); - if (options.layers.length > 1) { - L.control.layers(layers, overlaylayers).addTo(map); - } + return overlays; + }; - if (options.resizable) { - //TODO: Fix moving map when resized - _this.resizable(); - } + this.addLayersAndOverlays = function() { + let layers = this.addLayers(); + let overlays = this.addOverlays(); - if (!options.locations) { - options.locations = []; + if (options.layers.length > 1 || options.overlays.length > 0) { + L.control.layers(layers, overlays).addTo(this.map); } + }; - // Add the markers. - for (var i = options.locations.length - 1; i >= 0; i--) { - this.addMarker(options.locations[i]); + this.bindAjaxEvents = function() { + if ( !options.ajaxquery || !options.ajaxcoordproperty ) { + return; } - // Add markercluster - if (options.markercluster) { - this.createMarkerCluster(); - } + let ajaxRequest = null; - // Add lines - if (options.lines) { - for (var i = 0; i < options.lines.length; i++) { - this.addLine(options.lines[i]); - } - } + this.map.on( 'dragend zoomend', function() { + let bounds = _this.map.getBounds(); - // Add polygons - if (options.polygons) { - for (var i = 0; i < options.polygons.length; i++) { - this.addPolygon(options.polygons[i]); - } - } + let query = sm.buildQueryString( + decodeURIComponent( options.ajaxquery.replace( /\+/g, ' ' ) ), + options.ajaxcoordproperty, + bounds.getNorthEast().lat, + bounds.getNorthEast().lng, + bounds.getSouthWest().lat, + bounds.getSouthWest().lng + ); - // Add circles - if (options.circles) { - for (var i = 0; i < options.circles.length; i++) { - this.addCircle(options.circles[i]); + if( ajaxRequest !== null ) { + ajaxRequest.abort(); } + + ajaxRequest = sm.ajaxUpdateMarker( _this, query, options.icon ).done( function() { + ajaxRequest = null; + } ); + } ); + }; + + this.centerAndZoomMap = function() { + this.map.fitWorld(); + this.fitContent(); + + if (options.zoom !== false) { + this.map.setZoom(options.zoom); } - // Add rectangles - if (options.rectangles) { - for (var i = 0; i < options.rectangles.length; i++) { - this.addRectangle(options.rectangles[i]); - } + if (options.centre !== false) { + this.map.setView( + new L.LatLng(options.centre.lat, options.centre.lon), + this.map.getZoom() + ); } + }; - this.addGeoJson(options); - - // Set map position (centre and zoom) - var centre; - if (options.centre === false) { - switch ( this.points.length ) { - case 0: - centre = new L.LatLng(0, 0); - break; - case 1: - centre = this.points[0]; - break; - default: - var bounds = new L.LatLngBounds( this.points ); - if (options.zoom === false) { - map.fitBounds( bounds ); - centre = false; - } else { - centre = bounds.getCenter(); - } - break; + this.fitContent = function() { + let bounds = this.mapContent.getBounds(); + + if (bounds.isValid()) { + if (bounds.getNorthEast().equals(bounds.getSouthWest())) { + this.map.setView( + bounds.getCenter(), + options.defzoom + ); + } + else { + this.map.fitBounds(bounds); } - this.points = []; - } else { - centre = new L.LatLng(options.centre.lat, options.centre.lon); - } - if(centre) { - map.setView( centre, options.zoom !== false ? options.zoom : options.defzoom ); } }; this.getDependencies = function ( options ) { var dependencies = []; - if (options.layers !== ['MapQuestOpen'] || options.overlaylayers.length > 0) { - dependencies.push( 'ext.maps.leaflet.providers' ); + + if (this.shouldLoadEditorJs()) { + dependencies.push( 'ext.maps.leaflet.editor' ); } - if (options.enablefullscreen) { + + if (options.fullscreen) { dependencies.push( 'ext.maps.leaflet.fullscreen' ); } + if (options.resizable) { dependencies.push( 'ext.maps.resizable' ); } - if (options.markercluster) { + + if (options.cluster) { dependencies.push( 'ext.maps.leaflet.markercluster' ); } + return dependencies; }; @@ -429,6 +327,5 @@ } ); return this; - }; -})(jQuery, window.mediaWiki, L, window.MQ); +})(window.jQuery, window.mediaWiki, window.L, window.maps, window.sm); |