summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Maps/resources/leaflet/FeatureBuilder.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/Maps/resources/leaflet/FeatureBuilder.js')
-rw-r--r--www/wiki/extensions/Maps/resources/leaflet/FeatureBuilder.js220
1 files changed, 220 insertions, 0 deletions
diff --git a/www/wiki/extensions/Maps/resources/leaflet/FeatureBuilder.js b/www/wiki/extensions/Maps/resources/leaflet/FeatureBuilder.js
new file mode 100644
index 00000000..fad0adae
--- /dev/null
+++ b/www/wiki/extensions/Maps/resources/leaflet/FeatureBuilder.js
@@ -0,0 +1,220 @@
+// Builds markers, polygons, etc from the options object (serialized data coming from PHP)
+(function($, mw) {
+ 'use strict';
+
+ /**
+ * Creates a new marker with the provided data and returns it.
+ * @param {Object} properties Contains the fields lat, lon, title, text and icon
+ * @param {Object} options Map options
+ * @return {L.Marker}
+ */
+ function createMarker(properties, options) {
+ let markerOptions = {
+ title:properties.title
+ };
+
+ let marker = L.marker( [properties.lat, properties.lon], markerOptions );
+
+ if (properties.hasOwnProperty('icon') && properties.icon !== '') {
+ marker.setOpacity(0);
+
+ let img = new Image();
+ img.onload = function() {
+ let 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;
+ }
+
+ if( properties.hasOwnProperty('text') && properties.text.length > 0 ) {
+ marker.bindPopup( properties.text );
+ }
+
+ if ( options.copycoords ) {
+ marker.on(
+ 'contextmenu',
+ function( e ) {
+ prompt(mw.msg('maps-copycoords-prompt'), e.latlng.lat + ',' + e.latlng.lng);
+ }
+ );
+ }
+
+ return marker;
+ }
+
+ function newLineFromProperties(properties) {
+ var latlngs = [];
+
+ for (var x = 0; x < properties.pos.length; x++) {
+ latlngs.push([properties.pos[x].lat, properties.pos[x].lon]);
+ }
+
+ let line = L.polyline(
+ latlngs,
+ {
+ color: properties.strokeColor,
+ weight: properties.strokeWeight,
+ opacity: properties.strokeOpacity
+ }
+ );
+
+ // TODO: maybe bind via feature group
+ if ( properties.hasOwnProperty('text') && properties.text.trim().length > 0 ) {
+ line.bindPopup( properties.text );
+ }
+
+ return line;
+ }
+
+ function newPolygonFromProperties(properties) {
+ let 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
+ }
+ );
+
+ if( properties.hasOwnProperty('text') && properties.text.trim().length > 0 ) {
+ polygon.bindPopup( properties.text );
+ }
+
+ return polygon;
+ }
+
+ function newCircleFromProperties(properties) {
+ let 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,
+ }
+ );
+
+ if( properties.hasOwnProperty('text') && properties.text.trim().length > 0 ) {
+ circle.bindPopup( properties.text );
+ }
+
+ return circle;
+ }
+
+ function newRectangleFromProperties(properties) {
+ let rectangle = L.rectangle(
+ [
+ [properties.sw.lat, properties.sw.lon],
+ [properties.ne.lat, properties.ne.lon]
+ ],
+ {
+ color: properties.strokeColor,
+ weight: properties.strokeWeight,
+ opacity: properties.strokeOpacity,
+ fillColor: properties.fillColor,
+ fillOpacity: properties.fillOpacity
+ }
+ );
+
+ if( properties.hasOwnProperty('text') && properties.text.trim().length > 0 ) {
+ rectangle.bindPopup( properties.text );
+ }
+
+ return rectangle;
+ }
+
+ /**
+ * Caution: mutates markerLayer
+ * @param {Object} options
+ * @param {L.LayerGroup} markerLayer
+ * @return {L.GeoJSON}
+ */
+ function newGeoJsonLayer(options, markerLayer) {
+ return L.geoJSON(
+ options.geojson,
+ {
+ style: function (feature) {
+ return maps.leaflet.GeoJson.simpleStyleToLeafletPathOptions(feature.properties);
+ },
+ pointToLayer: function(feature, latlng) {
+ markerLayer.addLayer(
+ createMarker(
+ {
+ lat: latlng.lat,
+ lon: latlng.lng,
+ title: feature.properties.title || '',
+ text: maps.leaflet.GeoJson.popupContentFromProperties(feature.properties),
+ icon: ''
+ },
+ options
+ )
+ );
+ },
+ onEachFeature: function (feature, layer) {
+ if (feature.geometry.type !== 'Point') {
+ let popupContent = maps.leaflet.GeoJson.popupContentFromProperties(feature.properties);
+ if (popupContent !== '') {
+ layer.bindPopup(popupContent);
+ }
+ }
+ }
+ }
+ );
+ }
+
+ function getMarkersAndShapes(options) {
+ let features = L.featureGroup();
+
+ $.each(options.lines, function(index, properties) {
+ features.addLayer(newLineFromProperties(properties));
+ });
+
+ $.each(options.polygons, function(index, properties) {
+ features.addLayer(newPolygonFromProperties(properties));
+ });
+
+ $.each(options.circles, function(index, properties) {
+ features.addLayer(newCircleFromProperties(properties));
+ });
+
+ $.each(options.rectangles, function(index, properties) {
+ features.addLayer(newRectangleFromProperties(properties));
+ });
+
+ let markers = options.cluster ? maps.leaflet.LeafletCluster.newLayer(options) : L.featureGroup();
+
+ features.addLayer(markers);
+ features.markerLayer = markers;
+
+ $.each(options.locations, function(index, properties) {
+ markers.addLayer(createMarker(properties, options));
+ });
+
+ if (options.geojson !== '') {
+ features.addLayer(newGeoJsonLayer(options, markers));
+ }
+
+ return features
+ }
+
+ if (!window.maps) {window.maps = {};}
+ if (!window.maps.leaflet) {window.maps.leaflet = {};}
+
+ window.maps.leaflet.FeatureBuilder = {
+ contentLayerFromOptions: getMarkersAndShapes,
+ createMarker: createMarker
+ };
+})(window.jQuery, window.mediaWiki);