diff options
Diffstat (limited to 'ishtar_common/static/gis/js')
| -rw-r--r-- | ishtar_common/static/gis/js/OLMapWidget.js | 246 | 
1 files changed, 246 insertions, 0 deletions
| diff --git a/ishtar_common/static/gis/js/OLMapWidget.js b/ishtar_common/static/gis/js/OLMapWidget.js new file mode 100644 index 000000000..7102b0bf8 --- /dev/null +++ b/ishtar_common/static/gis/js/OLMapWidget.js @@ -0,0 +1,246 @@ +/* global ol */ + +var GeometryTypeControl = function(opt_options) { +    'use strict'; +    // Map control to switch type when geometry type is unknown +    var options = opt_options || {}; + +    var element = document.createElement('div'); +    element.className = 'switch-type type-' + options.type + ' ol-control ol-unselectable'; +    if (options.active) { +        element.className += " type-active"; +    } + +    var self = this; +    var switchType = function(e) { +        e.preventDefault(); +        if (options.widget.currentGeometryType !== self) { +            options.widget.map.removeInteraction(options.widget.interactions.draw); +            options.widget.interactions.draw = new ol.interaction.Draw({ +                features: options.widget.featureCollection, +                type: options.type +            }); +            options.widget.map.addInteraction(options.widget.interactions.draw); +            var className = options.widget.currentGeometryType.element.className.replace(/ type-active/g, ''); +            options.widget.currentGeometryType.element.className = className; +            options.widget.currentGeometryType = self; +            element.className += " type-active"; +        } +    }; + +    element.addEventListener('click', switchType, false); +    element.addEventListener('touchstart', switchType, false); + +    ol.control.Control.call(this, { +        element: element +    }); +}; + +// custom Ishtar - inherits not available anymore on new ol +// ol.inherits(GeometryTypeControl, ol.control.Control); +var ol_ext_inherits = function(child, parent) { +  child.prototype = Object.create(parent.prototype); +  child.prototype.constructor = child; +}; +ol_ext_inherits(GeometryTypeControl, ol.control.Control); +// end custom Ishtar + + +// TODO: allow deleting individual features (#8972) +(function() { +    'use strict'; +    var jsonFormat = new ol.format.GeoJSON(); + +    function MapWidget(options) { +        this.map = null; +        this.interactions = {draw: null, modify: null}; +        this.typeChoices = false; +        this.ready = false; + +        // Default options +        this.options = { +            default_lat: 0, +            default_lon: 0, +            default_zoom: 12, +            is_collection: options.geom_name.indexOf('Multi') > -1 || options.geom_name.indexOf('Collection') > -1 +        }; + +        // Altering using user-provided options +        for (var property in options) { +            if (options.hasOwnProperty(property)) { +                this.options[property] = options[property]; +            } +        } +        if (!options.base_layer) { +            this.options.base_layer = new ol.layer.Tile({source: new ol.source.OSM()}); +        } + +        this.map = this.createMap(); +        this.featureCollection = new ol.Collection(); +        this.featureOverlay = new ol.layer.Vector({ +            map: this.map, +            source: new ol.source.Vector({ +                features: this.featureCollection, +                useSpatialIndex: false // improve performance +            }), +            updateWhileAnimating: true, // optional, for instant visual feedback +            updateWhileInteracting: true // optional, for instant visual feedback +        }); + +        // Populate and set handlers for the feature container +        var self = this; +        this.featureCollection.on('add', function(event) { +            var feature = event.element; +            feature.on('change', function() { +                self.serializeFeatures(); +            }); +            if (self.ready) { +                self.serializeFeatures(); +                if (!self.options.is_collection) { +                    self.disableDrawing(); // Only allow one feature at a time +                } +            } +        }); + +        var initial_value = document.getElementById(this.options.id).value; +        if (initial_value) { +            var features = jsonFormat.readFeatures('{"type": "Feature", "geometry": ' + initial_value + '}'); +            var extent = ol.extent.createEmpty(); +            features.forEach(function(feature) { +                this.featureOverlay.getSource().addFeature(feature); +                ol.extent.extend(extent, feature.getGeometry().getExtent()); +            }, this); +            // Center/zoom the map +            this.map.getView().fit(extent, {maxZoom: this.options.default_zoom}); +        } else { +            this.map.getView().setCenter(this.defaultCenter()); +        } +        this.createInteractions(); +        if (initial_value && !this.options.is_collection) { +            this.disableDrawing(); +        } +        this.ready = true; +    } + +    MapWidget.prototype.createMap = function() { +    	// custom Ishtar +    	var layers = [this.options.base_layer]; +    	if (this.options.layers) layers = this.options.layers; +    	var options = { +            target: this.options.map_id, +            layers: layers, +            view: new ol.View({ +                zoom: this.options.default_zoom +            }) +    	}; +    	if (this.options.controls) options["controls"] = this.options.controls; +    	// end custom Ishtar +        var map = new ol.Map(options); +        return map; +    }; + +    MapWidget.prototype.createInteractions = function() { +        // Initialize the modify interaction +        this.interactions.modify = new ol.interaction.Modify({ +            features: this.featureCollection, +            deleteCondition: function(event) { +                return ol.events.condition.shiftKeyOnly(event) && +                    ol.events.condition.singleClick(event); +            } +        }); + +        // Initialize the draw interaction +        var geomType = this.options.geom_name; +        if (geomType === "Unknown" || geomType === "GeometryCollection") { +            // Default to Point, but create icons to switch type +            geomType = "Point"; +            this.currentGeometryType = new GeometryTypeControl({widget: this, type: "Point", active: true}); +            this.map.addControl(this.currentGeometryType); +            this.map.addControl(new GeometryTypeControl({widget: this, type: "LineString", active: false})); +            this.map.addControl(new GeometryTypeControl({widget: this, type: "Polygon", active: false})); +            this.typeChoices = true; +        } +        this.interactions.draw = new ol.interaction.Draw({ +            features: this.featureCollection, +            type: geomType +        }); + +        this.map.addInteraction(this.interactions.draw); +        this.map.addInteraction(this.interactions.modify); +    }; + +    MapWidget.prototype.defaultCenter = function() { +        var center = [this.options.default_lon, this.options.default_lat]; +        if (this.options.map_srid) { +            return ol.proj.transform(center, 'EPSG:4326', this.map.getView().getProjection()); +        } +        return center; +    }; + +    MapWidget.prototype.enableDrawing = function() { +        this.interactions.draw.setActive(true); +        if (this.typeChoices) { +            // Show geometry type icons +            var divs = document.getElementsByClassName("switch-type"); +            for (var i = 0; i !== divs.length; i++) { +                divs[i].style.visibility = "visible"; +            } +        } +    }; + +    MapWidget.prototype.disableDrawing = function() { +        if (this.interactions.draw) { +            this.interactions.draw.setActive(false); +            if (this.typeChoices) { +                // Hide geometry type icons +                var divs = document.getElementsByClassName("switch-type"); +                for (var i = 0; i !== divs.length; i++) { +                    divs[i].style.visibility = "hidden"; +                } +            } +        } +    }; + +    MapWidget.prototype.clearFeatures = function() { +        this.featureCollection.clear(); +        // Empty textarea widget +        document.getElementById(this.options.id).value = ''; +        this.enableDrawing(); +    }; + +    MapWidget.prototype.serializeFeatures = function() { +        // Three use cases: GeometryCollection, multigeometries, and single geometry +        var geometry = null; +        var features = this.featureOverlay.getSource().getFeatures(); +        if (this.options.is_collection) { +            if (this.options.geom_name === "GeometryCollection") { +                var geometries = []; +                for (var i = 0; i < features.length; i++) { +                    geometries.push(features[i].getGeometry()); +                } +                geometry = new ol.geom.GeometryCollection(geometries); +            } else { +                geometry = features[0].getGeometry().clone(); +                for (var j = 1; j < features.length; j++) { +                    switch (geometry.getType()) { +                    case "MultiPoint": +                        geometry.appendPoint(features[j].getGeometry().getPoint(0)); +                        break; +                    case "MultiLineString": +                        geometry.appendLineString(features[j].getGeometry().getLineString(0)); +                        break; +                    case "MultiPolygon": +                        geometry.appendPolygon(features[j].getGeometry().getPolygon(0)); +                    } +                } +            } +        } else { +            if (features[0]) { +                geometry = features[0].getGeometry(); +            } +        } +        document.getElementById(this.options.id).value = jsonFormat.writeGeometry(geometry); +    }; + +    window.MapWidget = MapWidget; +})(); | 
