Created
July 17, 2017 08:56
-
-
Save aleecan/cd2bd5bd6a6b22853beb64cc90720f80 to your computer and use it in GitHub Desktop.
OpenStreetMap Application
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <project version="4"> | |
| <component name="CompilerConfiguration"> | |
| <resourceExtensions /> | |
| <wildcardResourcePatterns> | |
| <entry name="!?*.java" /> | |
| <entry name="!?*.form" /> | |
| <entry name="!?*.class" /> | |
| <entry name="!?*.groovy" /> | |
| <entry name="!?*.scala" /> | |
| <entry name="!?*.flex" /> | |
| <entry name="!?*.kt" /> | |
| <entry name="!?*.clj" /> | |
| <entry name="!?*.aj" /> | |
| </wildcardResourcePatterns> | |
| <annotationProcessing> | |
| <profile default="true" name="Default" enabled="false"> | |
| <processorPath useClasspath="true" /> | |
| </profile> | |
| </annotationProcessing> | |
| </component> | |
| </project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <component name="CopyrightManager"> | |
| <settings default="" /> | |
| </component> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <module type="JAVA_MODULE" version="4"> | |
| <component name="NewModuleRootManager" inherit-compiler-output="true"> | |
| <exclude-output /> | |
| <content url="file://$MODULE_DIR$" /> | |
| <orderEntry type="inheritedJdk" /> | |
| <orderEntry type="sourceFolder" forTests="false" /> | |
| </component> | |
| </module> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <project version="4"> | |
| <component name="MavenImportPreferences"> | |
| <option name="generalSettings"> | |
| <MavenGeneralSettings> | |
| <option name="mavenHome" value="Bundled (Maven 3)" /> | |
| </MavenGeneralSettings> | |
| </option> | |
| </component> | |
| <component name="ProjectLevelVcsManager" settingsEditedManually="false"> | |
| <OptionsSetting value="true" id="Add" /> | |
| <OptionsSetting value="true" id="Remove" /> | |
| <OptionsSetting value="true" id="Checkout" /> | |
| <OptionsSetting value="true" id="Update" /> | |
| <OptionsSetting value="true" id="Status" /> | |
| <OptionsSetting value="true" id="Edit" /> | |
| <ConfirmationsSetting value="0" id="Add" /> | |
| <ConfirmationsSetting value="0" id="Remove" /> | |
| </component> | |
| <component name="ProjectRootManager" version="2" languageLevel="JDK_1_3" default="true" assert-keyword="false" jdk-15="false" /> | |
| </project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <project version="4"> | |
| <component name="ProjectModuleManager"> | |
| <modules> | |
| <module fileurl="file://$PROJECT_DIR$/.idea/Map.iml" filepath="$PROJECT_DIR$/.idea/Map.iml" /> | |
| </modules> | |
| </component> | |
| </project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html ng-app="demoapp"> | |
| <head> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script> | |
| <script src="leaflet/leaflet.js"></script> | |
| <script src="leaflet/angular-leaflet-directive.js"></script> | |
| <link rel="stylesheet" href="leaflet/leaflet.css" /> | |
| <link rel="stylesheet" type="text/css" href="src/leaflet-search.css"> | |
| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous"> | |
| <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script> | |
| <script> | |
| var app = angular.module("demoapp", ["leaflet-directive"]); | |
| app.controller('MarkersSimpleController', function($scope, $http) { | |
| var res=""; | |
| var mainMarker = { | |
| lat: 51, | |
| lng: 0, | |
| focus: true, | |
| message: "Drag it learn Weather ", | |
| draggable: true | |
| }; | |
| angular.extend($scope, { | |
| london: { | |
| lat: 51.505, | |
| lng: -0.09, | |
| zoom: 8 | |
| }, | |
| markers: { | |
| mainMarker: angular.copy(mainMarker) | |
| }, | |
| position: { | |
| lat: 51, | |
| lng: 0 | |
| }, | |
| events: { // or just {} //all events | |
| markers:{ | |
| enable: [ 'dragend' ] | |
| //logic: 'emit' | |
| } | |
| } | |
| }); | |
| $scope.$on("leafletDirectiveMarker.dragend", function(event, args){ | |
| $scope.position.lat = args.model.lat; | |
| $scope.position.lng = args.model.lng; | |
| var str1 = "http://api.openweathermap.org/data/2.5/forecast?lat="; | |
| var str2 =args.model.lat; | |
| var str3 = "&lon="; | |
| var str4 = args.model.lng; | |
| var str5 = "&appid=56652672db6e996ee84dc5615e92f718"; | |
| res = str1.concat(str2, str3 , str4 , str5); | |
| //document.location = res; | |
| $scope.al(); | |
| }); | |
| $scope.al=function(){ | |
| /*var islem = $http({ | |
| method: "get", | |
| url: "http://cksyazilim.xyz/andro/topics.php" | |
| }); | |
| islem.success(function (data) { | |
| $scope.personeller=data; | |
| }); | |
| */ | |
| //console.log(res); | |
| $http.get(res). | |
| then(function(response) { | |
| $scope.weather=response.data.list; | |
| $scope.city = response.data.city; | |
| console.log("list", $scope.weather); | |
| }, function(response) { | |
| // called asynchronously if an error occurs | |
| // or server returns response with an error status. | |
| }); | |
| } | |
| //$scope.al(); | |
| }); | |
| </script> | |
| </head> | |
| <body ng-controller="MarkersSimpleController"> | |
| <!-- <leaflet lf-center="london" markers="markers" height="480px" width="100%"></leaflet> EVENTS WILL STILL FIRE but all will for each directive--> | |
| <!-- NOTICE events attribute is optional it is more for options in whitelisting (enable), blacklisting (disable), and logic (emit or broadcast) --> | |
| <leaflet lf-center="london" event-broadcast="events" markers="markers" height="480px" width="100%"></leaflet> | |
| <div class="form-group row"> | |
| <label for="example-text-input" class="col-2 col-form-label">City</label> | |
| <div class="col-10"> | |
| <input class="form-control" type="text" value="Artisanal kale" id="example-text-input" ng-model="city.name"> | |
| </div> | |
| </div> | |
| <table class="table"> | |
| <!--<input type="number" step="1" ng-model="satirSayisi" max="20" min="0" /> --> | |
| <thead class="thead-inverse"> | |
| <tr> | |
| <th>Temp </th> | |
| <th> Cloud Rate </th> | |
| <th> Date&Time </th> | |
| <th> Pressure </th> | |
| <th> Temp_Max</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr ng-repeat="today in weather"> | |
| <td>{{today.main.temp - 273 | number:0}}</td> | |
| <td>{{"%" + today.clouds.all}}</td> | |
| <td>{{today.dt_txt}}</td> | |
| <td> {{today.main.pressure}}</td> | |
| <td>{{today.main.temp_max - 273 | number:0}}</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </p> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /**! | |
| * The MIT License | |
| * | |
| * Copyright (c) 2013 the angular-leaflet-directive Team, http://tombatossals.github.io/angular-leaflet-directive | |
| * | |
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| * of this software and associated documentation files (the "Software"), to deal | |
| * in the Software without restriction, including without limitation the rights | |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| * copies of the Software, and to permit persons to whom the Software is | |
| * furnished to do so, subject to the following conditions: | |
| * | |
| * The above copyright notice and this permission notice shall be included in | |
| * all copies or substantial portions of the Software. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| * THE SOFTWARE. | |
| * | |
| * angular-leaflet-directive | |
| * https://github.com/tombatossals/angular-leaflet-directive | |
| * | |
| * @authors https://github.com/tombatossals/angular-leaflet-directive/graphs/contributors | |
| */ | |
| /*! | |
| * angular-leaflet-directive 2015-11-06 | |
| * angular-leaflet-directive - An AngularJS directive to easily interact with Leaflet maps | |
| * git: https://github.com/tombatossals/angular-leaflet-directive | |
| */ | |
| (function(angular){ | |
| 'use strict'; | |
| angular.module('leaflet-directive', []).directive('leaflet', ["$q", "leafletData", "leafletMapDefaults", "leafletHelpers", "leafletMapEvents", function($q, leafletData, leafletMapDefaults, leafletHelpers, leafletMapEvents) { | |
| return { | |
| restrict: 'EA', | |
| replace: true, | |
| scope: { | |
| center: '=', | |
| lfCenter: '=', | |
| defaults: '=', | |
| maxbounds: '=', | |
| bounds: '=', | |
| markers: '=', | |
| legend: '=', | |
| geojson: '=', | |
| paths: '=', | |
| tiles: '=', | |
| layers: '=', | |
| controls: '=', | |
| decorations: '=', | |
| eventBroadcast: '=', | |
| markersWatchOptions: '=', | |
| geojsonWatchOptions: '=', | |
| }, | |
| transclude: true, | |
| template: '<div class="angular-leaflet-map"><div ng-transclude></div></div>', | |
| controller: ["$scope", function($scope) { | |
| this._leafletMap = $q.defer(); | |
| this.getMap = function() { | |
| return this._leafletMap.promise; | |
| }; | |
| this.getLeafletScope = function() { | |
| return $scope; | |
| }; | |
| }], | |
| link: function(scope, element, attrs, ctrl) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var defaults = leafletMapDefaults.setDefaults(scope.defaults, attrs.id); | |
| var mapEvents = leafletMapEvents.getAvailableMapEvents(); | |
| var addEvents = leafletMapEvents.addEvents; | |
| scope.mapId = attrs.id; | |
| leafletData.setDirectiveControls({}, attrs.id); | |
| // Set width and height utility functions | |
| function updateWidth() { | |
| if (isNaN(attrs.width)) { | |
| element.css('width', attrs.width); | |
| } else { | |
| element.css('width', attrs.width + 'px'); | |
| } | |
| } | |
| function updateHeight() { | |
| if (isNaN(attrs.height)) { | |
| element.css('height', attrs.height); | |
| } else { | |
| element.css('height', attrs.height + 'px'); | |
| } | |
| } | |
| // If the width attribute defined update css | |
| // Then watch if bound property changes and update css | |
| if (isDefined(attrs.width)) { | |
| updateWidth(); | |
| scope.$watch( | |
| function() { | |
| return element[0].getAttribute('width'); | |
| }, | |
| function() { | |
| updateWidth(); | |
| map.invalidateSize(); | |
| }); | |
| } | |
| // If the height attribute defined update css | |
| // Then watch if bound property changes and update css | |
| if (isDefined(attrs.height)) { | |
| updateHeight(); | |
| scope.$watch( | |
| function() { | |
| return element[0].getAttribute('height'); | |
| }, | |
| function() { | |
| updateHeight(); | |
| map.invalidateSize(); | |
| }); | |
| } | |
| // Create the Leaflet Map Object with the options | |
| var map = new L.Map(element[0], leafletMapDefaults.getMapCreationDefaults(attrs.id)); | |
| ctrl._leafletMap.resolve(map); | |
| if (!isDefined(attrs.center) && !isDefined(attrs.lfCenter)) { | |
| map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); | |
| } | |
| // If no layers nor tiles defined, set the default tileLayer | |
| if (!isDefined(attrs.tiles) && (!isDefined(attrs.layers))) { | |
| var tileLayerObj = L.tileLayer(defaults.tileLayer, defaults.tileLayerOptions); | |
| tileLayerObj.addTo(map); | |
| leafletData.setTiles(tileLayerObj, attrs.id); | |
| } | |
| // Set zoom control configuration | |
| if (isDefined(map.zoomControl) && | |
| isDefined(defaults.zoomControlPosition)) { | |
| map.zoomControl.setPosition(defaults.zoomControlPosition); | |
| } | |
| if (isDefined(map.zoomControl) && defaults.zoomControl === false) { | |
| map.zoomControl.removeFrom(map); | |
| } | |
| if (isDefined(map.zoomsliderControl) && | |
| isDefined(defaults.zoomsliderControl) && | |
| defaults.zoomsliderControl === false) { | |
| map.zoomsliderControl.removeFrom(map); | |
| } | |
| // if no event-broadcast attribute, all events are broadcasted | |
| if (!isDefined(attrs.eventBroadcast)) { | |
| var logic = 'broadcast'; | |
| addEvents(map, mapEvents, 'eventName', scope, logic); | |
| } | |
| // Resolve the map object to the promises | |
| map.whenReady(function() { | |
| leafletData.setMap(map, attrs.id); | |
| }); | |
| scope.$on('$destroy', function() { | |
| leafletMapDefaults.reset(); | |
| map.remove(); | |
| leafletData.unresolveMap(attrs.id); | |
| }); | |
| //Handle request to invalidate the map size | |
| //Up scope using $scope.$emit('invalidateSize') | |
| //Down scope using $scope.$broadcast('invalidateSize') | |
| scope.$on('invalidateSize', function() { | |
| map.invalidateSize(); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').factory('leafletBoundsHelpers', ["$log", "leafletHelpers", function($log, leafletHelpers) { | |
| var isArray = leafletHelpers.isArray; | |
| var isNumber = leafletHelpers.isNumber; | |
| var isFunction = leafletHelpers.isFunction; | |
| var isDefined = leafletHelpers.isDefined; | |
| function _isValidBounds(bounds) { | |
| return angular.isDefined(bounds) && angular.isDefined(bounds.southWest) && | |
| angular.isDefined(bounds.northEast) && angular.isNumber(bounds.southWest.lat) && | |
| angular.isNumber(bounds.southWest.lng) && angular.isNumber(bounds.northEast.lat) && | |
| angular.isNumber(bounds.northEast.lng); | |
| } | |
| return { | |
| createLeafletBounds: function(bounds) { | |
| if (_isValidBounds(bounds)) { | |
| return L.latLngBounds([bounds.southWest.lat, bounds.southWest.lng], | |
| [bounds.northEast.lat, bounds.northEast.lng]); | |
| } | |
| }, | |
| isValidBounds: _isValidBounds, | |
| createBoundsFromArray: function(boundsArray) { | |
| if (!(isArray(boundsArray) && boundsArray.length === 2 && | |
| isArray(boundsArray[0]) && isArray(boundsArray[1]) && | |
| boundsArray[0].length === 2 && boundsArray[1].length === 2 && | |
| isNumber(boundsArray[0][0]) && isNumber(boundsArray[0][1]) && | |
| isNumber(boundsArray[1][0]) && isNumber(boundsArray[1][1]))) { | |
| $log.error('[AngularJS - Leaflet] The bounds array is not valid.'); | |
| return; | |
| } | |
| return { | |
| northEast: { | |
| lat: boundsArray[0][0], | |
| lng: boundsArray[0][1], | |
| }, | |
| southWest: { | |
| lat: boundsArray[1][0], | |
| lng: boundsArray[1][1], | |
| }, | |
| }; | |
| }, | |
| createBoundsFromLeaflet: function(lfBounds) { | |
| if (!(isDefined(lfBounds) && isFunction(lfBounds.getNorthEast) && isFunction(lfBounds.getSouthWest))) { | |
| $log.error('[AngularJS - Leaflet] The leaflet bounds is not valid object.'); | |
| return; | |
| } | |
| var northEast = lfBounds.getNorthEast(); | |
| var southWest = lfBounds.getSouthWest(); | |
| return { | |
| northEast: { | |
| lat: northEast.lat, | |
| lng: northEast.lng, | |
| }, | |
| southWest: { | |
| lat: southWest.lat, | |
| lng: southWest.lng, | |
| }, | |
| }; | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').factory('leafletControlHelpers', ["$rootScope", "$log", "leafletHelpers", "leafletLayerHelpers", "leafletMapDefaults", function($rootScope, $log, leafletHelpers, leafletLayerHelpers, leafletMapDefaults) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var isObject = leafletHelpers.isObject; | |
| var createLayer = leafletLayerHelpers.createLayer; | |
| var _controls = {}; | |
| var errorHeader = leafletHelpers.errorHeader + ' [Controls] '; | |
| var _controlLayersMustBeVisible = function(baselayers, overlays, mapId) { | |
| var defaults = leafletMapDefaults.getDefaults(mapId); | |
| if (!defaults.controls.layers.visible) { | |
| return false; | |
| } | |
| var atLeastOneControlItemMustBeShown = false; | |
| if (isObject(baselayers)) { | |
| Object.keys(baselayers).forEach(function(key) { | |
| var layer = baselayers[key]; | |
| if (!isDefined(layer.layerOptions) || layer.layerOptions.showOnSelector !== false) { | |
| atLeastOneControlItemMustBeShown = true; | |
| } | |
| }); | |
| } | |
| if (isObject(overlays)) { | |
| Object.keys(overlays).forEach(function(key) { | |
| var layer = overlays[key]; | |
| if (!isDefined(layer.layerParams) || layer.layerParams.showOnSelector !== false) { | |
| atLeastOneControlItemMustBeShown = true; | |
| } | |
| }); | |
| } | |
| return atLeastOneControlItemMustBeShown; | |
| }; | |
| var _createLayersControl = function(mapId) { | |
| var defaults = leafletMapDefaults.getDefaults(mapId); | |
| var controlOptions = { | |
| collapsed: defaults.controls.layers.collapsed, | |
| position: defaults.controls.layers.position, | |
| autoZIndex: false, | |
| }; | |
| angular.extend(controlOptions, defaults.controls.layers.options); | |
| var control; | |
| if (defaults.controls.layers && isDefined(defaults.controls.layers.control)) { | |
| control = defaults.controls.layers.control.apply(this, [[], [], controlOptions]); | |
| } else { | |
| control = new L.control.layers([], [], controlOptions); | |
| } | |
| return control; | |
| }; | |
| var controlTypes = { | |
| draw: { | |
| isPluginLoaded: function() { | |
| if (!angular.isDefined(L.Control.Draw)) { | |
| $log.error(errorHeader + ' Draw plugin is not loaded.'); | |
| return false; | |
| } | |
| return true; | |
| }, | |
| checkValidParams: function(/* params */) { | |
| return true; | |
| }, | |
| createControl: function(params) { | |
| return new L.Control.Draw(params); | |
| }, | |
| }, | |
| scale: { | |
| isPluginLoaded: function() { | |
| return true; | |
| }, | |
| checkValidParams: function(/* params */) { | |
| return true; | |
| }, | |
| createControl: function(params) { | |
| return new L.control.scale(params); | |
| }, | |
| }, | |
| fullscreen: { | |
| isPluginLoaded: function() { | |
| if (!angular.isDefined(L.Control.Fullscreen)) { | |
| $log.error(errorHeader + ' Fullscreen plugin is not loaded.'); | |
| return false; | |
| } | |
| return true; | |
| }, | |
| checkValidParams: function(/* params */) { | |
| return true; | |
| }, | |
| createControl: function(params) { | |
| return new L.Control.Fullscreen(params); | |
| }, | |
| }, | |
| search: { | |
| isPluginLoaded: function() { | |
| if (!angular.isDefined(L.Control.Search)) { | |
| $log.error(errorHeader + ' Search plugin is not loaded.'); | |
| return false; | |
| } | |
| return true; | |
| }, | |
| checkValidParams: function(/* params */) { | |
| return true; | |
| }, | |
| createControl: function(params) { | |
| return new L.Control.Search(params); | |
| }, | |
| }, | |
| custom: {}, | |
| minimap: { | |
| isPluginLoaded: function() { | |
| if (!angular.isDefined(L.Control.MiniMap)) { | |
| $log.error(errorHeader + ' Minimap plugin is not loaded.'); | |
| return false; | |
| } | |
| return true; | |
| }, | |
| checkValidParams: function(params) { | |
| if (!isDefined(params.layer)) { | |
| $log.warn(errorHeader + ' minimap "layer" option should be defined.'); | |
| return false; | |
| } | |
| return true; | |
| }, | |
| createControl: function(params) { | |
| var layer = createLayer(params.layer); | |
| if (!isDefined(layer)) { | |
| $log.warn(errorHeader + ' minimap control "layer" could not be created.'); | |
| return; | |
| } | |
| return new L.Control.MiniMap(layer, params); | |
| }, | |
| }, | |
| }; | |
| return { | |
| layersControlMustBeVisible: _controlLayersMustBeVisible, | |
| isValidControlType: function(type) { | |
| return Object.keys(controlTypes).indexOf(type) !== -1; | |
| }, | |
| createControl: function(type, params) { | |
| if (!controlTypes[type].checkValidParams(params)) { | |
| return; | |
| } | |
| return controlTypes[type].createControl(params); | |
| }, | |
| updateLayersControl: function(map, mapId, loaded, baselayers, overlays, leafletLayers) { | |
| var i; | |
| var _layersControl = _controls[mapId]; | |
| var mustBeLoaded = _controlLayersMustBeVisible(baselayers, overlays, mapId); | |
| if (isDefined(_layersControl) && loaded) { | |
| for (i in leafletLayers.baselayers) { | |
| _layersControl.removeLayer(leafletLayers.baselayers[i]); | |
| } | |
| for (i in leafletLayers.overlays) { | |
| _layersControl.removeLayer(leafletLayers.overlays[i]); | |
| } | |
| map.removeControl(_layersControl); | |
| delete _controls[mapId]; | |
| } | |
| if (mustBeLoaded) { | |
| _layersControl = _createLayersControl(mapId); | |
| _controls[mapId] = _layersControl; | |
| for (i in baselayers) { | |
| var hideOnSelector = isDefined(baselayers[i].layerOptions) && | |
| baselayers[i].layerOptions.showOnSelector === false; | |
| if (!hideOnSelector && isDefined(leafletLayers.baselayers[i])) { | |
| _layersControl.addBaseLayer(leafletLayers.baselayers[i], baselayers[i].name); | |
| } | |
| } | |
| for (i in overlays) { | |
| var hideOverlayOnSelector = isDefined(overlays[i].layerParams) && | |
| overlays[i].layerParams.showOnSelector === false; | |
| if (!hideOverlayOnSelector && isDefined(leafletLayers.overlays[i])) { | |
| _layersControl.addOverlay(leafletLayers.overlays[i], overlays[i].name); | |
| } | |
| } | |
| map.addControl(_layersControl); | |
| } | |
| return mustBeLoaded; | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').service('leafletData', ["$log", "$q", "leafletHelpers", function($log, $q, leafletHelpers) { | |
| var getDefer = leafletHelpers.getDefer, | |
| getUnresolvedDefer = leafletHelpers.getUnresolvedDefer, | |
| setResolvedDefer = leafletHelpers.setResolvedDefer; | |
| var _private = {}; | |
| var self = this; | |
| var upperFirst = function(string) { | |
| return string.charAt(0).toUpperCase() + string.slice(1); | |
| }; | |
| var _privateItems = [ | |
| 'map', | |
| 'tiles', | |
| 'layers', | |
| 'paths', | |
| 'markers', | |
| 'geoJSON', | |
| 'UTFGrid', //odd ball on naming convention keeping to not break | |
| 'decorations', | |
| 'directiveControls',]; | |
| //init | |
| _privateItems.forEach(function(itemName) { | |
| _private[itemName] = {}; | |
| }); | |
| this.unresolveMap = function(scopeId) { | |
| var id = leafletHelpers.obtainEffectiveMapId(_private.map, scopeId); | |
| _privateItems.forEach(function(itemName) { | |
| _private[itemName][id] = undefined; | |
| }); | |
| }; | |
| //int repetitive stuff (get and sets) | |
| _privateItems.forEach(function(itemName) { | |
| var name = upperFirst(itemName); | |
| self['set' + name] = function(lObject, scopeId) { | |
| var defer = getUnresolvedDefer(_private[itemName], scopeId); | |
| defer.resolve(lObject); | |
| setResolvedDefer(_private[itemName], scopeId); | |
| }; | |
| self['get' + name] = function(scopeId) { | |
| var defer = getDefer(_private[itemName], scopeId); | |
| return defer.promise; | |
| }; | |
| }); | |
| }]); | |
| angular.module('leaflet-directive') | |
| .service('leafletDirectiveControlsHelpers', ["$log", "leafletData", "leafletHelpers", function($log, leafletData, leafletHelpers) { | |
| var _isDefined = leafletHelpers.isDefined; | |
| var _isString = leafletHelpers.isString; | |
| var _isObject = leafletHelpers.isObject; | |
| var _mainErrorHeader = leafletHelpers.errorHeader; | |
| var _errorHeader = _mainErrorHeader + '[leafletDirectiveControlsHelpers'; | |
| var _extend = function(id, thingToAddName, createFn, cleanFn) { | |
| var _fnHeader = _errorHeader + '.extend] '; | |
| var extender = {}; | |
| if (!_isDefined(thingToAddName)) { | |
| $log.error(_fnHeader + 'thingToAddName cannot be undefined'); | |
| return; | |
| } | |
| if (_isString(thingToAddName) && _isDefined(createFn) && _isDefined(cleanFn)) { | |
| extender[thingToAddName] = { | |
| create: createFn, | |
| clean: cleanFn, | |
| }; | |
| } else if (_isObject(thingToAddName) && !_isDefined(createFn) && !_isDefined(cleanFn)) { | |
| extender = thingToAddName; | |
| } else { | |
| $log.error(_fnHeader + 'incorrect arguments'); | |
| return; | |
| } | |
| //add external control to create / destroy markers without a watch | |
| leafletData.getDirectiveControls().then(function(controls) { | |
| angular.extend(controls, extender); | |
| leafletData.setDirectiveControls(controls, id); | |
| }); | |
| }; | |
| return { | |
| extend: _extend, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive') | |
| .service('leafletGeoJsonHelpers', ["leafletHelpers", "leafletIterators", function(leafletHelpers, leafletIterators) { | |
| var lHlp = leafletHelpers; | |
| var lIt = leafletIterators; | |
| var Point = function(lat, lng) { | |
| this.lat = lat; | |
| this.lng = lng; | |
| return this; | |
| }; | |
| var _getLat = function(value) { | |
| if (Array.isArray(value) && value.length === 2) { | |
| return value[1]; | |
| } else if (lHlp.isDefined(value.type) && value.type === 'Point') { | |
| return +value.coordinates[1]; | |
| } else { | |
| return +value.lat; | |
| } | |
| }; | |
| var _getLng = function(value) { | |
| if (Array.isArray(value) && value.length === 2) { | |
| return value[0]; | |
| } else if (lHlp.isDefined(value.type) && value.type === 'Point') { | |
| return +value.coordinates[0]; | |
| } else { | |
| return +value.lng; | |
| } | |
| }; | |
| var _validateCoords = function(coords) { | |
| if (lHlp.isUndefined(coords)) { | |
| return false; | |
| } | |
| if (lHlp.isArray(coords)) { | |
| if (coords.length === 2 && lHlp.isNumber(coords[0]) && lHlp.isNumber(coords[1])) { | |
| return true; | |
| } | |
| } else if (lHlp.isDefined(coords.type)) { | |
| if ( | |
| coords.type === 'Point' && lHlp.isArray(coords.coordinates) && | |
| coords.coordinates.length === 2 && | |
| lHlp.isNumber(coords.coordinates[0]) && | |
| lHlp.isNumber(coords.coordinates[1])) { | |
| return true; | |
| } | |
| } | |
| var ret = lIt.all(['lat', 'lng'], function(pos) { | |
| return lHlp.isDefined(coords[pos]) && lHlp.isNumber(coords[pos]); | |
| }); | |
| return ret; | |
| }; | |
| var _getCoords = function(value) { | |
| if (!value || !_validateCoords(value)) { | |
| return; | |
| } | |
| var p = null; | |
| if (Array.isArray(value) && value.length === 2) { | |
| p = new Point(value[1], value[0]); | |
| } else if (lHlp.isDefined(value.type) && value.type === 'Point') { | |
| p = new Point(value.coordinates[1], value.coordinates[0]); | |
| } else { | |
| return value; | |
| } | |
| //note angular.merge is avail in angular 1.4.X we might want to fill it here | |
| return angular.extend(value, p);//tap on lat, lng if it doesnt exist | |
| }; | |
| return { | |
| getLat: _getLat, | |
| getLng: _getLng, | |
| validateCoords: _validateCoords, | |
| getCoords: _getCoords, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').service('leafletHelpers', ["$q", "$log", function($q, $log) { | |
| var _errorHeader = '[AngularJS - Leaflet] '; | |
| var _copy = angular.copy; | |
| var _clone = _copy; | |
| /* | |
| For parsing paths to a field in an object | |
| Example: | |
| var obj = { | |
| bike:{ | |
| 1: 'hi' | |
| 2: 'foo' | |
| } | |
| }; | |
| _getObjectValue(obj,"bike.1") returns 'hi' | |
| this is getPath in ui-gmap | |
| */ | |
| var _getObjectValue = function(object, pathStr) { | |
| var obj; | |
| if (!object || !angular.isObject(object)) | |
| return; | |
| //if the key is not a sting then we already have the value | |
| if ((pathStr === null) || !angular.isString(pathStr)) { | |
| return pathStr; | |
| } | |
| obj = object; | |
| pathStr.split('.').forEach(function(value) { | |
| if (obj) { | |
| obj = obj[value]; | |
| } | |
| }); | |
| return obj; | |
| }; | |
| /* | |
| Object Array Notation | |
| _getObjectArrayPath("bike.one.two") | |
| returns: | |
| 'bike["one"]["two"]' | |
| */ | |
| var _getObjectArrayPath = function(pathStr) { | |
| return pathStr.split('.').reduce(function(previous, current) { | |
| return previous + '["' + current + '"]'; | |
| }); | |
| }; | |
| /* Object Dot Notation | |
| _getObjectPath(["bike","one","two"]) | |
| returns: | |
| "bike.one.two" | |
| */ | |
| var _getObjectDotPath = function(arrayOfStrings) { | |
| return arrayOfStrings.reduce(function(previous, current) { | |
| return previous + '.' + current; | |
| }); | |
| }; | |
| function _obtainEffectiveMapId(d, mapId) { | |
| var id; | |
| var i; | |
| if (!angular.isDefined(mapId)) { | |
| if (Object.keys(d).length === 0) { | |
| id = 'main'; | |
| } else if (Object.keys(d).length >= 1) { | |
| for (i in d) { | |
| if (d.hasOwnProperty(i)) { | |
| id = i; | |
| } | |
| } | |
| } else { | |
| $log.error(_errorHeader + '- You have more than 1 map on the DOM, you must provide the map ID to the leafletData.getXXX call'); | |
| } | |
| } else { | |
| id = mapId; | |
| } | |
| return id; | |
| } | |
| function _getUnresolvedDefer(d, mapId) { | |
| var id = _obtainEffectiveMapId(d, mapId); | |
| var defer; | |
| if (!angular.isDefined(d[id]) || d[id].resolvedDefer === true) { | |
| defer = $q.defer(); | |
| d[id] = { | |
| defer: defer, | |
| resolvedDefer: false, | |
| }; | |
| } else { | |
| defer = d[id].defer; | |
| } | |
| return defer; | |
| } | |
| var _isDefined = function(value) { | |
| return angular.isDefined(value) && value !== null; | |
| }; | |
| var _isUndefined = function(value) { | |
| return !_isDefined(value); | |
| }; | |
| // BEGIN DIRECT PORT FROM AngularJS code base | |
| var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; | |
| var MOZ_HACK_REGEXP = /^moz([A-Z])/; | |
| var PREFIX_REGEXP = /^((?:x|data)[\:\-_])/i; | |
| /** | |
| Converts snake_case to camelCase. | |
| Also there is special case for Moz prefix starting with upper case letter. | |
| @param name Name to normalize | |
| */ | |
| var camelCase = function(name) { | |
| return name.replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { | |
| if (offset) { | |
| return letter.toUpperCase(); | |
| } else { | |
| return letter; | |
| } | |
| }).replace(MOZ_HACK_REGEXP, 'Moz$1'); | |
| }; | |
| /** | |
| Converts all accepted directives format into proper directive name. | |
| @param name Name to normalize | |
| */ | |
| var directiveNormalize = function(name) { | |
| return camelCase(name.replace(PREFIX_REGEXP, '')); | |
| }; | |
| // END AngularJS port | |
| return { | |
| camelCase: camelCase, | |
| directiveNormalize: directiveNormalize, | |
| copy:_copy, | |
| clone:_clone, | |
| errorHeader: _errorHeader, | |
| getObjectValue: _getObjectValue, | |
| getObjectArrayPath:_getObjectArrayPath, | |
| getObjectDotPath: _getObjectDotPath, | |
| defaultTo: function(val, _default) { | |
| return _isDefined(val) ? val : _default; | |
| }, | |
| //mainly for checking attributes of directives lets keep this minimal (on what we accept) | |
| isTruthy: function(val) { | |
| return val === 'true' || val === true; | |
| }, | |
| //Determine if a reference is {} | |
| isEmpty: function(value) { | |
| return Object.keys(value).length === 0; | |
| }, | |
| //Determine if a reference is undefined or {} | |
| isUndefinedOrEmpty: function(value) { | |
| return (angular.isUndefined(value) || value === null) || Object.keys(value).length === 0; | |
| }, | |
| // Determine if a reference is defined | |
| isDefined: _isDefined, | |
| isUndefined:_isUndefined, | |
| isNumber: angular.isNumber, | |
| isString: angular.isString, | |
| isArray: angular.isArray, | |
| isObject: angular.isObject, | |
| isFunction: angular.isFunction, | |
| equals: angular.equals, | |
| isValidCenter: function(center) { | |
| return angular.isDefined(center) && angular.isNumber(center.lat) && | |
| angular.isNumber(center.lng) && angular.isNumber(center.zoom); | |
| }, | |
| isValidPoint: function(point) { | |
| if (!angular.isDefined(point)) { | |
| return false; | |
| } | |
| if (angular.isArray(point)) { | |
| return point.length === 2 && angular.isNumber(point[0]) && angular.isNumber(point[1]); | |
| } | |
| return angular.isNumber(point.lat) && angular.isNumber(point.lng); | |
| }, | |
| isSameCenterOnMap: function(centerModel, map) { | |
| var mapCenter = map.getCenter(); | |
| var zoom = map.getZoom(); | |
| if (centerModel.lat && centerModel.lng && | |
| mapCenter.lat.toFixed(4) === centerModel.lat.toFixed(4) && | |
| mapCenter.lng.toFixed(4) === centerModel.lng.toFixed(4) && | |
| zoom === centerModel.zoom) { | |
| return true; | |
| } | |
| return false; | |
| }, | |
| safeApply: function($scope, fn) { | |
| var phase = $scope.$root.$$phase; | |
| if (phase === '$apply' || phase === '$digest') { | |
| $scope.$eval(fn); | |
| } else { | |
| $scope.$evalAsync(fn); | |
| } | |
| }, | |
| obtainEffectiveMapId: _obtainEffectiveMapId, | |
| getDefer: function(d, mapId) { | |
| var id = _obtainEffectiveMapId(d, mapId); | |
| var defer; | |
| if (!angular.isDefined(d[id]) || d[id].resolvedDefer === false) { | |
| defer = _getUnresolvedDefer(d, mapId); | |
| } else { | |
| defer = d[id].defer; | |
| } | |
| return defer; | |
| }, | |
| getUnresolvedDefer: _getUnresolvedDefer, | |
| setResolvedDefer: function(d, mapId) { | |
| var id = _obtainEffectiveMapId(d, mapId); | |
| d[id].resolvedDefer = true; | |
| }, | |
| rangeIsSupported: function() { | |
| var testrange = document.createElement('input'); | |
| testrange.setAttribute('type', 'range'); | |
| return testrange.type === 'range'; | |
| }, | |
| FullScreenControlPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.Control.Fullscreen); | |
| }, | |
| }, | |
| MiniMapControlPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.Control.MiniMap); | |
| }, | |
| }, | |
| AwesomeMarkersPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.AwesomeMarkers) && angular.isDefined(L.AwesomeMarkers.Icon); | |
| }, | |
| is: function(icon) { | |
| if (this.isLoaded()) { | |
| return icon instanceof L.AwesomeMarkers.Icon; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| equal: function(iconA, iconB) { | |
| if (!this.isLoaded()) { | |
| return false; | |
| } | |
| if (this.is(iconA)) { | |
| return angular.equals(iconA, iconB); | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| VectorMarkersPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.VectorMarkers) && angular.isDefined(L.VectorMarkers.Icon); | |
| }, | |
| is: function(icon) { | |
| if (this.isLoaded()) { | |
| return icon instanceof L.VectorMarkers.Icon; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| equal: function(iconA, iconB) { | |
| if (!this.isLoaded()) { | |
| return false; | |
| } | |
| if (this.is(iconA)) { | |
| return angular.equals(iconA, iconB); | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| DomMarkersPlugin: { | |
| isLoaded: function() { | |
| if (angular.isDefined(L.DomMarkers) && angular.isDefined(L.DomMarkers.Icon)) { | |
| return true; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| is: function(icon) { | |
| if (this.isLoaded()) { | |
| return icon instanceof L.DomMarkers.Icon; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| equal: function(iconA, iconB) { | |
| if (!this.isLoaded()) { | |
| return false; | |
| } | |
| if (this.is(iconA)) { | |
| return angular.equals(iconA, iconB); | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| PolylineDecoratorPlugin: { | |
| isLoaded: function() { | |
| if (angular.isDefined(L.PolylineDecorator)) { | |
| return true; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| is: function(decoration) { | |
| if (this.isLoaded()) { | |
| return decoration instanceof L.PolylineDecorator; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| equal: function(decorationA, decorationB) { | |
| if (!this.isLoaded()) { | |
| return false; | |
| } | |
| if (this.is(decorationA)) { | |
| return angular.equals(decorationA, decorationB); | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| MakiMarkersPlugin: { | |
| isLoaded: function() { | |
| if (angular.isDefined(L.MakiMarkers) && angular.isDefined(L.MakiMarkers.Icon)) { | |
| return true; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| is: function(icon) { | |
| if (this.isLoaded()) { | |
| return icon instanceof L.MakiMarkers.Icon; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| equal: function(iconA, iconB) { | |
| if (!this.isLoaded()) { | |
| return false; | |
| } | |
| if (this.is(iconA)) { | |
| return angular.equals(iconA, iconB); | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| ExtraMarkersPlugin: { | |
| isLoaded: function() { | |
| if (angular.isDefined(L.ExtraMarkers) && angular.isDefined(L.ExtraMarkers.Icon)) { | |
| return true; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| is: function(icon) { | |
| if (this.isLoaded()) { | |
| return icon instanceof L.ExtraMarkers.Icon; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| equal: function(iconA, iconB) { | |
| if (!this.isLoaded()) { | |
| return false; | |
| } | |
| if (this.is(iconA)) { | |
| return angular.equals(iconA, iconB); | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| LabelPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.Label); | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.MarkerClusterGroup; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| MarkerClusterPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.MarkerClusterGroup); | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.MarkerClusterGroup; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| GoogleLayerPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.Google); | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.Google; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| LeafletProviderPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.TileLayer.Provider); | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.TileLayer.Provider; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| ChinaLayerPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.tileLayer.chinaProvider); | |
| }, | |
| }, | |
| HeatLayerPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.heatLayer); | |
| }, | |
| }, | |
| WebGLHeatMapLayerPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.TileLayer.WebGLHeatMap); | |
| }, | |
| }, | |
| BingLayerPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.BingLayer); | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.BingLayer; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| WFSLayerPlugin: { | |
| isLoaded: function() { | |
| return L.GeoJSON.WFS !== undefined; | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.GeoJSON.WFS; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| AGSBaseLayerPlugin: { | |
| isLoaded: function() { | |
| return L.esri !== undefined && L.esri.basemapLayer !== undefined; | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.esri.basemapLayer; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| AGSLayerPlugin: { | |
| isLoaded: function() { | |
| return lvector !== undefined && lvector.AGS !== undefined; | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof lvector.AGS; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| AGSFeatureLayerPlugin: { | |
| isLoaded: function() { | |
| return L.esri !== undefined && L.esri.featureLayer !== undefined; | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.esri.featureLayer; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| AGSTiledMapLayerPlugin: { | |
| isLoaded: function() { | |
| return L.esri !== undefined && L.esri.tiledMapLayer !== undefined; | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.esri.tiledMapLayer; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| AGSDynamicMapLayerPlugin: { | |
| isLoaded: function() { | |
| return L.esri !== undefined && L.esri.dynamicMapLayer !== undefined; | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.esri.dynamicMapLayer; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| AGSImageMapLayerPlugin: { | |
| isLoaded: function() { | |
| return L.esri !== undefined && L.esri.imageMapLayer !== undefined; | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.esri.imageMapLayer; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| AGSClusteredLayerPlugin: { | |
| isLoaded: function() { | |
| return L.esri !== undefined && L.esri.clusteredFeatureLayer !== undefined; | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.esri.clusteredFeatureLayer; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| AGSHeatmapLayerPlugin: { | |
| isLoaded: function() { | |
| return L.esri !== undefined && L.esri.heatmapFeatureLayer !== undefined; | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.esri.heatmapFeatureLayer; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| YandexLayerPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.Yandex); | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.Yandex; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| GeoJSONPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.TileLayer.GeoJSON); | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.TileLayer.GeoJSON; | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| UTFGridPlugin: { | |
| isLoaded: function() { | |
| return angular.isDefined(L.UtfGrid); | |
| }, | |
| is: function(layer) { | |
| if (this.isLoaded()) { | |
| return layer instanceof L.UtfGrid; | |
| } else { | |
| $log.error('[AngularJS - Leaflet] No UtfGrid plugin found.'); | |
| return false; | |
| } | |
| }, | |
| }, | |
| CartoDB: { | |
| isLoaded: function() { | |
| return cartodb; | |
| }, | |
| is: function(/*layer*/) { | |
| return true; | |
| /* | |
| if (this.isLoaded()) { | |
| return layer instanceof L.TileLayer.GeoJSON; | |
| } else { | |
| return false; | |
| }*/ | |
| }, | |
| }, | |
| Leaflet: { | |
| DivIcon: { | |
| is: function(icon) { | |
| return icon instanceof L.DivIcon; | |
| }, | |
| equal: function(iconA, iconB) { | |
| if (this.is(iconA)) { | |
| return angular.equals(iconA, iconB); | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| Icon: { | |
| is: function(icon) { | |
| return icon instanceof L.Icon; | |
| }, | |
| equal: function(iconA, iconB) { | |
| if (this.is(iconA)) { | |
| return angular.equals(iconA, iconB); | |
| } else { | |
| return false; | |
| } | |
| }, | |
| }, | |
| }, | |
| /* | |
| watchOptions - object to set deep nested watches and turn off watches all together | |
| (rely on control / functional updates) | |
| watchOptions - Object | |
| doWatch:boolean | |
| isDeep:boolean (sets $watch(function,isDeep)) | |
| individual | |
| doWatch:boolean | |
| isDeep:boolean | |
| */ | |
| //legacy defaults | |
| watchOptions: { | |
| doWatch:true, | |
| isDeep: true, | |
| individual:{ | |
| doWatch:true, | |
| isDeep: true, | |
| }, | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').service('leafletIterators', ["$log", "leafletHelpers", function($log, leafletHelpers) { | |
| var lHlp = leafletHelpers; | |
| var errorHeader = leafletHelpers.errorHeader + 'leafletIterators: '; | |
| //BEGIN COPY from underscore | |
| var _keys = Object.keys; | |
| var _isFunction = lHlp.isFunction; | |
| var _isObject = lHlp.isObject; | |
| // Helper for collection methods to determine whether a collection | |
| // should be iterated as an array or as an object | |
| // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength | |
| var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; | |
| var _isArrayLike = function(collection) { | |
| var length = collection !== null && collection.length; | |
| return lHlp.isNumber(length) && length >= 0 && length <= MAX_ARRAY_INDEX; | |
| }; | |
| // Keep the identity function around for default iteratees. | |
| var _identity = function(value) { | |
| return value; | |
| }; | |
| var _property = function(key) { | |
| return function(obj) { | |
| return obj === null ? void 0 : obj[key]; | |
| }; | |
| }; | |
| // Internal function that returns an efficient (for current engines) version | |
| // of the passed-in callback, to be repeatedly applied in other Underscore | |
| // functions. | |
| var optimizeCb = function(func, context, argCount) { | |
| if (context === void 0) return func; | |
| switch (argCount === null ? 3 : argCount) { | |
| case 1: return function(value) { | |
| return func.call(context, value); | |
| }; | |
| case 2: return function(value, other) { | |
| return func.call(context, value, other); | |
| }; | |
| case 3: return function(value, index, collection) { | |
| return func.call(context, value, index, collection); | |
| }; | |
| case 4: return function(accumulator, value, index, collection) { | |
| return func.call(context, accumulator, value, index, collection); | |
| }; | |
| } | |
| return function() { | |
| return func.apply(context, arguments); | |
| }; | |
| }; | |
| // An internal function for creating assigner functions. | |
| var createAssigner = function(keysFunc, undefinedOnly) { | |
| return function(obj) { | |
| var length = arguments.length; | |
| if (length < 2 || obj === null) return obj; | |
| for (var index = 1; index < length; index++) { | |
| var source = arguments[index]; | |
| var keys = keysFunc(source); | |
| var l = keys.length; | |
| for (var i = 0; i < l; i++) { | |
| var key = keys[i]; | |
| if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; | |
| } | |
| } | |
| return obj; | |
| }; | |
| }; | |
| // Assigns a given object with all the own properties in the passed-in object(s) | |
| // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) | |
| var _extendOwn; | |
| var _assign = null; | |
| _extendOwn = _assign = createAssigner(_keys); | |
| // Returns whether an object has a given set of `key:value` pairs. | |
| var _isMatch = function(object, attrs) { | |
| var keys = _keys(attrs); | |
| var length = keys.length; | |
| if (object === null) return !length; | |
| var obj = Object(object); | |
| for (var i = 0; i < length; i++) { | |
| var key = keys[i]; | |
| if (attrs[key] !== obj[key] || !(key in obj)) return false; | |
| } | |
| return true; | |
| }; | |
| // Returns a predicate for checking whether an object has a given set of | |
| // `key:value` pairs. | |
| var _matcher; | |
| var _matches = null; | |
| _matcher = _matches = function(attrs) { | |
| attrs = _extendOwn({}, attrs); | |
| return function(obj) { | |
| return _isMatch(obj, attrs); | |
| }; | |
| }; | |
| // A mostly-internal function to generate callbacks that can be applied | |
| // to each element in a collection, returning the desired result — either | |
| // identity, an arbitrary callback, a property matcher, or a property accessor. | |
| var cb = function(value, context, argCount) { | |
| if (value === null) return _identity; | |
| if (_isFunction(value)) return optimizeCb(value, context, argCount); | |
| if (_isObject(value)) return _matcher(value); | |
| return _property(value); | |
| }; | |
| var _every; | |
| var _all = null; | |
| _every = _all = function(obj, predicate, context) { | |
| predicate = cb(predicate, context); | |
| var keys = !_isArrayLike(obj) && _keys(obj); | |
| var length = (keys || obj).length; | |
| for (var index = 0; index < length; index++) { | |
| var currentKey = keys ? keys[index] : index; | |
| if (!predicate(obj[currentKey], currentKey, obj)) return false; | |
| } | |
| return true; | |
| }; | |
| //END COPY fron underscore | |
| var _hasErrors = function(collection, cb, ignoreCollection, cbName) { | |
| if (!ignoreCollection) { | |
| if (!lHlp.isDefined(collection) || !lHlp.isDefined(cb)) { | |
| return true; | |
| } | |
| } | |
| if (!lHlp.isFunction(cb)) { | |
| cbName = lHlp.defaultTo(cb, 'cb'); | |
| $log.error(errorHeader + cbName + ' is not a function'); | |
| return true; | |
| } | |
| return false; | |
| }; | |
| var _iterate = function(collection, externalCb, internalCb) { | |
| if (_hasErrors(undefined, internalCb, true, 'internalCb')) { | |
| return; | |
| } | |
| if (!_hasErrors(collection, externalCb)) { | |
| for (var key in collection) { | |
| if (collection.hasOwnProperty(key)) { | |
| internalCb(collection[key], key); | |
| } | |
| } | |
| } | |
| }; | |
| //see http://jsperf.com/iterators/3 | |
| //utilizing for in is way faster | |
| var _each = function(collection, cb) { | |
| _iterate(collection, cb, function(val, key) { | |
| cb(val, key); | |
| }); | |
| }; | |
| return { | |
| each:_each, | |
| forEach: _each, | |
| every: _every, | |
| all: _all, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive') | |
| .factory('leafletLayerHelpers', ["$rootScope", "$log", "$q", "leafletHelpers", "leafletIterators", function($rootScope, $log, $q, leafletHelpers, leafletIterators) { | |
| var Helpers = leafletHelpers; | |
| var isString = leafletHelpers.isString; | |
| var isObject = leafletHelpers.isObject; | |
| var isArray = leafletHelpers.isArray; | |
| var isDefined = leafletHelpers.isDefined; | |
| var errorHeader = leafletHelpers.errorHeader; | |
| var $it = leafletIterators; | |
| var utfGridCreateLayer = function(params) { | |
| if (!Helpers.UTFGridPlugin.isLoaded()) { | |
| $log.error('[AngularJS - Leaflet] The UTFGrid plugin is not loaded.'); | |
| return; | |
| } | |
| var utfgrid = new L.UtfGrid(params.url, params.pluginOptions); | |
| utfgrid.on('mouseover', function(e) { | |
| $rootScope.$broadcast('leafletDirectiveMap.utfgridMouseover', e); | |
| }); | |
| utfgrid.on('mouseout', function(e) { | |
| $rootScope.$broadcast('leafletDirectiveMap.utfgridMouseout', e); | |
| }); | |
| utfgrid.on('click', function(e) { | |
| $rootScope.$broadcast('leafletDirectiveMap.utfgridClick', e); | |
| }); | |
| utfgrid.on('mousemove', function(e) { | |
| $rootScope.$broadcast('leafletDirectiveMap.utfgridMousemove', e); | |
| }); | |
| return utfgrid; | |
| }; | |
| var layerTypes = { | |
| xyz: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| return L.tileLayer(params.url, params.options); | |
| }, | |
| }, | |
| mapbox: { | |
| mustHaveKey: true, | |
| createLayer: function(params) { | |
| var version = 3; | |
| if (isDefined(params.options.version) && params.options.version === 4) { | |
| version = params.options.version; | |
| } | |
| var url = version === 3 ? | |
| '//{s}.tiles.mapbox.com/v3/' + params.key + '/{z}/{x}/{y}.png' : | |
| '//api.tiles.mapbox.com/v4/' + params.key + '/{z}/{x}/{y}.png?access_token=' + params.apiKey; | |
| return L.tileLayer(url, params.options); | |
| }, | |
| }, | |
| geoJSON: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| if (!Helpers.GeoJSONPlugin.isLoaded()) { | |
| return; | |
| } | |
| return new L.TileLayer.GeoJSON(params.url, params.pluginOptions, params.options); | |
| }, | |
| }, | |
| geoJSONShape: { | |
| mustHaveUrl: false, | |
| createLayer: function(params) { | |
| return new L.GeoJSON(params.data, | |
| params.options); | |
| }, | |
| }, | |
| geoJSONAwesomeMarker: { | |
| mustHaveUrl: false, | |
| createLayer: function(params) { | |
| return new L.geoJson(params.data, { | |
| pointToLayer: function(feature, latlng) { | |
| return L.marker(latlng, {icon: L.AwesomeMarkers.icon(params.icon)}); | |
| }, | |
| }); | |
| }, | |
| }, | |
| geoJSONVectorMarker: { | |
| mustHaveUrl: false, | |
| createLayer: function(params) { | |
| return new L.geoJson(params.data, { | |
| pointToLayer: function(feature, latlng) { | |
| return L.marker(latlng, {icon: L.VectorMarkers.icon(params.icon)}); | |
| }, | |
| }); | |
| }, | |
| }, | |
| utfGrid: { | |
| mustHaveUrl: true, | |
| createLayer: utfGridCreateLayer, | |
| }, | |
| cartodbTiles: { | |
| mustHaveKey: true, | |
| createLayer: function(params) { | |
| var url = '//' + params.user + '.cartodb.com/api/v1/map/' + params.key + '/{z}/{x}/{y}.png'; | |
| return L.tileLayer(url, params.options); | |
| }, | |
| }, | |
| cartodbUTFGrid: { | |
| mustHaveKey: true, | |
| mustHaveLayer: true, | |
| createLayer: function(params) { | |
| params.url = '//' + params.user + '.cartodb.com/api/v1/map/' + params.key + '/' + params.layer + '/{z}/{x}/{y}.grid.json'; | |
| return utfGridCreateLayer(params); | |
| }, | |
| }, | |
| cartodbInteractive: { | |
| mustHaveKey: true, | |
| mustHaveLayer: true, | |
| createLayer: function(params) { | |
| var tilesURL = '//' + params.user + '.cartodb.com/api/v1/map/' + params.key + '/{z}/{x}/{y}.png'; | |
| var tileLayer = L.tileLayer(tilesURL, params.options); | |
| params.url = '//' + params.user + '.cartodb.com/api/v1/map/' + params.key + '/' + params.layer + '/{z}/{x}/{y}.grid.json'; | |
| var utfLayer = utfGridCreateLayer(params); | |
| return L.layerGroup([tileLayer, utfLayer]); | |
| }, | |
| }, | |
| wms: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| return L.tileLayer.wms(params.url, params.options); | |
| }, | |
| }, | |
| wmts: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| return L.tileLayer.wmts(params.url, params.options); | |
| }, | |
| }, | |
| wfs: { | |
| mustHaveUrl: true, | |
| mustHaveLayer: true, | |
| createLayer: function(params) { | |
| if (!Helpers.WFSLayerPlugin.isLoaded()) { | |
| return; | |
| } | |
| var options = angular.copy(params.options); | |
| if (options.crs && typeof options.crs === 'string') { | |
| /*jshint -W061 */ | |
| options.crs = eval(options.crs); | |
| } | |
| return new L.GeoJSON.WFS(params.url, params.layer, options); | |
| }, | |
| }, | |
| group: { | |
| mustHaveUrl: false, | |
| createLayer: function(params) { | |
| var lyrs = []; | |
| $it.each(params.options.layers, function(l) { | |
| lyrs.push(createLayer(l)); | |
| }); | |
| params.options.loadedDefer = function() { | |
| var defers = []; | |
| if (isDefined(params.options.layers)) { | |
| for (var i = 0; i < params.options.layers.length; i++) { | |
| var d = params.options.layers[i].layerOptions.loadedDefer; | |
| if (isDefined(d)) { | |
| defers.push(d); | |
| } | |
| } | |
| } | |
| return defers; | |
| }; | |
| return L.layerGroup(lyrs); | |
| }, | |
| }, | |
| featureGroup: { | |
| mustHaveUrl: false, | |
| createLayer: function() { | |
| return L.featureGroup(); | |
| }, | |
| }, | |
| google: { | |
| mustHaveUrl: false, | |
| createLayer: function(params) { | |
| var type = params.type || 'SATELLITE'; | |
| if (!Helpers.GoogleLayerPlugin.isLoaded()) { | |
| return; | |
| } | |
| return new L.Google(type, params.options); | |
| }, | |
| }, | |
| here: { | |
| mustHaveUrl: false, | |
| createLayer: function(params) { | |
| var provider = params.provider || 'HERE.terrainDay'; | |
| if (!Helpers.LeafletProviderPlugin.isLoaded()) { | |
| return; | |
| } | |
| return new L.TileLayer.Provider(provider, params.options); | |
| }, | |
| }, | |
| china:{ | |
| mustHaveUrl:false, | |
| createLayer:function(params) { | |
| var type = params.type || ''; | |
| if (!Helpers.ChinaLayerPlugin.isLoaded()) { | |
| return; | |
| } | |
| return L.tileLayer.chinaProvider(type, params.options); | |
| }, | |
| }, | |
| agsBase: { | |
| mustHaveLayer: true, | |
| createLayer: function(params) { | |
| if (!Helpers.AGSBaseLayerPlugin.isLoaded()) { | |
| return; | |
| } | |
| return L.esri.basemapLayer(params.layer, params.options); | |
| }, | |
| }, | |
| ags: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| if (!Helpers.AGSLayerPlugin.isLoaded()) { | |
| return; | |
| } | |
| var options = angular.copy(params.options); | |
| angular.extend(options, { | |
| url: params.url, | |
| }); | |
| var layer = new lvector.AGS(options); | |
| layer.onAdd = function(map) { | |
| this.setMap(map); | |
| }; | |
| layer.onRemove = function() { | |
| this.setMap(null); | |
| }; | |
| return layer; | |
| }, | |
| }, | |
| agsFeature: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| if (!Helpers.AGSFeatureLayerPlugin.isLoaded()) { | |
| $log.warn(errorHeader + ' The esri plugin is not loaded.'); | |
| return; | |
| } | |
| params.options.url = params.url; | |
| var layer = L.esri.featureLayer(params.options); | |
| var load = function() { | |
| if (isDefined(params.options.loadedDefer)) { | |
| params.options.loadedDefer.resolve(); | |
| } | |
| }; | |
| layer.on('loading', function() { | |
| params.options.loadedDefer = $q.defer(); | |
| layer.off('load', load); | |
| layer.on('load', load); | |
| }); | |
| return layer; | |
| }, | |
| }, | |
| agsTiled: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| if (!Helpers.AGSTiledMapLayerPlugin.isLoaded()) { | |
| $log.warn(errorHeader + ' The esri plugin is not loaded.'); | |
| return; | |
| } | |
| params.options.url = params.url; | |
| return L.esri.tiledMapLayer(params.options); | |
| }, | |
| }, | |
| agsDynamic: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| if (!Helpers.AGSDynamicMapLayerPlugin.isLoaded()) { | |
| $log.warn(errorHeader + ' The esri plugin is not loaded.'); | |
| return; | |
| } | |
| params.options.url = params.url; | |
| return L.esri.dynamicMapLayer(params.options); | |
| }, | |
| }, | |
| agsImage: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| if (!Helpers.AGSImageMapLayerPlugin.isLoaded()) { | |
| $log.warn(errorHeader + ' The esri plugin is not loaded.'); | |
| return; | |
| } | |
| params.options.url = params.url; | |
| return L.esri.imageMapLayer(params.options); | |
| }, | |
| }, | |
| agsClustered: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| if (!Helpers.AGSClusteredLayerPlugin.isLoaded()) { | |
| $log.warn(errorHeader + ' The esri clustered layer plugin is not loaded.'); | |
| return; | |
| } | |
| if (!Helpers.MarkerClusterPlugin.isLoaded()) { | |
| $log.warn(errorHeader + ' The markercluster plugin is not loaded.'); | |
| return; | |
| } | |
| return L.esri.clusteredFeatureLayer(params.url, params.options); | |
| }, | |
| }, | |
| agsHeatmap: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| if (!Helpers.AGSHeatmapLayerPlugin.isLoaded()) { | |
| $log.warn(errorHeader + ' The esri heatmap layer plugin is not loaded.'); | |
| return; | |
| } | |
| if (!Helpers.HeatLayerPlugin.isLoaded()) { | |
| $log.warn(errorHeader + ' The heatlayer plugin is not loaded.'); | |
| return; | |
| } | |
| return L.esri.heatmapFeatureLayer(params.url, params.options); | |
| }, | |
| }, | |
| markercluster: { | |
| mustHaveUrl: false, | |
| createLayer: function(params) { | |
| if (!Helpers.MarkerClusterPlugin.isLoaded()) { | |
| $log.warn(errorHeader + ' The markercluster plugin is not loaded.'); | |
| return; | |
| } | |
| return new L.MarkerClusterGroup(params.options); | |
| }, | |
| }, | |
| bing: { | |
| mustHaveUrl: false, | |
| createLayer: function(params) { | |
| if (!Helpers.BingLayerPlugin.isLoaded()) { | |
| return; | |
| } | |
| return new L.BingLayer(params.key, params.options); | |
| }, | |
| }, | |
| webGLHeatmap: { | |
| mustHaveUrl: false, | |
| mustHaveData: true, | |
| createLayer: function(params) { | |
| if (!Helpers.WebGLHeatMapLayerPlugin.isLoaded()) { | |
| return; | |
| } | |
| var layer = new L.TileLayer.WebGLHeatMap(params.options); | |
| if (isDefined(params.data)) { | |
| layer.setData(params.data); | |
| } | |
| return layer; | |
| }, | |
| }, | |
| heat: { | |
| mustHaveUrl: false, | |
| mustHaveData: true, | |
| createLayer: function(params) { | |
| if (!Helpers.HeatLayerPlugin.isLoaded()) { | |
| return; | |
| } | |
| var layer = new L.heatLayer(); | |
| if (isArray(params.data)) { | |
| layer.setLatLngs(params.data); | |
| } | |
| if (isObject(params.options)) { | |
| layer.setOptions(params.options); | |
| } | |
| return layer; | |
| }, | |
| }, | |
| yandex: { | |
| mustHaveUrl: false, | |
| createLayer: function(params) { | |
| var type = params.type || 'map'; | |
| if (!Helpers.YandexLayerPlugin.isLoaded()) { | |
| return; | |
| } | |
| return new L.Yandex(type, params.options); | |
| }, | |
| }, | |
| imageOverlay: { | |
| mustHaveUrl: true, | |
| mustHaveBounds: true, | |
| createLayer: function(params) { | |
| return L.imageOverlay(params.url, params.bounds, params.options); | |
| }, | |
| }, | |
| iip: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| return L.tileLayer.iip(params.url, params.options); | |
| }, | |
| }, | |
| // This "custom" type is used to accept every layer that user want to define himself. | |
| // We can wrap these custom layers like heatmap or yandex, but it means a lot of work/code to wrap the world, | |
| // so we let user to define their own layer outside the directive, | |
| // and pass it on "createLayer" result for next processes | |
| custom: { | |
| createLayer: function(params) { | |
| if (params.layer instanceof L.Class) { | |
| return angular.copy(params.layer); | |
| } else { | |
| $log.error('[AngularJS - Leaflet] A custom layer must be a leaflet Class'); | |
| } | |
| }, | |
| }, | |
| cartodb: { | |
| mustHaveUrl: true, | |
| createLayer: function(params) { | |
| return cartodb.createLayer(params.map, params.url); | |
| }, | |
| }, | |
| }; | |
| function isValidLayerType(layerDefinition) { | |
| // Check if the baselayer has a valid type | |
| if (!isString(layerDefinition.type)) { | |
| $log.error('[AngularJS - Leaflet] A layer must have a valid type defined.'); | |
| return false; | |
| } | |
| if (Object.keys(layerTypes).indexOf(layerDefinition.type) === -1) { | |
| $log.error('[AngularJS - Leaflet] A layer must have a valid type: ' + Object.keys(layerTypes)); | |
| return false; | |
| } | |
| // Check if the layer must have an URL | |
| if (layerTypes[layerDefinition.type].mustHaveUrl && !isString(layerDefinition.url)) { | |
| $log.error('[AngularJS - Leaflet] A base layer must have an url'); | |
| return false; | |
| } | |
| if (layerTypes[layerDefinition.type].mustHaveData && !isDefined(layerDefinition.data)) { | |
| $log.error('[AngularJS - Leaflet] The base layer must have a "data" array attribute'); | |
| return false; | |
| } | |
| if (layerTypes[layerDefinition.type].mustHaveLayer && !isDefined(layerDefinition.layer)) { | |
| $log.error('[AngularJS - Leaflet] The type of layer ' + layerDefinition.type + ' must have an layer defined'); | |
| return false; | |
| } | |
| if (layerTypes[layerDefinition.type].mustHaveBounds && !isDefined(layerDefinition.bounds)) { | |
| $log.error('[AngularJS - Leaflet] The type of layer ' + layerDefinition.type + ' must have bounds defined'); | |
| return false; | |
| } | |
| if (layerTypes[layerDefinition.type].mustHaveKey && !isDefined(layerDefinition.key)) { | |
| $log.error('[AngularJS - Leaflet] The type of layer ' + layerDefinition.type + ' must have key defined'); | |
| return false; | |
| } | |
| return true; | |
| } | |
| function createLayer(layerDefinition) { | |
| if (!isValidLayerType(layerDefinition)) { | |
| return; | |
| } | |
| if (!isString(layerDefinition.name)) { | |
| $log.error('[AngularJS - Leaflet] A base layer must have a name'); | |
| return; | |
| } | |
| if (!isObject(layerDefinition.layerParams)) { | |
| layerDefinition.layerParams = {}; | |
| } | |
| if (!isObject(layerDefinition.layerOptions)) { | |
| layerDefinition.layerOptions = {}; | |
| } | |
| // Mix the layer specific parameters with the general Leaflet options. Although this is an overhead | |
| // the definition of a base layers is more 'clean' if the two types of parameters are differentiated | |
| for (var attrname in layerDefinition.layerParams) { | |
| layerDefinition.layerOptions[attrname] = layerDefinition.layerParams[attrname]; | |
| } | |
| var params = { | |
| url: layerDefinition.url, | |
| data: layerDefinition.data, | |
| options: layerDefinition.layerOptions, | |
| layer: layerDefinition.layer, | |
| icon: layerDefinition.icon, | |
| type: layerDefinition.layerType, | |
| bounds: layerDefinition.bounds, | |
| key: layerDefinition.key, | |
| apiKey: layerDefinition.apiKey, | |
| pluginOptions: layerDefinition.pluginOptions, | |
| user: layerDefinition.user, | |
| }; | |
| //TODO Add $watch to the layer properties | |
| return layerTypes[layerDefinition.type].createLayer(params); | |
| } | |
| function safeAddLayer(map, layer) { | |
| if (layer && typeof layer.addTo === 'function') { | |
| layer.addTo(map); | |
| } else { | |
| map.addLayer(layer); | |
| } | |
| } | |
| function safeRemoveLayer(map, layer, layerOptions) { | |
| if (isDefined(layerOptions) && isDefined(layerOptions.loadedDefer)) { | |
| if (angular.isFunction(layerOptions.loadedDefer)) { | |
| var defers = layerOptions.loadedDefer(); | |
| $log.debug('Loaded Deferred', defers); | |
| var count = defers.length; | |
| if (count > 0) { | |
| var resolve = function() { | |
| count--; | |
| if (count === 0) { | |
| map.removeLayer(layer); | |
| } | |
| }; | |
| for (var i = 0; i < defers.length; i++) { | |
| defers[i].promise.then(resolve); | |
| } | |
| } else { | |
| map.removeLayer(layer); | |
| } | |
| } else { | |
| layerOptions.loadedDefer.promise.then(function() { | |
| map.removeLayer(layer); | |
| }); | |
| } | |
| } else { | |
| map.removeLayer(layer); | |
| } | |
| } | |
| return { | |
| createLayer: createLayer, | |
| safeAddLayer: safeAddLayer, | |
| safeRemoveLayer: safeRemoveLayer, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').factory('leafletLegendHelpers', function() { | |
| var _updateLegend = function(div, legendData, type, url) { | |
| div.innerHTML = ''; | |
| if (legendData.error) { | |
| div.innerHTML += '<div class="info-title alert alert-danger">' + legendData.error.message + '</div>'; | |
| } else { | |
| if (type === 'arcgis') { | |
| for (var i = 0; i < legendData.layers.length; i++) { | |
| var layer = legendData.layers[i]; | |
| div.innerHTML += '<div class="info-title" data-layerid="' + layer.layerId + '">' + layer.layerName + '</div>'; | |
| for (var j = 0; j < layer.legend.length; j++) { | |
| var leg = layer.legend[j]; | |
| div.innerHTML += | |
| '<div class="inline" data-layerid="' + layer.layerId + '"><img src="data:' + leg.contentType + ';base64,' + leg.imageData + '" /></div>' + | |
| '<div class="info-label" data-layerid="' + layer.layerId + '">' + leg.label + '</div>'; | |
| } | |
| } | |
| } else if (type === 'image') { | |
| div.innerHTML = '<img src="' + url + '"/>'; | |
| } | |
| } | |
| }; | |
| var _getOnAddLegend = function(legendData, legendClass, type, url) { | |
| return function(/*map*/) { | |
| var div = L.DomUtil.create('div', legendClass); | |
| if (!L.Browser.touch) { | |
| L.DomEvent.disableClickPropagation(div); | |
| L.DomEvent.on(div, 'mousewheel', L.DomEvent.stopPropagation); | |
| } else { | |
| L.DomEvent.on(div, 'click', L.DomEvent.stopPropagation); | |
| } | |
| _updateLegend(div, legendData, type, url); | |
| return div; | |
| }; | |
| }; | |
| var _getOnAddArrayLegend = function(legend, legendClass) { | |
| return function(/*map*/) { | |
| var div = L.DomUtil.create('div', legendClass); | |
| for (var i = 0; i < legend.colors.length; i++) { | |
| div.innerHTML += | |
| '<div class="outline"><i style="background:' + legend.colors[i] + '"></i></div>' + | |
| '<div class="info-label">' + legend.labels[i] + '</div>'; | |
| } | |
| if (!L.Browser.touch) { | |
| L.DomEvent.disableClickPropagation(div); | |
| L.DomEvent.on(div, 'mousewheel', L.DomEvent.stopPropagation); | |
| } else { | |
| L.DomEvent.on(div, 'click', L.DomEvent.stopPropagation); | |
| } | |
| return div; | |
| }; | |
| }; | |
| return { | |
| getOnAddLegend: _getOnAddLegend, | |
| getOnAddArrayLegend: _getOnAddArrayLegend, | |
| updateLegend: _updateLegend, | |
| }; | |
| }); | |
| angular.module('leaflet-directive').factory('leafletMapDefaults', ["$q", "leafletHelpers", function($q, leafletHelpers) { | |
| function _getDefaults() { | |
| return { | |
| keyboard: true, | |
| dragging: true, | |
| worldCopyJump: false, | |
| doubleClickZoom: true, | |
| scrollWheelZoom: true, | |
| tap: true, | |
| touchZoom: true, | |
| zoomControl: true, | |
| zoomsliderControl: false, | |
| zoomControlPosition: 'topleft', | |
| attributionControl: true, | |
| controls: { | |
| layers: { | |
| visible: true, | |
| position: 'topright', | |
| collapsed: true, | |
| }, | |
| }, | |
| nominatim: { | |
| server: ' http://nominatim.openstreetmap.org/search', | |
| }, | |
| crs: L.CRS.EPSG3857, | |
| tileLayer: '//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', | |
| tileLayerOptions: { | |
| attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', | |
| }, | |
| path: { | |
| weight: 10, | |
| opacity: 1, | |
| color: '#0000ff', | |
| }, | |
| center: { | |
| lat: 0, | |
| lng: 0, | |
| zoom: 1, | |
| }, | |
| }; | |
| } | |
| var isDefined = leafletHelpers.isDefined; | |
| var isObject = leafletHelpers.isObject; | |
| var obtainEffectiveMapId = leafletHelpers.obtainEffectiveMapId; | |
| var defaults = {}; | |
| // Get the _defaults dictionary, and override the properties defined by the user | |
| return { | |
| reset: function() { | |
| defaults = {}; | |
| }, | |
| getDefaults: function(scopeId) { | |
| var mapId = obtainEffectiveMapId(defaults, scopeId); | |
| return defaults[mapId]; | |
| }, | |
| getMapCreationDefaults: function(scopeId) { | |
| var mapId = obtainEffectiveMapId(defaults, scopeId); | |
| var d = defaults[mapId]; | |
| var mapDefaults = { | |
| maxZoom: d.maxZoom, | |
| keyboard: d.keyboard, | |
| dragging: d.dragging, | |
| zoomControl: d.zoomControl, | |
| doubleClickZoom: d.doubleClickZoom, | |
| scrollWheelZoom: d.scrollWheelZoom, | |
| tap: d.tap, | |
| touchZoom: d.touchZoom, | |
| attributionControl: d.attributionControl, | |
| worldCopyJump: d.worldCopyJump, | |
| crs: d.crs, | |
| }; | |
| if (isDefined(d.minZoom)) { | |
| mapDefaults.minZoom = d.minZoom; | |
| } | |
| if (isDefined(d.zoomAnimation)) { | |
| mapDefaults.zoomAnimation = d.zoomAnimation; | |
| } | |
| if (isDefined(d.fadeAnimation)) { | |
| mapDefaults.fadeAnimation = d.fadeAnimation; | |
| } | |
| if (isDefined(d.markerZoomAnimation)) { | |
| mapDefaults.markerZoomAnimation = d.markerZoomAnimation; | |
| } | |
| if (d.map) { | |
| for (var option in d.map) { | |
| mapDefaults[option] = d.map[option]; | |
| } | |
| } | |
| return mapDefaults; | |
| }, | |
| setDefaults: function(userDefaults, scopeId) { | |
| var newDefaults = _getDefaults(); | |
| if (isDefined(userDefaults)) { | |
| newDefaults.doubleClickZoom = isDefined(userDefaults.doubleClickZoom) ? userDefaults.doubleClickZoom : newDefaults.doubleClickZoom; | |
| newDefaults.scrollWheelZoom = isDefined(userDefaults.scrollWheelZoom) ? userDefaults.scrollWheelZoom : newDefaults.doubleClickZoom; | |
| newDefaults.tap = isDefined(userDefaults.tap) ? userDefaults.tap : newDefaults.tap; | |
| newDefaults.touchZoom = isDefined(userDefaults.touchZoom) ? userDefaults.touchZoom : newDefaults.doubleClickZoom; | |
| newDefaults.zoomControl = isDefined(userDefaults.zoomControl) ? userDefaults.zoomControl : newDefaults.zoomControl; | |
| newDefaults.zoomsliderControl = isDefined(userDefaults.zoomsliderControl) ? userDefaults.zoomsliderControl : newDefaults.zoomsliderControl; | |
| newDefaults.attributionControl = isDefined(userDefaults.attributionControl) ? userDefaults.attributionControl : newDefaults.attributionControl; | |
| newDefaults.tileLayer = isDefined(userDefaults.tileLayer) ? userDefaults.tileLayer : newDefaults.tileLayer; | |
| newDefaults.zoomControlPosition = isDefined(userDefaults.zoomControlPosition) ? userDefaults.zoomControlPosition : newDefaults.zoomControlPosition; | |
| newDefaults.keyboard = isDefined(userDefaults.keyboard) ? userDefaults.keyboard : newDefaults.keyboard; | |
| newDefaults.dragging = isDefined(userDefaults.dragging) ? userDefaults.dragging : newDefaults.dragging; | |
| if (isDefined(userDefaults.controls)) { | |
| angular.extend(newDefaults.controls, userDefaults.controls); | |
| } | |
| if (isObject(userDefaults.crs)) { | |
| newDefaults.crs = userDefaults.crs; | |
| } else if (isDefined(L.CRS[userDefaults.crs])) { | |
| newDefaults.crs = L.CRS[userDefaults.crs]; | |
| } | |
| if (isDefined(userDefaults.center)) { | |
| angular.copy(userDefaults.center, newDefaults.center); | |
| } | |
| if (isDefined(userDefaults.tileLayerOptions)) { | |
| angular.copy(userDefaults.tileLayerOptions, newDefaults.tileLayerOptions); | |
| } | |
| if (isDefined(userDefaults.maxZoom)) { | |
| newDefaults.maxZoom = userDefaults.maxZoom; | |
| } | |
| if (isDefined(userDefaults.minZoom)) { | |
| newDefaults.minZoom = userDefaults.minZoom; | |
| } | |
| if (isDefined(userDefaults.zoomAnimation)) { | |
| newDefaults.zoomAnimation = userDefaults.zoomAnimation; | |
| } | |
| if (isDefined(userDefaults.fadeAnimation)) { | |
| newDefaults.fadeAnimation = userDefaults.fadeAnimation; | |
| } | |
| if (isDefined(userDefaults.markerZoomAnimation)) { | |
| newDefaults.markerZoomAnimation = userDefaults.markerZoomAnimation; | |
| } | |
| if (isDefined(userDefaults.worldCopyJump)) { | |
| newDefaults.worldCopyJump = userDefaults.worldCopyJump; | |
| } | |
| if (isDefined(userDefaults.map)) { | |
| newDefaults.map = userDefaults.map; | |
| } | |
| if (isDefined(userDefaults.path)) { | |
| newDefaults.path = userDefaults.path; | |
| } | |
| } | |
| var mapId = obtainEffectiveMapId(defaults, scopeId); | |
| defaults[mapId] = newDefaults; | |
| return newDefaults; | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').service('leafletMarkersHelpers', ["$rootScope", "$timeout", "leafletHelpers", "$log", "$compile", "leafletGeoJsonHelpers", function($rootScope, $timeout, leafletHelpers, $log, $compile, leafletGeoJsonHelpers) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var defaultTo = leafletHelpers.defaultTo; | |
| var MarkerClusterPlugin = leafletHelpers.MarkerClusterPlugin; | |
| var AwesomeMarkersPlugin = leafletHelpers.AwesomeMarkersPlugin; | |
| var VectorMarkersPlugin = leafletHelpers.VectorMarkersPlugin; | |
| var MakiMarkersPlugin = leafletHelpers.MakiMarkersPlugin; | |
| var ExtraMarkersPlugin = leafletHelpers.ExtraMarkersPlugin; | |
| var DomMarkersPlugin = leafletHelpers.DomMarkersPlugin; | |
| var safeApply = leafletHelpers.safeApply; | |
| var Helpers = leafletHelpers; | |
| var isString = leafletHelpers.isString; | |
| var isNumber = leafletHelpers.isNumber; | |
| var isObject = leafletHelpers.isObject; | |
| var groups = {}; | |
| var geoHlp = leafletGeoJsonHelpers; | |
| var errorHeader = leafletHelpers.errorHeader; | |
| var _string = function(marker) { | |
| //this exists since JSON.stringify barfs on cyclic | |
| var retStr = ''; | |
| ['_icon', '_latlng', '_leaflet_id', '_map', '_shadow'].forEach(function(prop) { | |
| retStr += prop + ': ' + defaultTo(marker[prop], 'undefined') + ' \n'; | |
| }); | |
| return '[leafletMarker] : \n' + retStr; | |
| }; | |
| var _log = function(marker, useConsole) { | |
| var logger = useConsole ? console : $log; | |
| logger.debug(_string(marker)); | |
| }; | |
| var createLeafletIcon = function(iconData) { | |
| if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'awesomeMarker') { | |
| if (!AwesomeMarkersPlugin.isLoaded()) { | |
| $log.error(errorHeader + ' The AwesomeMarkers Plugin is not loaded.'); | |
| } | |
| return new L.AwesomeMarkers.icon(iconData); | |
| } | |
| if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'vectorMarker') { | |
| if (!VectorMarkersPlugin.isLoaded()) { | |
| $log.error(errorHeader + ' The VectorMarkers Plugin is not loaded.'); | |
| } | |
| return new L.VectorMarkers.icon(iconData); | |
| } | |
| if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'makiMarker') { | |
| if (!MakiMarkersPlugin.isLoaded()) { | |
| $log.error(errorHeader + 'The MakiMarkers Plugin is not loaded.'); | |
| } | |
| return new L.MakiMarkers.icon(iconData); | |
| } | |
| if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'extraMarker') { | |
| if (!ExtraMarkersPlugin.isLoaded()) { | |
| $log.error(errorHeader + 'The ExtraMarkers Plugin is not loaded.'); | |
| } | |
| return new L.ExtraMarkers.icon(iconData); | |
| } | |
| if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'div') { | |
| return new L.divIcon(iconData); | |
| } | |
| if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'dom') { | |
| if (!DomMarkersPlugin.isLoaded()) { | |
| $log.error(errorHeader + 'The DomMarkers Plugin is not loaded.'); | |
| } | |
| var markerScope = angular.isFunction(iconData.getMarkerScope) ? iconData.getMarkerScope() : $rootScope; | |
| var template = $compile(iconData.template)(markerScope); | |
| var iconDataCopy = angular.copy(iconData); | |
| iconDataCopy.element = template[0]; | |
| return new L.DomMarkers.icon(iconDataCopy); | |
| } | |
| // allow for any custom icon to be used... assumes the icon has already been initialized | |
| if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'icon') { | |
| return iconData.icon; | |
| } | |
| var base64icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAGmklEQVRYw7VXeUyTZxjvNnfELFuyIzOabermMZEeQC/OclkO49CpOHXOLJl/CAURuYbQi3KLgEhbrhZ1aDwmaoGqKII6odATmH/scDFbdC7LvFqOCc+e95s2VG50X/LLm/f4/Z7neY/ne18aANCmAr5E/xZf1uDOkTcGcWR6hl9247tT5U7Y6SNvWsKT63P58qbfeLJG8M5qcgTknrvvrdDbsT7Ml+tv82X6vVxJE33aRmgSyYtcWVMqX97Yv2JvW39UhRE2HuyBL+t+gK1116ly06EeWFNlAmHxlQE0OMiV6mQCScusKRlhS3QLeVJdl1+23h5dY4FNB3thrbYboqptEFlphTC1hSpJnbRvxP4NWgsE5Jyz86QNNi/5qSUTGuFk1gu54tN9wuK2wc3o+Wc13RCmsoBwEqzGcZsxsvCSy/9wJKf7UWf1mEY8JWfewc67UUoDbDjQC+FqK4QqLVMGGR9d2wurKzqBk3nqIT/9zLxRRjgZ9bqQgub+DdoeCC03Q8j+0QhFhBHR/eP3U/zCln7Uu+hihJ1+bBNffLIvmkyP0gpBZWYXhKussK6mBz5HT6M1Nqpcp+mBCPXosYQfrekGvrjewd59/GvKCE7TbK/04/ZV5QZYVWmDwH1mF3xa2Q3ra3DBC5vBT1oP7PTj4C0+CcL8c7C2CtejqhuCnuIQHaKHzvcRfZpnylFfXsYJx3pNLwhKzRAwAhEqG0SpusBHfAKkxw3w4627MPhoCH798z7s0ZnBJ/MEJbZSbXPhER2ih7p2ok/zSj2cEJDd4CAe+5WYnBCgR2uruyEw6zRoW6/DWJ/OeAP8pd/BGtzOZKpG8oke0SX6GMmRk6GFlyAc59K32OTEinILRJRchah8HQwND8N435Z9Z0FY1EqtxUg+0SO6RJ/mmXz4VuS+DpxXC3gXmZwIL7dBSH4zKE50wESf8qwVgrP1EIlTO5JP9Igu0aexdh28F1lmAEGJGfh7jE6ElyM5Rw/FDcYJjWhbeiBYoYNIpc2FT/SILivp0F1ipDWk4BIEo2VuodEJUifhbiltnNBIXPUFCMpthtAyqws/BPlEF/VbaIxErdxPphsU7rcCp8DohC+GvBIPJS/tW2jtvTmmAeuNO8BNOYQeG8G/2OzCJ3q+soYB5i6NhMaKr17FSal7GIHheuV3uSCY8qYVuEm1cOzqdWr7ku/R0BDoTT+DT+ohCM6/CCvKLKO4RI+dXPeAuaMqksaKrZ7L3FE5FIFbkIceeOZ2OcHO6wIhTkNo0ffgjRGxEqogXHYUPHfWAC/lADpwGcLRY3aeK4/oRGCKYcZXPVoeX/kelVYY8dUGf8V5EBRbgJXT5QIPhP9ePJi428JKOiEYhYXFBqou2Guh+p/mEB1/RfMw6rY7cxcjTrneI1FrDyuzUSRm9miwEJx8E/gUmqlyvHGkneiwErR21F3tNOK5Tf0yXaT+O7DgCvALTUBXdM4YhC/IawPU+2PduqMvuaR6eoxSwUk75ggqsYJ7VicsnwGIkZBSXKOUww73WGXyqP+J2/b9c+gi1YAg/xpwck3gJuucNrh5JvDPvQr0WFXf0piyt8f8/WI0hV4pRxxkQZdJDfDJNOAmM0Ag8jyT6hz0WGXWuP94Yh2jcfjmXAGvHCMslRimDHYuHuDsy2QtHuIavznhbYURq5R57KpzBBRZKPJi8eQg48h4j8SDdowifdIrEVdU+gbO6QNvRRt4ZBthUaZhUnjlYObNagV3keoeru3rU7rcuceqU1mJBxy+BWZYlNEBH+0eH4vRiB+OYybU2hnblYlTvkHinM4m54YnxSyaZYSF6R3jwgP7udKLGIX6r/lbNa9N6y5MFynjWDtrHd75ZvTYAPO/6RgF0k76mQla3FGq7dO+cH8sKn0Vo7nDllwAhqwLPkxrHwWmHJOo+AKJ4rab5OgrM7rVu8eWb2Pu0Dh4eDgXoOfvp7Y7QeqknRmvcTBEyq9m/HQQSCSz6LHq3z0yzsNySRfMS253wl2KyRDbcZPcfJKjZmSEOjcxyi+Y8dUOtsIEH6R2wNykdqrkYJ0RV92H0W58pkfQk7cKevsLK10Py8SdMGfXNXATY+pPbyJR/ET6n9nIfztNtZYRV9XniQu9IA2vOVgy4ir7GCLVmmd+zjkH0eAF9Po6K61pmCXHxU5rHMYd1ftc3owjwRSVRzLjKvqZEty6cRUD7jGqiOdu5HG6MdHjNcNYGqfDm5YRzLBBCCDl/2bk8a8gdbqcfwECu62Fg/HrggAAAABJRU5ErkJggg=='; | |
| var base64shadow = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAApCAYAAACoYAD2AAAC5ElEQVRYw+2YW4/TMBCF45S0S1luXZCABy5CgLQgwf//S4BYBLTdJLax0fFqmB07nnQfEGqkIydpVH85M+NLjPe++dcPc4Q8Qh4hj5D/AaQJx6H/4TMwB0PeBNwU7EGQAmAtsNfAzoZkgIa0ZgLMa4Aj6CxIAsjhjOCoL5z7Glg1JAOkaicgvQBXuncwJAWjksLtBTWZe04CnYRktUGdilALppZBOgHGZcBzL6OClABvMSVIzyBjazOgrvACf1ydC5mguqAVg6RhdkSWQFj2uxfaq/BrIZOLEWgZdALIDvcMcZLD8ZbLC9de4yR1sYMi4G20S4Q/PWeJYxTOZn5zJXANZHIxAd4JWhPIloTJZhzMQduM89WQ3MUVAE/RnhAXpTycqys3NZALOBbB7kFrgLesQl2h45Fcj8L1tTSohUwuxhy8H/Qg6K7gIs+3kkaigQCOcyEXCHN07wyQazhrmIulvKMQAwMcmLNqyCVyMAI+BuxSMeTk3OPikLY2J1uE+VHQk6ANrhds+tNARqBeaGc72cK550FP4WhXmFmcMGhTwAR1ifOe3EvPqIegFmF+C8gVy0OfAaWQPMR7gF1OQKqGoBjq90HPMP01BUjPOqGFksC4emE48tWQAH0YmvOgF3DST6xieJgHAWxPAHMuNhrImIdvoNOKNWIOcE+UXE0pYAnkX6uhWsgVXDxHdTfCmrEEmMB2zMFimLVOtiiajxiGWrbU52EeCdyOwPEQD8LqyPH9Ti2kgYMf4OhSKB7qYILbBv3CuVTJ11Y80oaseiMWOONc/Y7kJYe0xL2f0BaiFTxknHO5HaMGMublKwxFGzYdWsBF174H/QDknhTHmHHN39iWFnkZx8lPyM8WHfYELmlLKtgWNmFNzQcC1b47gJ4hL19i7o65dhH0Negbca8vONZoP7doIeOC9zXm8RjuL0Gf4d4OYaU5ljo3GYiqzrWQHfJxA6ALhDpVKv9qYeZA8eM3EhfPSCmpuD0AAAAASUVORK5CYII='; | |
| if (!isDefined(iconData) || !isDefined(iconData.iconUrl)) { | |
| return new L.Icon.Default({ | |
| iconUrl: base64icon, | |
| shadowUrl: base64shadow, | |
| iconSize: [25, 41], | |
| iconAnchor: [12, 41], | |
| popupAnchor: [1, -34], | |
| shadowSize: [41, 41], | |
| }); | |
| } | |
| return new L.Icon(iconData); | |
| }; | |
| var _resetMarkerGroup = function(groupName) { | |
| if (isDefined(groups[groupName])) { | |
| groups.splice(groupName, 1); | |
| } | |
| }; | |
| var _resetMarkerGroups = function() { | |
| groups = {}; | |
| }; | |
| var _deleteMarker = function(marker, map, layers) { | |
| marker.closePopup(); | |
| // There is no easy way to know if a marker is added to a layer, so we search for it | |
| // if there are overlays | |
| if (isDefined(layers) && isDefined(layers.overlays)) { | |
| for (var key in layers.overlays) { | |
| if (layers.overlays[key] instanceof L.LayerGroup || layers.overlays[key] instanceof L.FeatureGroup) { | |
| if (layers.overlays[key].hasLayer(marker)) { | |
| layers.overlays[key].removeLayer(marker); | |
| return; | |
| } | |
| } | |
| } | |
| } | |
| if (isDefined(groups)) { | |
| for (var groupKey in groups) { | |
| if (groups[groupKey].hasLayer(marker)) { | |
| groups[groupKey].removeLayer(marker); | |
| } | |
| } | |
| } | |
| if (map.hasLayer(marker)) { | |
| map.removeLayer(marker); | |
| } | |
| }; | |
| var adjustPopupPan = function(marker, map) { | |
| var containerHeight = marker._popup._container.offsetHeight; | |
| var layerPos = new L.Point(marker._popup._containerLeft, -containerHeight - marker._popup._containerBottom); | |
| var containerPos = map.layerPointToContainerPoint(layerPos); | |
| if (containerPos !== null) { | |
| marker._popup._adjustPan(); | |
| } | |
| }; | |
| var compilePopup = function(marker, markerScope) { | |
| $compile(marker._popup._contentNode)(markerScope); | |
| }; | |
| var updatePopup = function(marker, markerScope, map) { | |
| //The innerText should be more than 1 once angular has compiled. | |
| //We need to keep trying until angular has compiled before we _updateLayout and _updatePosition | |
| //This should take care of any scenario , eg ngincludes, whatever. | |
| //Is there a better way to check for this? | |
| var innerText = marker._popup._contentNode.innerText || marker._popup._contentNode.textContent; | |
| if (innerText.length < 1) { | |
| $timeout(function() { | |
| updatePopup(marker, markerScope, map); | |
| }); | |
| } | |
| //cause a reflow - this is also very important - if we don't do this then the widths are from before $compile | |
| var reflow = marker._popup._contentNode.offsetWidth; | |
| marker._popup._updateLayout(); | |
| marker._popup._updatePosition(); | |
| if (marker._popup.options.autoPan) { | |
| adjustPopupPan(marker, map); | |
| } | |
| //using / returning reflow so jshint doesn't moan | |
| return reflow; | |
| }; | |
| var _manageOpenPopup = function(marker, markerData, map) { | |
| // The marker may provide a scope returning function used to compile the message | |
| // default to $rootScope otherwise | |
| var markerScope = angular.isFunction(markerData.getMessageScope) ? markerData.getMessageScope() : $rootScope; | |
| var compileMessage = isDefined(markerData.compileMessage) ? markerData.compileMessage : true; | |
| if (compileMessage) { | |
| if (!isDefined(marker._popup) || !isDefined(marker._popup._contentNode)) { | |
| $log.error(errorHeader + 'Popup is invalid or does not have any content.'); | |
| return false; | |
| } | |
| compilePopup(marker, markerScope); | |
| updatePopup(marker, markerData, map); | |
| } | |
| }; | |
| var _manageOpenLabel = function(marker, markerData) { | |
| var markerScope = angular.isFunction(markerData.getMessageScope) ? markerData.getMessageScope() : $rootScope; | |
| var labelScope = angular.isFunction(markerData.getLabelScope) ? markerData.getLabelScope() : markerScope; | |
| var compileMessage = isDefined(markerData.compileMessage) ? markerData.compileMessage : true; | |
| if (Helpers.LabelPlugin.isLoaded() && isDefined(markerData.label)) { | |
| if (isDefined(markerData.label.options) && markerData.label.options.noHide === true) { | |
| marker.showLabel(); | |
| } | |
| if (compileMessage && isDefined(marker.label)) { | |
| $compile(marker.label._container)(labelScope); | |
| } | |
| } | |
| }; | |
| var _updateMarker = function(markerData, oldMarkerData, marker, name, leafletScope, layers, map) { | |
| if (!isDefined(oldMarkerData)) { | |
| return; | |
| } | |
| // Update the lat-lng property (always present in marker properties) | |
| if (!geoHlp.validateCoords(markerData)) { | |
| $log.warn('There are problems with lat-lng data, please verify your marker model'); | |
| _deleteMarker(marker, map, layers); | |
| return; | |
| } | |
| // watch is being initialized if old and new object is the same | |
| var isInitializing = markerData === oldMarkerData; | |
| // Update marker rotation | |
| if (isDefined(markerData.iconAngle) && oldMarkerData.iconAngle !== markerData.iconAngle) { | |
| marker.setIconAngle(markerData.iconAngle); | |
| } | |
| // It is possible that the layer has been removed or the layer marker does not exist | |
| // Update the layer group if present or move it to the map if not | |
| if (!isString(markerData.layer)) { | |
| // There is no layer information, we move the marker to the map if it was in a layer group | |
| if (isString(oldMarkerData.layer)) { | |
| // Remove from the layer group that is supposed to be | |
| if (isDefined(layers.overlays[oldMarkerData.layer]) && layers.overlays[oldMarkerData.layer].hasLayer(marker)) { | |
| layers.overlays[oldMarkerData.layer].removeLayer(marker); | |
| marker.closePopup(); | |
| } | |
| // Test if it is not on the map and add it | |
| if (!map.hasLayer(marker)) { | |
| map.addLayer(marker); | |
| } | |
| } | |
| } | |
| if ((isNumber(markerData.opacity) || isNumber(parseFloat(markerData.opacity))) && markerData.opacity !== oldMarkerData.opacity) { | |
| // There was a different opacity so we update it | |
| marker.setOpacity(markerData.opacity); | |
| } | |
| if (isString(markerData.layer) && oldMarkerData.layer !== markerData.layer) { | |
| // If it was on a layer group we have to remove it | |
| if (isString(oldMarkerData.layer) && isDefined(layers.overlays[oldMarkerData.layer]) && layers.overlays[oldMarkerData.layer].hasLayer(marker)) { | |
| layers.overlays[oldMarkerData.layer].removeLayer(marker); | |
| } | |
| marker.closePopup(); | |
| // Remove it from the map in case the new layer is hidden or there is an error in the new layer | |
| if (map.hasLayer(marker)) { | |
| map.removeLayer(marker); | |
| } | |
| // The markerData.layer is defined so we add the marker to the layer if it is different from the old data | |
| if (!isDefined(layers.overlays[markerData.layer])) { | |
| $log.error(errorHeader + 'You must use a name of an existing layer'); | |
| return; | |
| } | |
| // Is a group layer? | |
| var layerGroup = layers.overlays[markerData.layer]; | |
| if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) { | |
| $log.error(errorHeader + 'A marker can only be added to a layer of type "group" or "featureGroup"'); | |
| return; | |
| } | |
| // The marker goes to a correct layer group, so first of all we add it | |
| layerGroup.addLayer(marker); | |
| // The marker is automatically added to the map depending on the visibility | |
| // of the layer, so we only have to open the popup if the marker is in the map | |
| if (map.hasLayer(marker) && markerData.focus === true) { | |
| marker.openPopup(); | |
| } | |
| } | |
| // Update the draggable property | |
| if (markerData.draggable !== true && oldMarkerData.draggable === true && (isDefined(marker.dragging))) { | |
| marker.dragging.disable(); | |
| } | |
| if (markerData.draggable === true && oldMarkerData.draggable !== true) { | |
| // The markerData.draggable property must be true so we update if there wasn't a previous value or it wasn't true | |
| if (marker.dragging) { | |
| marker.dragging.enable(); | |
| } else { | |
| if (L.Handler.MarkerDrag) { | |
| marker.dragging = new L.Handler.MarkerDrag(marker); | |
| marker.options.draggable = true; | |
| marker.dragging.enable(); | |
| } | |
| } | |
| } | |
| // Update the icon property | |
| if (!isObject(markerData.icon)) { | |
| // If there is no icon property or it's not an object | |
| if (isObject(oldMarkerData.icon)) { | |
| // If there was an icon before restore to the default | |
| marker.setIcon(createLeafletIcon()); | |
| marker.closePopup(); | |
| marker.unbindPopup(); | |
| if (isString(markerData.message)) { | |
| marker.bindPopup(markerData.message, markerData.popupOptions); | |
| } | |
| } | |
| } | |
| if (isObject(markerData.icon) && isObject(oldMarkerData.icon) && !angular.equals(markerData.icon, oldMarkerData.icon)) { | |
| var dragG = false; | |
| if (marker.dragging) { | |
| dragG = marker.dragging.enabled(); | |
| } | |
| marker.setIcon(createLeafletIcon(markerData.icon)); | |
| if (dragG) { | |
| marker.dragging.enable(); | |
| } | |
| marker.closePopup(); | |
| marker.unbindPopup(); | |
| if (isString(markerData.message)) { | |
| marker.bindPopup(markerData.message, markerData.popupOptions); | |
| // if marker has been already focused, reopen popup | |
| if (map.hasLayer(marker) && markerData.focus === true) { | |
| marker.openPopup(); | |
| } | |
| } | |
| } | |
| // Update the Popup message property | |
| if (!isString(markerData.message) && isString(oldMarkerData.message)) { | |
| marker.closePopup(); | |
| marker.unbindPopup(); | |
| } | |
| // Update the label content or bind a new label if the old one has been removed. | |
| if (Helpers.LabelPlugin.isLoaded()) { | |
| if (isDefined(markerData.label) && isDefined(markerData.label.message)) { | |
| if ('label' in oldMarkerData && 'message' in oldMarkerData.label && !angular.equals(markerData.label.message, oldMarkerData.label.message)) { | |
| marker.updateLabelContent(markerData.label.message); | |
| } else if (!angular.isFunction(marker.getLabel) || angular.isFunction(marker.getLabel) && !isDefined(marker.getLabel())) { | |
| marker.bindLabel(markerData.label.message, markerData.label.options); | |
| _manageOpenLabel(marker, markerData); | |
| } else { | |
| _manageOpenLabel(marker, markerData); | |
| } | |
| } else if (!('label' in markerData && !('message' in markerData.label))) { | |
| if (angular.isFunction(marker.unbindLabel)) { | |
| marker.unbindLabel(); | |
| } | |
| } | |
| } | |
| // There is some text in the popup, so we must show the text or update existing | |
| if (isString(markerData.message) && !isString(oldMarkerData.message)) { | |
| // There was no message before so we create it | |
| marker.bindPopup(markerData.message, markerData.popupOptions); | |
| } | |
| if (isString(markerData.message) && isString(oldMarkerData.message) && markerData.message !== oldMarkerData.message) { | |
| // There was a different previous message so we update it | |
| marker.setPopupContent(markerData.message); | |
| } | |
| // Update the focus property | |
| var updatedFocus = false; | |
| if (markerData.focus !== true && oldMarkerData.focus === true) { | |
| // If there was a focus property and was true we turn it off | |
| marker.closePopup(); | |
| updatedFocus = true; | |
| } | |
| // The markerData.focus property must be true so we update if there wasn't a previous value or it wasn't true | |
| if (markerData.focus === true && (!isDefined(oldMarkerData.focus) || oldMarkerData.focus === false) || (isInitializing && markerData.focus === true)) { | |
| // Reopen the popup when focus is still true | |
| marker.openPopup(); | |
| updatedFocus = true; | |
| } | |
| // zIndexOffset adjustment | |
| if (oldMarkerData.zIndexOffset !== markerData.zIndexOffset) { | |
| marker.setZIndexOffset(markerData.zIndexOffset); | |
| } | |
| var markerLatLng = marker.getLatLng(); | |
| var isCluster = (isString(markerData.layer) && Helpers.MarkerClusterPlugin.is(layers.overlays[markerData.layer])); | |
| // If the marker is in a cluster it has to be removed and added to the layer when the location is changed | |
| if (isCluster) { | |
| // The focus has changed even by a user click or programatically | |
| if (updatedFocus) { | |
| // We only have to update the location if it was changed programatically, because it was | |
| // changed by a user drag the marker data has already been updated by the internal event | |
| // listened by the directive | |
| if ((markerData.lat !== oldMarkerData.lat) || (markerData.lng !== oldMarkerData.lng)) { | |
| layers.overlays[markerData.layer].removeLayer(marker); | |
| marker.setLatLng([markerData.lat, markerData.lng]); | |
| layers.overlays[markerData.layer].addLayer(marker); | |
| } | |
| } else { | |
| // The marker has possibly moved. It can be moved by a user drag (marker location and data are equal but old | |
| // data is diferent) or programatically (marker location and data are diferent) | |
| if ((markerLatLng.lat !== markerData.lat) || (markerLatLng.lng !== markerData.lng)) { | |
| // The marker was moved by a user drag | |
| layers.overlays[markerData.layer].removeLayer(marker); | |
| marker.setLatLng([markerData.lat, markerData.lng]); | |
| layers.overlays[markerData.layer].addLayer(marker); | |
| } else if ((markerData.lat !== oldMarkerData.lat) || (markerData.lng !== oldMarkerData.lng)) { | |
| // The marker was moved programatically | |
| layers.overlays[markerData.layer].removeLayer(marker); | |
| marker.setLatLng([markerData.lat, markerData.lng]); | |
| layers.overlays[markerData.layer].addLayer(marker); | |
| } else if (isObject(markerData.icon) && isObject(oldMarkerData.icon) && !angular.equals(markerData.icon, oldMarkerData.icon)) { | |
| layers.overlays[markerData.layer].removeLayer(marker); | |
| layers.overlays[markerData.layer].addLayer(marker); | |
| } | |
| } | |
| } else if (markerLatLng.lat !== markerData.lat || markerLatLng.lng !== markerData.lng) { | |
| marker.setLatLng([markerData.lat, markerData.lng]); | |
| } | |
| }; | |
| return { | |
| resetMarkerGroup: _resetMarkerGroup, | |
| resetMarkerGroups: _resetMarkerGroups, | |
| deleteMarker: _deleteMarker, | |
| manageOpenPopup: _manageOpenPopup, | |
| manageOpenLabel: _manageOpenLabel, | |
| createMarker: function(markerData) { | |
| if (!isDefined(markerData) || !geoHlp.validateCoords(markerData)) { | |
| $log.error(errorHeader + 'The marker definition is not valid.'); | |
| return; | |
| } | |
| var coords = geoHlp.getCoords(markerData); | |
| if (!isDefined(coords)) { | |
| $log.error(errorHeader + 'Unable to get coordinates from markerData.'); | |
| return; | |
| } | |
| var markerOptions = { | |
| icon: createLeafletIcon(markerData.icon), | |
| title: isDefined(markerData.title) ? markerData.title : '', | |
| draggable: isDefined(markerData.draggable) ? markerData.draggable : false, | |
| clickable: isDefined(markerData.clickable) ? markerData.clickable : true, | |
| riseOnHover: isDefined(markerData.riseOnHover) ? markerData.riseOnHover : false, | |
| zIndexOffset: isDefined(markerData.zIndexOffset) ? markerData.zIndexOffset : 0, | |
| iconAngle: isDefined(markerData.iconAngle) ? markerData.iconAngle : 0, | |
| }; | |
| // Add any other options not added above to markerOptions | |
| for (var markerDatum in markerData) { | |
| if (markerData.hasOwnProperty(markerDatum) && !markerOptions.hasOwnProperty(markerDatum)) { | |
| markerOptions[markerDatum] = markerData[markerDatum]; | |
| } | |
| } | |
| var marker = new L.marker(coords, markerOptions); | |
| if (!isString(markerData.message)) { | |
| marker.unbindPopup(); | |
| } | |
| return marker; | |
| }, | |
| addMarkerToGroup: function(marker, groupName, groupOptions, map) { | |
| if (!isString(groupName)) { | |
| $log.error(errorHeader + 'The marker group you have specified is invalid.'); | |
| return; | |
| } | |
| if (!MarkerClusterPlugin.isLoaded()) { | |
| $log.error(errorHeader + 'The MarkerCluster plugin is not loaded.'); | |
| return; | |
| } | |
| if (!isDefined(groups[groupName])) { | |
| groups[groupName] = new L.MarkerClusterGroup(groupOptions); | |
| map.addLayer(groups[groupName]); | |
| } | |
| groups[groupName].addLayer(marker); | |
| }, | |
| listenMarkerEvents: function(marker, markerData, leafletScope, doWatch, map) { | |
| marker.on('popupopen', function(/* event */) { | |
| safeApply(leafletScope, function() { | |
| if (isDefined(marker._popup) || isDefined(marker._popup._contentNode)) { | |
| markerData.focus = true; | |
| _manageOpenPopup(marker, markerData, map);//needed since markerData is now a copy | |
| } | |
| }); | |
| }); | |
| marker.on('popupclose', function(/* event */) { | |
| safeApply(leafletScope, function() { | |
| markerData.focus = false; | |
| }); | |
| }); | |
| marker.on('add', function(/* event */) { | |
| safeApply(leafletScope, function() { | |
| if ('label' in markerData) | |
| _manageOpenLabel(marker, markerData); | |
| }); | |
| }); | |
| }, | |
| updateMarker: _updateMarker, | |
| addMarkerWatcher: function(marker, name, leafletScope, layers, map, isDeepWatch) { | |
| var markerWatchPath = Helpers.getObjectArrayPath('markers.' + name); | |
| isDeepWatch = defaultTo(isDeepWatch, true); | |
| var clearWatch = leafletScope.$watch(markerWatchPath, function(markerData, oldMarkerData) { | |
| if (!isDefined(markerData)) { | |
| _deleteMarker(marker, map, layers); | |
| clearWatch(); | |
| return; | |
| } | |
| _updateMarker(markerData, oldMarkerData, marker, name, leafletScope, layers, map); | |
| }, isDeepWatch); | |
| }, | |
| string: _string, | |
| log: _log, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').factory('leafletPathsHelpers', ["$rootScope", "$log", "leafletHelpers", function($rootScope, $log, leafletHelpers) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var isArray = leafletHelpers.isArray; | |
| var isNumber = leafletHelpers.isNumber; | |
| var isValidPoint = leafletHelpers.isValidPoint; | |
| var availableOptions = [ | |
| // Path options | |
| 'stroke', 'weight', 'color', 'opacity', | |
| 'fill', 'fillColor', 'fillOpacity', | |
| 'dashArray', 'lineCap', 'lineJoin', 'clickable', | |
| 'pointerEvents', 'className', | |
| // Polyline options | |
| 'smoothFactor', 'noClip', | |
| ]; | |
| function _convertToLeafletLatLngs(latlngs) { | |
| return latlngs.filter(function(latlng) { | |
| return isValidPoint(latlng); | |
| }).map(function(latlng) { | |
| return _convertToLeafletLatLng(latlng); | |
| }); | |
| } | |
| function _convertToLeafletLatLng(latlng) { | |
| if (isArray(latlng)) { | |
| return new L.LatLng(latlng[0], latlng[1]); | |
| } else { | |
| return new L.LatLng(latlng.lat, latlng.lng); | |
| } | |
| } | |
| function _convertToLeafletMultiLatLngs(paths) { | |
| return paths.map(function(latlngs) { | |
| return _convertToLeafletLatLngs(latlngs); | |
| }); | |
| } | |
| function _getOptions(path, defaults) { | |
| var options = {}; | |
| for (var i = 0; i < availableOptions.length; i++) { | |
| var optionName = availableOptions[i]; | |
| if (isDefined(path[optionName])) { | |
| options[optionName] = path[optionName]; | |
| } else if (isDefined(defaults.path[optionName])) { | |
| options[optionName] = defaults.path[optionName]; | |
| } | |
| } | |
| return options; | |
| } | |
| var _updatePathOptions = function(path, data) { | |
| var updatedStyle = {}; | |
| for (var i = 0; i < availableOptions.length; i++) { | |
| var optionName = availableOptions[i]; | |
| if (isDefined(data[optionName])) { | |
| updatedStyle[optionName] = data[optionName]; | |
| } | |
| } | |
| path.setStyle(data); | |
| }; | |
| var _isValidPolyline = function(latlngs) { | |
| if (!isArray(latlngs)) { | |
| return false; | |
| } | |
| for (var i = 0; i < latlngs.length; i++) { | |
| var point = latlngs[i]; | |
| if (!isValidPoint(point)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| }; | |
| var pathTypes = { | |
| polyline: { | |
| isValid: function(pathData) { | |
| var latlngs = pathData.latlngs; | |
| return _isValidPolyline(latlngs); | |
| }, | |
| createPath: function(options) { | |
| return new L.Polyline([], options); | |
| }, | |
| setPath: function(path, data) { | |
| path.setLatLngs(_convertToLeafletLatLngs(data.latlngs)); | |
| _updatePathOptions(path, data); | |
| return; | |
| }, | |
| }, | |
| multiPolyline: { | |
| isValid: function(pathData) { | |
| var latlngs = pathData.latlngs; | |
| if (!isArray(latlngs)) { | |
| return false; | |
| } | |
| for (var i in latlngs) { | |
| var polyline = latlngs[i]; | |
| if (!_isValidPolyline(polyline)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| }, | |
| createPath: function(options) { | |
| return new L.multiPolyline([[[0, 0], [1, 1]]], options); | |
| }, | |
| setPath: function(path, data) { | |
| path.setLatLngs(_convertToLeafletMultiLatLngs(data.latlngs)); | |
| _updatePathOptions(path, data); | |
| return; | |
| }, | |
| }, | |
| polygon: { | |
| isValid: function(pathData) { | |
| var latlngs = pathData.latlngs; | |
| return _isValidPolyline(latlngs); | |
| }, | |
| createPath: function(options) { | |
| return new L.Polygon([], options); | |
| }, | |
| setPath: function(path, data) { | |
| path.setLatLngs(_convertToLeafletLatLngs(data.latlngs)); | |
| _updatePathOptions(path, data); | |
| return; | |
| }, | |
| }, | |
| multiPolygon: { | |
| isValid: function(pathData) { | |
| var latlngs = pathData.latlngs; | |
| if (!isArray(latlngs)) { | |
| return false; | |
| } | |
| for (var i in latlngs) { | |
| var polyline = latlngs[i]; | |
| if (!_isValidPolyline(polyline)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| }, | |
| createPath: function(options) { | |
| return new L.MultiPolygon([[[0, 0], [1, 1], [0, 1]]], options); | |
| }, | |
| setPath: function(path, data) { | |
| path.setLatLngs(_convertToLeafletMultiLatLngs(data.latlngs)); | |
| _updatePathOptions(path, data); | |
| return; | |
| }, | |
| }, | |
| rectangle: { | |
| isValid: function(pathData) { | |
| var latlngs = pathData.latlngs; | |
| if (!isArray(latlngs) || latlngs.length !== 2) { | |
| return false; | |
| } | |
| for (var i in latlngs) { | |
| var point = latlngs[i]; | |
| if (!isValidPoint(point)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| }, | |
| createPath: function(options) { | |
| return new L.Rectangle([[0, 0], [1, 1]], options); | |
| }, | |
| setPath: function(path, data) { | |
| path.setBounds(new L.LatLngBounds(_convertToLeafletLatLngs(data.latlngs))); | |
| _updatePathOptions(path, data); | |
| }, | |
| }, | |
| circle: { | |
| isValid: function(pathData) { | |
| var point = pathData.latlngs; | |
| return isValidPoint(point) && isNumber(pathData.radius); | |
| }, | |
| createPath: function(options) { | |
| return new L.Circle([0, 0], 1, options); | |
| }, | |
| setPath: function(path, data) { | |
| path.setLatLng(_convertToLeafletLatLng(data.latlngs)); | |
| if (isDefined(data.radius)) { | |
| path.setRadius(data.radius); | |
| } | |
| _updatePathOptions(path, data); | |
| }, | |
| }, | |
| circleMarker: { | |
| isValid: function(pathData) { | |
| var point = pathData.latlngs; | |
| return isValidPoint(point) && isNumber(pathData.radius); | |
| }, | |
| createPath: function(options) { | |
| return new L.CircleMarker([0, 0], options); | |
| }, | |
| setPath: function(path, data) { | |
| path.setLatLng(_convertToLeafletLatLng(data.latlngs)); | |
| if (isDefined(data.radius)) { | |
| path.setRadius(data.radius); | |
| } | |
| _updatePathOptions(path, data); | |
| }, | |
| }, | |
| }; | |
| var _getPathData = function(path) { | |
| var pathData = {}; | |
| if (path.latlngs) { | |
| pathData.latlngs = path.latlngs; | |
| } | |
| if (path.radius) { | |
| pathData.radius = path.radius; | |
| } | |
| return pathData; | |
| }; | |
| return { | |
| setPathOptions: function(leafletPath, pathType, data) { | |
| if (!isDefined(pathType)) { | |
| pathType = 'polyline'; | |
| } | |
| pathTypes[pathType].setPath(leafletPath, data); | |
| }, | |
| createPath: function(name, path, defaults) { | |
| if (!isDefined(path.type)) { | |
| path.type = 'polyline'; | |
| } | |
| var options = _getOptions(path, defaults); | |
| var pathData = _getPathData(path); | |
| if (!pathTypes[path.type].isValid(pathData)) { | |
| $log.error('[AngularJS - Leaflet] Invalid data passed to the ' + path.type + ' path'); | |
| return; | |
| } | |
| return pathTypes[path.type].createPath(options); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive') | |
| .service('leafletWatchHelpers', function() { | |
| var _maybe = function(scope, watchFunctionName, thingToWatchStr, watchOptions, initCb) { | |
| //watchOptions.isDeep is/should be ignored in $watchCollection | |
| var unWatch = scope[watchFunctionName](thingToWatchStr, function(newValue, oldValue) { | |
| initCb(newValue, oldValue); | |
| if (!watchOptions.doWatch) | |
| unWatch(); | |
| }, watchOptions.isDeep); | |
| return unWatch; | |
| }; | |
| /* | |
| @name: maybeWatch | |
| @description: Utility to watch something once or forever. | |
| @returns unWatch function | |
| @param watchOptions - see markersWatchOptions and or derrivatives. This object is used | |
| to set watching to once and its watch depth. | |
| */ | |
| var _maybeWatch = function(scope, thingToWatchStr, watchOptions, initCb) { | |
| return _maybe(scope, '$watch', thingToWatchStr, watchOptions, initCb); | |
| }; | |
| /* | |
| @name: _maybeWatchCollection | |
| @description: Utility to watch something once or forever. | |
| @returns unWatch function | |
| @param watchOptions - see markersWatchOptions and or derrivatives. This object is used | |
| to set watching to once and its watch depth. | |
| */ | |
| var _maybeWatchCollection = function(scope, thingToWatchStr, watchOptions, initCb) { | |
| return _maybe(scope, '$watchCollection', thingToWatchStr, watchOptions, initCb); | |
| }; | |
| return { | |
| maybeWatch: _maybeWatch, | |
| maybeWatchCollection: _maybeWatchCollection, | |
| }; | |
| }); | |
| angular.module('leaflet-directive').factory('nominatimService', ["$q", "$http", "leafletHelpers", "leafletMapDefaults", function($q, $http, leafletHelpers, leafletMapDefaults) { | |
| var isDefined = leafletHelpers.isDefined; | |
| return { | |
| query: function(address, mapId) { | |
| var defaults = leafletMapDefaults.getDefaults(mapId); | |
| var url = defaults.nominatim.server; | |
| var df = $q.defer(); | |
| $http.get(url, { params: { format: 'json', limit: 1, q: address } }).success(function(data) { | |
| if (data.length > 0 && isDefined(data[0].boundingbox)) { | |
| df.resolve(data[0]); | |
| } else { | |
| df.reject('[Nominatim] Invalid address'); | |
| } | |
| }); | |
| return df.promise; | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').directive('bounds', ["$log", "$timeout", "$http", "leafletHelpers", "nominatimService", "leafletBoundsHelpers", function($log, $timeout, $http, leafletHelpers, nominatimService, leafletBoundsHelpers) { | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: ['leaflet'], | |
| link: function(scope, element, attrs, controller) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var createLeafletBounds = leafletBoundsHelpers.createLeafletBounds; | |
| var leafletScope = controller[0].getLeafletScope(); | |
| var mapController = controller[0]; | |
| var errorHeader = leafletHelpers.errorHeader + ' [Bounds] '; | |
| var emptyBounds = function(bounds) { | |
| return (bounds._southWest.lat === 0 && bounds._southWest.lng === 0 && | |
| bounds._northEast.lat === 0 && bounds._northEast.lng === 0); | |
| }; | |
| mapController.getMap().then(function(map) { | |
| leafletScope.$on('boundsChanged', function(event) { | |
| var scope = event.currentScope; | |
| var bounds = map.getBounds(); | |
| if (emptyBounds(bounds) || scope.settingBoundsFromScope) { | |
| return; | |
| } | |
| scope.settingBoundsFromLeaflet = true; | |
| var newScopeBounds = { | |
| northEast: { | |
| lat: bounds._northEast.lat, | |
| lng: bounds._northEast.lng, | |
| }, | |
| southWest: { | |
| lat: bounds._southWest.lat, | |
| lng: bounds._southWest.lng, | |
| }, | |
| options: bounds.options, | |
| }; | |
| if (!angular.equals(scope.bounds, newScopeBounds)) { | |
| scope.bounds = newScopeBounds; | |
| } | |
| $timeout(function() { | |
| scope.settingBoundsFromLeaflet = false; | |
| }); | |
| }); | |
| var lastNominatimQuery; | |
| leafletScope.$watch('bounds', function(bounds) { | |
| if (scope.settingBoundsFromLeaflet) | |
| return; | |
| if (isDefined(bounds.address) && bounds.address !== lastNominatimQuery) { | |
| scope.settingBoundsFromScope = true; | |
| nominatimService.query(bounds.address, attrs.id).then(function(data) { | |
| var b = data.boundingbox; | |
| var newBounds = [[b[0], b[2]], [b[1], b[3]]]; | |
| map.fitBounds(newBounds); | |
| }, function(errMsg) { | |
| $log.error(errorHeader + ' ' + errMsg + '.'); | |
| }); | |
| lastNominatimQuery = bounds.address; | |
| $timeout(function() { | |
| scope.settingBoundsFromScope = false; | |
| }); | |
| return; | |
| } | |
| var leafletBounds = createLeafletBounds(bounds); | |
| if (leafletBounds && !map.getBounds().equals(leafletBounds)) { | |
| scope.settingBoundsFromScope = true; | |
| map.fitBounds(leafletBounds, bounds.options); | |
| $timeout(function() { | |
| scope.settingBoundsFromScope = false; | |
| }); | |
| } | |
| }, true); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| var centerDirectiveTypes = ['center', 'lfCenter']; | |
| var centerDirectives = {}; | |
| centerDirectiveTypes.forEach(function(directiveName) { | |
| centerDirectives[directiveName] = ['$log', '$q', '$location', '$timeout', 'leafletMapDefaults', 'leafletHelpers', | |
| 'leafletBoundsHelpers', 'leafletMapEvents', | |
| function($log, $q, $location, $timeout, leafletMapDefaults, leafletHelpers, | |
| leafletBoundsHelpers, leafletMapEvents) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var isNumber = leafletHelpers.isNumber; | |
| var isSameCenterOnMap = leafletHelpers.isSameCenterOnMap; | |
| var safeApply = leafletHelpers.safeApply; | |
| var isValidCenter = leafletHelpers.isValidCenter; | |
| var isValidBounds = leafletBoundsHelpers.isValidBounds; | |
| var isUndefinedOrEmpty = leafletHelpers.isUndefinedOrEmpty; | |
| var errorHeader = leafletHelpers.errorHeader; | |
| var shouldInitializeMapWithBounds = function(bounds, center) { | |
| return isDefined(bounds) && isValidBounds(bounds) && isUndefinedOrEmpty(center); | |
| }; | |
| var _leafletCenter; | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: 'leaflet', | |
| controller: function() { | |
| _leafletCenter = $q.defer(); | |
| this.getCenter = function() { | |
| return _leafletCenter.promise; | |
| }; | |
| }, | |
| link: function(scope, element, attrs, controller) { | |
| var leafletScope = controller.getLeafletScope(); | |
| var centerModel = leafletScope[directiveName]; | |
| controller.getMap().then(function(map) { | |
| var defaults = leafletMapDefaults.getDefaults(attrs.id); | |
| if (attrs[directiveName].search('-') !== -1) { | |
| $log.error(errorHeader + ' The "center" variable can\'t use a "-" on its key name: "' + attrs[directiveName] + '".'); | |
| map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); | |
| return; | |
| } else if (shouldInitializeMapWithBounds(leafletScope.bounds, centerModel)) { | |
| map.fitBounds(leafletBoundsHelpers.createLeafletBounds(leafletScope.bounds), leafletScope.bounds.options); | |
| centerModel = map.getCenter(); | |
| safeApply(leafletScope, function(scope) { | |
| angular.extend(scope[directiveName], { | |
| lat: map.getCenter().lat, | |
| lng: map.getCenter().lng, | |
| zoom: map.getZoom(), | |
| autoDiscover: false, | |
| }); | |
| }); | |
| safeApply(leafletScope, function(scope) { | |
| var mapBounds = map.getBounds(); | |
| scope.bounds = { | |
| northEast: { | |
| lat: mapBounds._northEast.lat, | |
| lng: mapBounds._northEast.lng, | |
| }, | |
| southWest: { | |
| lat: mapBounds._southWest.lat, | |
| lng: mapBounds._southWest.lng, | |
| }, | |
| }; | |
| }); | |
| } else if (!isDefined(centerModel)) { | |
| $log.error(errorHeader + ' The "center" property is not defined in the main scope'); | |
| map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); | |
| return; | |
| } else if (!(isDefined(centerModel.lat) && isDefined(centerModel.lng)) && !isDefined(centerModel.autoDiscover)) { | |
| angular.copy(defaults.center, centerModel); | |
| } | |
| var urlCenterHash; | |
| var mapReady; | |
| if (attrs.urlHashCenter === 'yes') { | |
| var extractCenterFromUrl = function() { | |
| var search = $location.search(); | |
| var centerParam; | |
| if (isDefined(search.c)) { | |
| var cParam = search.c.split(':'); | |
| if (cParam.length === 3) { | |
| centerParam = { | |
| lat: parseFloat(cParam[0]), | |
| lng: parseFloat(cParam[1]), | |
| zoom: parseInt(cParam[2], 10), | |
| }; | |
| } | |
| } | |
| return centerParam; | |
| }; | |
| urlCenterHash = extractCenterFromUrl(); | |
| leafletScope.$on('$locationChangeSuccess', function(event) { | |
| var scope = event.currentScope; | |
| //$log.debug("updated location..."); | |
| var urlCenter = extractCenterFromUrl(); | |
| if (isDefined(urlCenter) && !isSameCenterOnMap(urlCenter, map)) { | |
| //$log.debug("updating center model...", urlCenter); | |
| angular.extend(scope[directiveName], { | |
| lat: urlCenter.lat, | |
| lng: urlCenter.lng, | |
| zoom: urlCenter.zoom, | |
| }); | |
| } | |
| }); | |
| } | |
| leafletScope.$watch(directiveName, function(center) { | |
| if (leafletScope.settingCenterFromLeaflet) | |
| return; | |
| //$log.debug("updated center model..."); | |
| // The center from the URL has priority | |
| if (isDefined(urlCenterHash)) { | |
| angular.copy(urlCenterHash, center); | |
| urlCenterHash = undefined; | |
| } | |
| if (!isValidCenter(center) && center.autoDiscover !== true) { | |
| $log.warn(errorHeader + ' invalid \'center\''); | |
| //map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); | |
| return; | |
| } | |
| if (center.autoDiscover === true) { | |
| if (!isNumber(center.zoom)) { | |
| map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); | |
| } | |
| if (isNumber(center.zoom) && center.zoom > defaults.center.zoom) { | |
| map.locate({ | |
| setView: true, | |
| maxZoom: center.zoom, | |
| }); | |
| } else if (isDefined(defaults.maxZoom)) { | |
| map.locate({ | |
| setView: true, | |
| maxZoom: defaults.maxZoom, | |
| }); | |
| } else { | |
| map.locate({ | |
| setView: true, | |
| }); | |
| } | |
| return; | |
| } | |
| if (mapReady && isSameCenterOnMap(center, map)) { | |
| //$log.debug("no need to update map again."); | |
| return; | |
| } | |
| //$log.debug("updating map center...", center); | |
| leafletScope.settingCenterFromScope = true; | |
| map.setView([center.lat, center.lng], center.zoom); | |
| leafletMapEvents.notifyCenterChangedToBounds(leafletScope, map); | |
| $timeout(function() { | |
| leafletScope.settingCenterFromScope = false; | |
| //$log.debug("allow center scope updates"); | |
| }); | |
| }, true); | |
| map.whenReady(function() { | |
| mapReady = true; | |
| }); | |
| map.on('moveend', function(/* event */) { | |
| // Resolve the center after the first map position | |
| _leafletCenter.resolve(); | |
| leafletMapEvents.notifyCenterUrlHashChanged(leafletScope, map, attrs, $location.search()); | |
| //$log.debug("updated center on map..."); | |
| if (isSameCenterOnMap(centerModel, map) || leafletScope.settingCenterFromScope) { | |
| //$log.debug("same center in model, no need to update again."); | |
| return; | |
| } | |
| leafletScope.settingCenterFromLeaflet = true; | |
| safeApply(leafletScope, function(scope) { | |
| if (!leafletScope.settingCenterFromScope) { | |
| //$log.debug("updating center model...", map.getCenter(), map.getZoom()); | |
| angular.extend(scope[directiveName], { | |
| lat: map.getCenter().lat, | |
| lng: map.getCenter().lng, | |
| zoom: map.getZoom(), | |
| autoDiscover: false, | |
| }); | |
| } | |
| leafletMapEvents.notifyCenterChangedToBounds(leafletScope, map); | |
| $timeout(function() { | |
| leafletScope.settingCenterFromLeaflet = false; | |
| }); | |
| }); | |
| }); | |
| if (centerModel.autoDiscover === true) { | |
| map.on('locationerror', function() { | |
| $log.warn(errorHeader + ' The Geolocation API is unauthorized on this page.'); | |
| if (isValidCenter(centerModel)) { | |
| map.setView([centerModel.lat, centerModel.lng], centerModel.zoom); | |
| leafletMapEvents.notifyCenterChangedToBounds(leafletScope, map); | |
| } else { | |
| map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); | |
| leafletMapEvents.notifyCenterChangedToBounds(leafletScope, map); | |
| } | |
| }); | |
| } | |
| }); | |
| }, | |
| }; | |
| }, | |
| ]; | |
| }); | |
| centerDirectiveTypes.forEach(function(dirType) { | |
| angular.module('leaflet-directive').directive(dirType, centerDirectives[dirType]); | |
| }); | |
| angular.module('leaflet-directive').directive('controls', ["$log", "leafletHelpers", "leafletControlHelpers", function($log, leafletHelpers, leafletControlHelpers) { | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: '?^leaflet', | |
| link: function(scope, element, attrs, controller) { | |
| if (!controller) { | |
| return; | |
| } | |
| var createControl = leafletControlHelpers.createControl; | |
| var isValidControlType = leafletControlHelpers.isValidControlType; | |
| var leafletScope = controller.getLeafletScope(); | |
| var isDefined = leafletHelpers.isDefined; | |
| var isArray = leafletHelpers.isArray; | |
| var leafletControls = {}; | |
| var errorHeader = leafletHelpers.errorHeader + ' [Controls] '; | |
| controller.getMap().then(function(map) { | |
| leafletScope.$watchCollection('controls', function(newControls) { | |
| // Delete controls from the array | |
| for (var name in leafletControls) { | |
| if (!isDefined(newControls[name])) { | |
| if (map.hasControl(leafletControls[name])) { | |
| map.removeControl(leafletControls[name]); | |
| } | |
| delete leafletControls[name]; | |
| } | |
| } | |
| for (var newName in newControls) { | |
| var control; | |
| var controlType = isDefined(newControls[newName].type) ? newControls[newName].type : newName; | |
| if (!isValidControlType(controlType)) { | |
| $log.error(errorHeader + ' Invalid control type: ' + controlType + '.'); | |
| return; | |
| } | |
| if (controlType !== 'custom') { | |
| control = createControl(controlType, newControls[newName]); | |
| map.addControl(control); | |
| leafletControls[newName] = control; | |
| } else { | |
| var customControlValue = newControls[newName]; | |
| if (isArray(customControlValue)) { | |
| for (var i in customControlValue) { | |
| var customControl = customControlValue[i]; | |
| map.addControl(customControl); | |
| leafletControls[newName] = !isDefined(leafletControls[newName]) ? [customControl] : leafletControls[newName].concat([customControl]); | |
| } | |
| } else { | |
| map.addControl(customControlValue); | |
| leafletControls[newName] = customControlValue; | |
| } | |
| } | |
| } | |
| }); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').directive('decorations', ["$log", "leafletHelpers", function($log, leafletHelpers) { | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: 'leaflet', | |
| link: function(scope, element, attrs, controller) { | |
| var leafletScope = controller.getLeafletScope(); | |
| var PolylineDecoratorPlugin = leafletHelpers.PolylineDecoratorPlugin; | |
| var isDefined = leafletHelpers.isDefined; | |
| var leafletDecorations = {}; | |
| /* Creates an "empty" decoration with a set of coordinates, but no pattern. */ | |
| function createDecoration(options) { | |
| if (isDefined(options) && isDefined(options.coordinates)) { | |
| if (!PolylineDecoratorPlugin.isLoaded()) { | |
| $log.error('[AngularJS - Leaflet] The PolylineDecorator Plugin is not loaded.'); | |
| } | |
| } | |
| return L.polylineDecorator(options.coordinates); | |
| } | |
| /* Updates the path and the patterns for the provided decoration, and returns the decoration. */ | |
| function setDecorationOptions(decoration, options) { | |
| if (isDefined(decoration) && isDefined(options)) { | |
| if (isDefined(options.coordinates) && isDefined(options.patterns)) { | |
| decoration.setPaths(options.coordinates); | |
| decoration.setPatterns(options.patterns); | |
| return decoration; | |
| } | |
| } | |
| } | |
| controller.getMap().then(function(map) { | |
| leafletScope.$watch('decorations', function(newDecorations) { | |
| for (var name in leafletDecorations) { | |
| if (!isDefined(newDecorations[name]) || !angular.equals(newDecorations[name], leafletDecorations)) { | |
| map.removeLayer(leafletDecorations[name]); | |
| delete leafletDecorations[name]; | |
| } | |
| } | |
| for (var newName in newDecorations) { | |
| var decorationData = newDecorations[newName]; | |
| var newDecoration = createDecoration(decorationData); | |
| if (isDefined(newDecoration)) { | |
| leafletDecorations[newName] = newDecoration; | |
| map.addLayer(newDecoration); | |
| setDecorationOptions(newDecoration, decorationData); | |
| } | |
| } | |
| }, true); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').directive('eventBroadcast', ["$log", "$rootScope", "leafletHelpers", "leafletMapEvents", "leafletIterators", function($log, $rootScope, leafletHelpers, leafletMapEvents, leafletIterators) { | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: 'leaflet', | |
| link: function(scope, element, attrs, controller) { | |
| var isObject = leafletHelpers.isObject; | |
| var isDefined = leafletHelpers.isDefined; | |
| var leafletScope = controller.getLeafletScope(); | |
| var eventBroadcast = leafletScope.eventBroadcast; | |
| var availableMapEvents = leafletMapEvents.getAvailableMapEvents(); | |
| var addEvents = leafletMapEvents.addEvents; | |
| controller.getMap().then(function(map) { | |
| var mapEvents = []; | |
| var logic = 'broadcast'; | |
| // We have a possible valid object | |
| if (!isDefined(eventBroadcast.map)) { | |
| // We do not have events enable/disable do we do nothing (all enabled by default) | |
| mapEvents = availableMapEvents; | |
| } else if (!isObject(eventBroadcast.map)) { | |
| // Not a valid object | |
| $log.warn('[AngularJS - Leaflet] event-broadcast.map must be an object check your model.'); | |
| } else { | |
| // We have a possible valid map object | |
| // Event propadation logic | |
| if (eventBroadcast.map.logic !== 'emit' && eventBroadcast.map.logic !== 'broadcast') { | |
| // This is an error | |
| $log.warn('[AngularJS - Leaflet] Available event propagation logic are: \'emit\' or \'broadcast\'.'); | |
| } else { | |
| logic = eventBroadcast.map.logic; | |
| } | |
| if (!(isObject(eventBroadcast.map.enable) && eventBroadcast.map.enable.length >= 0)) { | |
| $log.warn('[AngularJS - Leaflet] event-broadcast.map.enable must be an object check your model.'); | |
| } else { | |
| // Enable events | |
| leafletIterators.each(eventBroadcast.map.enable, function(eventName) { | |
| // Do we have already the event enabled? | |
| if (mapEvents.indexOf(eventName) === -1 && availableMapEvents.indexOf(eventName) !== -1) { | |
| mapEvents.push(eventName); | |
| } | |
| }); | |
| } | |
| } | |
| // as long as the map is removed in the root leaflet directive we | |
| // do not need ot clean up the events as leaflet does it itself | |
| addEvents(map, mapEvents, 'eventName', leafletScope, logic); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive') | |
| .directive('geojson', ["$log", "$rootScope", "leafletData", "leafletHelpers", "leafletWatchHelpers", "leafletDirectiveControlsHelpers", "leafletIterators", "leafletGeoJsonEvents", function($log, $rootScope, leafletData, leafletHelpers, | |
| leafletWatchHelpers, leafletDirectiveControlsHelpers, leafletIterators, leafletGeoJsonEvents) { | |
| var _maybeWatch = leafletWatchHelpers.maybeWatch; | |
| var _watchOptions = leafletHelpers.watchOptions; | |
| var _extendDirectiveControls = leafletDirectiveControlsHelpers.extend; | |
| var hlp = leafletHelpers; | |
| var $it = leafletIterators; | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: 'leaflet', | |
| link: function(scope, element, attrs, controller) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var leafletScope = controller.getLeafletScope(); | |
| var leafletGeoJSON = {}; | |
| var _hasSetLeafletData = false; | |
| controller.getMap().then(function(map) { | |
| var watchOptions = leafletScope.geojsonWatchOptions || _watchOptions; | |
| var _hookUpEvents = function(geojson, maybeName) { | |
| var onEachFeature; | |
| if (angular.isFunction(geojson.onEachFeature)) { | |
| onEachFeature = geojson.onEachFeature; | |
| } else { | |
| onEachFeature = function(feature, layer) { | |
| if (leafletHelpers.LabelPlugin.isLoaded() && isDefined(feature.properties.description)) { | |
| layer.bindLabel(feature.properties.description); | |
| } | |
| leafletGeoJsonEvents.bindEvents(attrs.id, layer, null, feature, | |
| leafletScope, maybeName, | |
| {resetStyleOnMouseout: geojson.resetStyleOnMouseout, | |
| mapId: attrs.id, }); | |
| }; | |
| } | |
| return onEachFeature; | |
| }; | |
| var isNested = (hlp.isDefined(attrs.geojsonNested) && | |
| hlp.isTruthy(attrs.geojsonNested)); | |
| var _clean = function() { | |
| if (!leafletGeoJSON) | |
| return; | |
| var _remove = function(lObject) { | |
| if (isDefined(lObject) && map.hasLayer(lObject)) { | |
| map.removeLayer(lObject); | |
| } | |
| }; | |
| if (isNested) { | |
| $it.each(leafletGeoJSON, function(lObject) { | |
| _remove(lObject); | |
| }); | |
| return; | |
| } | |
| _remove(leafletGeoJSON); | |
| }; | |
| var _addGeojson = function(model, maybeName) { | |
| var geojson = angular.copy(model); | |
| if (!(isDefined(geojson) && isDefined(geojson.data))) { | |
| return; | |
| } | |
| var onEachFeature = _hookUpEvents(geojson, maybeName); | |
| if (!isDefined(geojson.options)) { | |
| //right here is why we use a clone / copy (we modify and thus) | |
| //would kick of a watcher.. we need to be more careful everywhere | |
| //for stuff like this | |
| geojson.options = { | |
| style: geojson.style, | |
| filter: geojson.filter, | |
| onEachFeature: onEachFeature, | |
| pointToLayer: geojson.pointToLayer, | |
| }; | |
| } | |
| var lObject = L.geoJson(geojson.data, geojson.options); | |
| if (maybeName && hlp.isString(maybeName)) { | |
| leafletGeoJSON[maybeName] = lObject; | |
| } else { | |
| leafletGeoJSON = lObject; | |
| } | |
| lObject.addTo(map); | |
| if (!_hasSetLeafletData) {//only do this once and play with the same ref forever | |
| _hasSetLeafletData = true; | |
| leafletData.setGeoJSON(leafletGeoJSON, attrs.id); | |
| } | |
| }; | |
| var _create = function(model) { | |
| _clean(); | |
| if (isNested) { | |
| if (!model || !Object.keys(model).length) | |
| return; | |
| $it.each(model, function(m, name) { | |
| //name could be layerName and or groupName | |
| //for now it is not tied to a layer | |
| _addGeojson(m, name); | |
| }); | |
| return; | |
| } | |
| _addGeojson(model); | |
| }; | |
| _extendDirectiveControls(attrs.id, 'geojson', _create, _clean); | |
| _maybeWatch(leafletScope, 'geojson', watchOptions, function(geojson) { | |
| _create(geojson); | |
| }); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').directive('layercontrol', ["$filter", "$log", "leafletData", "leafletHelpers", function($filter, $log, leafletData, leafletHelpers) { | |
| return { | |
| restrict: 'E', | |
| scope: { | |
| icons: '=?', | |
| autoHideOpacity: '=?', // Hide other opacity controls when one is activated. | |
| showGroups: '=?', // Hide other opacity controls when one is activated. | |
| title: '@', | |
| baseTitle: '@', | |
| overlaysTitle: '@', | |
| }, | |
| replace: true, | |
| transclude: false, | |
| require: '^leaflet', | |
| controller: ["$scope", "$element", "$sce", function($scope, $element, $sce) { | |
| $log.debug('[Angular Directive - Layers] layers', $scope, $element); | |
| var safeApply = leafletHelpers.safeApply; | |
| var isDefined = leafletHelpers.isDefined; | |
| angular.extend($scope, { | |
| baselayer: '', | |
| oldGroup: '', | |
| layerProperties: {}, | |
| groupProperties: {}, | |
| rangeIsSupported: leafletHelpers.rangeIsSupported(), | |
| changeBaseLayer: function(key, e) { | |
| leafletHelpers.safeApply($scope, function(scp) { | |
| scp.baselayer = key; | |
| leafletData.getMap().then(function(map) { | |
| leafletData.getLayers().then(function(leafletLayers) { | |
| if (map.hasLayer(leafletLayers.baselayers[key])) { | |
| return; | |
| } | |
| for (var i in scp.layers.baselayers) { | |
| scp.layers.baselayers[i].icon = scp.icons.unradio; | |
| if (map.hasLayer(leafletLayers.baselayers[i])) { | |
| map.removeLayer(leafletLayers.baselayers[i]); | |
| } | |
| } | |
| map.addLayer(leafletLayers.baselayers[key]); | |
| scp.layers.baselayers[key].icon = $scope.icons.radio; | |
| }); | |
| }); | |
| }); | |
| e.preventDefault(); | |
| }, | |
| moveLayer: function(ly, newIndex, e) { | |
| var delta = Object.keys($scope.layers.baselayers).length; | |
| if (newIndex >= (1 + delta) && newIndex <= ($scope.overlaysArray.length + delta)) { | |
| var oldLy; | |
| for (var key in $scope.layers.overlays) { | |
| if ($scope.layers.overlays[key].index === newIndex) { | |
| oldLy = $scope.layers.overlays[key]; | |
| break; | |
| } | |
| } | |
| if (oldLy) { | |
| safeApply($scope, function() { | |
| oldLy.index = ly.index; | |
| ly.index = newIndex; | |
| }); | |
| } | |
| } | |
| e.stopPropagation(); | |
| e.preventDefault(); | |
| }, | |
| initIndex: function(layer, idx) { | |
| var delta = Object.keys($scope.layers.baselayers).length; | |
| layer.index = isDefined(layer.index) ? layer.index : idx + delta + 1; | |
| }, | |
| initGroup: function(groupName) { | |
| $scope.groupProperties[groupName] = $scope.groupProperties[groupName] ? $scope.groupProperties[groupName] : {}; | |
| }, | |
| toggleOpacity: function(e, layer) { | |
| if (layer.visible) { | |
| if ($scope.autoHideOpacity && !$scope.layerProperties[layer.name].opacityControl) { | |
| for (var k in $scope.layerProperties) { | |
| $scope.layerProperties[k].opacityControl = false; | |
| } | |
| } | |
| $scope.layerProperties[layer.name].opacityControl = !$scope.layerProperties[layer.name].opacityControl; | |
| } | |
| e.stopPropagation(); | |
| e.preventDefault(); | |
| }, | |
| toggleLegend: function(layer) { | |
| $scope.layerProperties[layer.name].showLegend = !$scope.layerProperties[layer.name].showLegend; | |
| }, | |
| showLegend: function(layer) { | |
| return layer.legend && $scope.layerProperties[layer.name].showLegend; | |
| }, | |
| unsafeHTML: function(html) { | |
| return $sce.trustAsHtml(html); | |
| }, | |
| getOpacityIcon: function(layer) { | |
| return layer.visible && $scope.layerProperties[layer.name].opacityControl ? $scope.icons.close : $scope.icons.open; | |
| }, | |
| getGroupIcon: function(group) { | |
| return group.visible ? $scope.icons.check : $scope.icons.uncheck; | |
| }, | |
| changeOpacity: function(layer) { | |
| var op = $scope.layerProperties[layer.name].opacity; | |
| leafletData.getMap().then(function(map) { | |
| leafletData.getLayers().then(function(leafletLayers) { | |
| var ly; | |
| for (var k in $scope.layers.overlays) { | |
| if ($scope.layers.overlays[k] === layer) { | |
| ly = leafletLayers.overlays[k]; | |
| break; | |
| } | |
| } | |
| if (map.hasLayer(ly)) { | |
| if (ly.setOpacity) { | |
| ly.setOpacity(op / 100); | |
| } | |
| if (ly.getLayers && ly.eachLayer) { | |
| ly.eachLayer(function(lay) { | |
| if (lay.setOpacity) { | |
| lay.setOpacity(op / 100); | |
| } | |
| }); | |
| } | |
| } | |
| }); | |
| }); | |
| }, | |
| changeGroupVisibility: function(groupName) { | |
| if (!isDefined($scope.groupProperties[groupName])) { | |
| return; | |
| } | |
| var visible = $scope.groupProperties[groupName].visible; | |
| for (var k in $scope.layers.overlays) { | |
| var layer = $scope.layers.overlays[k]; | |
| if (layer.group === groupName) { | |
| layer.visible = visible; | |
| } | |
| } | |
| }, | |
| }); | |
| var div = $element.get(0); | |
| if (!L.Browser.touch) { | |
| L.DomEvent.disableClickPropagation(div); | |
| L.DomEvent.on(div, 'mousewheel', L.DomEvent.stopPropagation); | |
| } else { | |
| L.DomEvent.on(div, 'click', L.DomEvent.stopPropagation); | |
| } | |
| }], | |
| template: | |
| '<div class="angular-leaflet-control-layers" ng-show="overlaysArray.length">' + | |
| '<h4 ng-if="title">{{ title }}</h4>' + | |
| '<div class="lf-baselayers">' + | |
| '<h5 class="lf-title" ng-if="baseTitle">{{ baseTitle }}</h5>' + | |
| '<div class="lf-row" ng-repeat="(key, layer) in baselayersArray">' + | |
| '<label class="lf-icon-bl" ng-click="changeBaseLayer(key, $event)">' + | |
| '<input class="leaflet-control-layers-selector" type="radio" name="lf-radio" ' + | |
| 'ng-show="false" ng-checked="baselayer === key" ng-value="key" /> ' + | |
| '<i class="lf-icon lf-icon-radio" ng-class="layer.icon"></i>' + | |
| '<div class="lf-text">{{layer.name}}</div>' + | |
| '</label>' + | |
| '</div>' + | |
| '</div>' + | |
| '<div class="lf-overlays">' + | |
| '<h5 class="lf-title" ng-if="overlaysTitle">{{ overlaysTitle }}</h5>' + | |
| '<div class="lf-container">' + | |
| '<div class="lf-row" ng-repeat="layer in (o = (overlaysArray | orderBy:\'index\':order))" ng-init="initIndex(layer, $index)">' + | |
| '<label class="lf-icon-ol-group" ng-if="showGroups && layer.group && layer.group != o[$index-1].group">' + | |
| '<input class="lf-control-layers-selector" type="checkbox" ng-show="false" ' + | |
| 'ng-change="changeGroupVisibility(layer.group)" ng-model="groupProperties[layer.group].visible"/> ' + | |
| '<i class="lf-icon lf-icon-check" ng-class="getGroupIcon(groupProperties[layer.group])"></i>' + | |
| '<div class="lf-text">{{ layer.group }}</div>' + | |
| '</label>' + | |
| '<label class="lf-icon-ol">' + | |
| '<input class="lf-control-layers-selector" type="checkbox" ng-show="false" ng-model="layer.visible"/> ' + | |
| '<i class="lf-icon lf-icon-check" ng-class="layer.icon"></i>' + | |
| '<div class="lf-text">{{layer.name}}</div>' + | |
| '</label>' + | |
| '<div class="lf-icons">' + | |
| '<i class="lf-icon lf-up" ng-class="icons.up" ng-click="moveLayer(layer, layer.index - orderNumber, $event)"></i> ' + | |
| '<i class="lf-icon lf-down" ng-class="icons.down" ng-click="moveLayer(layer, layer.index + orderNumber, $event)"></i> ' + | |
| '<i class="lf-icon lf-toggle-legend" ng-class="icons.toggleLegend" ng-if="layer.legend" ng-click="toggleLegend(layer)"></i> ' + | |
| '<i class="lf-icon lf-open" ng-class="getOpacityIcon(layer)" ng-click="toggleOpacity($event, layer)"></i>' + | |
| '</div>' + | |
| '<div class="lf-legend" ng-if="showLegend(layer)" ng-bind-html="unsafeHTML(layer.legend)"></div>' + | |
| '<div class="lf-opacity clearfix" ng-if="layer.visible && layerProperties[layer.name].opacityControl">' + | |
| '<label ng-if="rangeIsSupported" class="pull-left" style="width: 50%">0</label>' + | |
| '<label ng-if="rangeIsSupported" class="pull-left text-right" style="width: 50%">100</label>' + | |
| '<input ng-if="rangeIsSupported" class="clearfix" type="range" min="0" max="100" class="lf-opacity-control" ' + | |
| 'ng-model="layerProperties[layer.name].opacity" ng-change="changeOpacity(layer)"/>' + | |
| '<h6 ng-if="!rangeIsSupported">Range is not supported in this browser</h6>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>' + | |
| '</div>', | |
| link: function(scope, element, attrs, controller) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var leafletScope = controller.getLeafletScope(); | |
| var layers = leafletScope.layers; | |
| scope.$watch('icons', function() { | |
| var defaultIcons = { | |
| uncheck: 'fa fa-square-o', | |
| check: 'fa fa-check-square-o', | |
| radio: 'fa fa-dot-circle-o', | |
| unradio: 'fa fa-circle-o', | |
| up: 'fa fa-angle-up', | |
| down: 'fa fa-angle-down', | |
| open: 'fa fa-angle-double-down', | |
| close: 'fa fa-angle-double-up', | |
| toggleLegend: 'fa fa-pencil-square-o', | |
| }; | |
| if (isDefined(scope.icons)) { | |
| angular.extend(defaultIcons, scope.icons); | |
| angular.extend(scope.icons, defaultIcons); | |
| } else { | |
| scope.icons = defaultIcons; | |
| } | |
| }); | |
| // Setting layer stack order. | |
| attrs.order = (isDefined(attrs.order) && (attrs.order === 'normal' || attrs.order === 'reverse')) ? attrs.order : 'normal'; | |
| scope.order = attrs.order === 'normal'; | |
| scope.orderNumber = attrs.order === 'normal' ? -1 : 1; | |
| scope.layers = layers; | |
| controller.getMap().then(function(map) { | |
| leafletScope.$watch('layers.baselayers', function(newBaseLayers) { | |
| var baselayersArray = {}; | |
| leafletData.getLayers().then(function(leafletLayers) { | |
| var key; | |
| for (key in newBaseLayers) { | |
| var layer = newBaseLayers[key]; | |
| layer.icon = scope.icons[map.hasLayer(leafletLayers.baselayers[key]) ? 'radio' : 'unradio']; | |
| baselayersArray[key] = layer; | |
| } | |
| scope.baselayersArray = baselayersArray; | |
| }); | |
| }); | |
| leafletScope.$watch('layers.overlays', function(newOverlayLayers) { | |
| var overlaysArray = []; | |
| var groupVisibleCount = {}; | |
| leafletData.getLayers().then(function(leafletLayers) { | |
| var key; | |
| for (key in newOverlayLayers) { | |
| var layer = newOverlayLayers[key]; | |
| layer.icon = scope.icons[(layer.visible ? 'check' : 'uncheck')]; | |
| overlaysArray.push(layer); | |
| if (!isDefined(scope.layerProperties[layer.name])) { | |
| scope.layerProperties[layer.name] = { | |
| opacity: isDefined(layer.layerOptions.opacity) ? layer.layerOptions.opacity * 100 : 100, | |
| opacityControl: false, | |
| showLegend: true, | |
| }; | |
| } | |
| if (isDefined(layer.group)) { | |
| if (!isDefined(scope.groupProperties[layer.group])) { | |
| scope.groupProperties[layer.group] = { | |
| visible: false, | |
| }; | |
| } | |
| groupVisibleCount[layer.group] = isDefined(groupVisibleCount[layer.group]) ? groupVisibleCount[layer.group] : { | |
| count: 0, | |
| visibles: 0, | |
| }; | |
| groupVisibleCount[layer.group].count++; | |
| if (layer.visible) { | |
| groupVisibleCount[layer.group].visibles++; | |
| } | |
| } | |
| if (isDefined(layer.index) && leafletLayers.overlays[key].setZIndex) { | |
| leafletLayers.overlays[key].setZIndex(newOverlayLayers[key].index); | |
| } | |
| } | |
| for (key in groupVisibleCount) { | |
| scope.groupProperties[key].visible = groupVisibleCount[key].visibles === groupVisibleCount[key].count; | |
| } | |
| scope.overlaysArray = overlaysArray; | |
| }); | |
| }, true); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').directive('layers', ["$log", "$q", "leafletData", "leafletHelpers", "leafletLayerHelpers", "leafletControlHelpers", function($log, $q, leafletData, leafletHelpers, leafletLayerHelpers, leafletControlHelpers) { | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: 'leaflet', | |
| controller: ["$scope", function($scope) { | |
| $scope._leafletLayers = $q.defer(); | |
| this.getLayers = function() { | |
| return $scope._leafletLayers.promise; | |
| }; | |
| }], | |
| link: function(scope, element, attrs, controller) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var leafletLayers = {}; | |
| var leafletScope = controller.getLeafletScope(); | |
| var layers = leafletScope.layers; | |
| var createLayer = leafletLayerHelpers.createLayer; | |
| var safeAddLayer = leafletLayerHelpers.safeAddLayer; | |
| var safeRemoveLayer = leafletLayerHelpers.safeRemoveLayer; | |
| var updateLayersControl = leafletControlHelpers.updateLayersControl; | |
| var isLayersControlVisible = false; | |
| controller.getMap().then(function(map) { | |
| // We have baselayers to add to the map | |
| scope._leafletLayers.resolve(leafletLayers); | |
| leafletData.setLayers(leafletLayers, attrs.id); | |
| leafletLayers.baselayers = {}; | |
| leafletLayers.overlays = {}; | |
| var mapId = attrs.id; | |
| // Setup all baselayers definitions | |
| var oneVisibleLayer = false; | |
| for (var layerName in layers.baselayers) { | |
| var newBaseLayer = createLayer(layers.baselayers[layerName]); | |
| if (!isDefined(newBaseLayer)) { | |
| delete layers.baselayers[layerName]; | |
| continue; | |
| } | |
| leafletLayers.baselayers[layerName] = newBaseLayer; | |
| // Only add the visible layer to the map, layer control manages the addition to the map | |
| // of layers in its control | |
| if (layers.baselayers[layerName].top === true) { | |
| safeAddLayer(map, leafletLayers.baselayers[layerName]); | |
| oneVisibleLayer = true; | |
| } | |
| } | |
| // If there is no visible layer add first to the map | |
| if (!oneVisibleLayer && Object.keys(leafletLayers.baselayers).length > 0) { | |
| safeAddLayer(map, leafletLayers.baselayers[Object.keys(layers.baselayers)[0]]); | |
| } | |
| // Setup the Overlays | |
| for (layerName in layers.overlays) { | |
| //if (layers.overlays[layerName].type === 'cartodb') { | |
| // | |
| //} | |
| var newOverlayLayer = createLayer(layers.overlays[layerName]); | |
| if (!isDefined(newOverlayLayer)) { | |
| delete layers.overlays[layerName]; | |
| continue; | |
| } | |
| leafletLayers.overlays[layerName] = newOverlayLayer; | |
| // Only add the visible overlays to the map | |
| if (layers.overlays[layerName].visible === true) { | |
| safeAddLayer(map, leafletLayers.overlays[layerName]); | |
| } | |
| } | |
| // Watch for the base layers | |
| leafletScope.$watch('layers.baselayers', function(newBaseLayers, oldBaseLayers) { | |
| if (angular.equals(newBaseLayers, oldBaseLayers)) { | |
| isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, newBaseLayers, layers.overlays, leafletLayers); | |
| return true; | |
| } | |
| // Delete layers from the array | |
| for (var name in leafletLayers.baselayers) { | |
| if (!isDefined(newBaseLayers[name]) || newBaseLayers[name].doRefresh) { | |
| // Remove from the map if it's on it | |
| if (map.hasLayer(leafletLayers.baselayers[name])) { | |
| map.removeLayer(leafletLayers.baselayers[name]); | |
| } | |
| delete leafletLayers.baselayers[name]; | |
| if (newBaseLayers[name] && newBaseLayers[name].doRefresh) { | |
| newBaseLayers[name].doRefresh = false; | |
| } | |
| } | |
| } | |
| // add new layers | |
| for (var newName in newBaseLayers) { | |
| if (!isDefined(leafletLayers.baselayers[newName])) { | |
| var testBaseLayer = createLayer(newBaseLayers[newName]); | |
| if (isDefined(testBaseLayer)) { | |
| leafletLayers.baselayers[newName] = testBaseLayer; | |
| // Only add the visible layer to the map | |
| if (newBaseLayers[newName].top === true) { | |
| safeAddLayer(map, leafletLayers.baselayers[newName]); | |
| } | |
| } | |
| } else { | |
| if (newBaseLayers[newName].top === true && !map.hasLayer(leafletLayers.baselayers[newName])) { | |
| safeAddLayer(map, leafletLayers.baselayers[newName]); | |
| } else if (newBaseLayers[newName].top === false && map.hasLayer(leafletLayers.baselayers[newName])) { | |
| map.removeLayer(leafletLayers.baselayers[newName]); | |
| } | |
| } | |
| } | |
| //we have layers, so we need to make, at least, one active | |
| var found = false; | |
| // search for an active layer | |
| for (var key in leafletLayers.baselayers) { | |
| if (map.hasLayer(leafletLayers.baselayers[key])) { | |
| found = true; | |
| break; | |
| } | |
| } | |
| // If there is no active layer make one active | |
| if (!found && Object.keys(leafletLayers.baselayers).length > 0) { | |
| safeAddLayer(map, leafletLayers.baselayers[Object.keys(leafletLayers.baselayers)[0]]); | |
| } | |
| // Only show the layers switch selector control if we have more than one baselayer + overlay | |
| isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, newBaseLayers, layers.overlays, leafletLayers); | |
| }, true); | |
| // Watch for the overlay layers | |
| leafletScope.$watch('layers.overlays', function(newOverlayLayers, oldOverlayLayers) { | |
| if (angular.equals(newOverlayLayers, oldOverlayLayers)) { | |
| isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, layers.baselayers, newOverlayLayers, leafletLayers); | |
| return true; | |
| } | |
| // Delete layers from the array | |
| for (var name in leafletLayers.overlays) { | |
| if (!isDefined(newOverlayLayers[name]) || newOverlayLayers[name].doRefresh) { | |
| // Remove from the map if it's on it | |
| if (map.hasLayer(leafletLayers.overlays[name])) { | |
| // Safe remove when ArcGIS layers is loading. | |
| var options = isDefined(newOverlayLayers[name]) ? | |
| newOverlayLayers[name].layerOptions : null; | |
| safeRemoveLayer(map, leafletLayers.overlays[name], options); | |
| } | |
| // TODO: Depending on the layer type we will have to delete what's included on it | |
| delete leafletLayers.overlays[name]; | |
| if (newOverlayLayers[name] && newOverlayLayers[name].doRefresh) { | |
| newOverlayLayers[name].doRefresh = false; | |
| } | |
| } | |
| } | |
| // add new overlays | |
| for (var newName in newOverlayLayers) { | |
| if (!isDefined(leafletLayers.overlays[newName])) { | |
| var testOverlayLayer = createLayer(newOverlayLayers[newName]); | |
| if (!isDefined(testOverlayLayer)) { | |
| // If the layer creation fails, continue to the next overlay | |
| continue; | |
| } | |
| leafletLayers.overlays[newName] = testOverlayLayer; | |
| if (newOverlayLayers[newName].visible === true) { | |
| safeAddLayer(map, leafletLayers.overlays[newName]); | |
| } | |
| } else { | |
| // check for the .visible property to hide/show overLayers | |
| if (newOverlayLayers[newName].visible && !map.hasLayer(leafletLayers.overlays[newName])) { | |
| safeAddLayer(map, leafletLayers.overlays[newName]); | |
| } else if (newOverlayLayers[newName].visible === false && map.hasLayer(leafletLayers.overlays[newName])) { | |
| // Safe remove when ArcGIS layers is loading. | |
| safeRemoveLayer(map, leafletLayers.overlays[newName], newOverlayLayers[newName].layerOptions); | |
| } | |
| } | |
| //refresh heatmap data if present | |
| if (newOverlayLayers[newName].visible && map._loaded && newOverlayLayers[newName].data && newOverlayLayers[newName].type === 'heatmap') { | |
| leafletLayers.overlays[newName].setData(newOverlayLayers[newName].data); | |
| leafletLayers.overlays[newName].update(); | |
| } | |
| } | |
| // Only add the layers switch selector control if we have more than one baselayer + overlay | |
| isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, layers.baselayers, newOverlayLayers, leafletLayers); | |
| }, true); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').directive('legend', ["$log", "$http", "leafletHelpers", "leafletLegendHelpers", function($log, $http, leafletHelpers, leafletLegendHelpers) { | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: 'leaflet', | |
| link: function(scope, element, attrs, controller) { | |
| var isArray = leafletHelpers.isArray; | |
| var isDefined = leafletHelpers.isDefined; | |
| var isFunction = leafletHelpers.isFunction; | |
| var leafletScope = controller.getLeafletScope(); | |
| var legend = leafletScope.legend; | |
| var legendClass; | |
| var position; | |
| var leafletLegend; | |
| var type; | |
| leafletScope.$watch('legend', function(newLegend) { | |
| if (isDefined(newLegend)) { | |
| legendClass = newLegend.legendClass ? newLegend.legendClass : 'legend'; | |
| position = newLegend.position || 'bottomright'; | |
| // default to arcgis | |
| type = newLegend.type || 'arcgis'; | |
| } | |
| }, true); | |
| controller.getMap().then(function(map) { | |
| leafletScope.$watch('legend', function(newLegend) { | |
| if (!isDefined(newLegend)) { | |
| if (isDefined(leafletLegend)) { | |
| leafletLegend.removeFrom(map); | |
| leafletLegend = null; | |
| } | |
| return; | |
| } | |
| if (!isDefined(newLegend.url) && (type === 'arcgis') && (!isArray(newLegend.colors) || !isArray(newLegend.labels) || newLegend.colors.length !== newLegend.labels.length)) { | |
| $log.warn('[AngularJS - Leaflet] legend.colors and legend.labels must be set.'); | |
| return; | |
| } | |
| if (isDefined(newLegend.url)) { | |
| $log.info('[AngularJS - Leaflet] loading legend service.'); | |
| return; | |
| } | |
| if (isDefined(leafletLegend)) { | |
| leafletLegend.removeFrom(map); | |
| leafletLegend = null; | |
| } | |
| leafletLegend = L.control({ | |
| position: position, | |
| }); | |
| if (type === 'arcgis') { | |
| leafletLegend.onAdd = leafletLegendHelpers.getOnAddArrayLegend(newLegend, legendClass); | |
| } | |
| leafletLegend.addTo(map); | |
| }); | |
| leafletScope.$watch('legend.url', function(newURL) { | |
| if (!isDefined(newURL)) { | |
| return; | |
| } | |
| $http.get(newURL) | |
| .success(function(legendData) { | |
| if (isDefined(leafletLegend)) { | |
| leafletLegendHelpers.updateLegend(leafletLegend.getContainer(), legendData, type, newURL); | |
| } else { | |
| leafletLegend = L.control({ | |
| position: position, | |
| }); | |
| leafletLegend.onAdd = leafletLegendHelpers.getOnAddLegend(legendData, legendClass, type, newURL); | |
| leafletLegend.addTo(map); | |
| } | |
| if (isDefined(legend.loadedData) && isFunction(legend.loadedData)) { | |
| legend.loadedData(); | |
| } | |
| }) | |
| .error(function() { | |
| $log.warn('[AngularJS - Leaflet] legend.url not loaded.'); | |
| }); | |
| }); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').directive('markers', | |
| ["$log", "$rootScope", "$q", "leafletData", "leafletHelpers", "leafletMapDefaults", "leafletMarkersHelpers", "leafletMarkerEvents", "leafletIterators", "leafletWatchHelpers", "leafletDirectiveControlsHelpers", function($log, $rootScope, $q, leafletData, leafletHelpers, leafletMapDefaults, | |
| leafletMarkersHelpers, leafletMarkerEvents, leafletIterators, leafletWatchHelpers, | |
| leafletDirectiveControlsHelpers) { | |
| //less terse vars to helpers | |
| var isDefined = leafletHelpers.isDefined; | |
| var errorHeader = leafletHelpers.errorHeader; | |
| var Helpers = leafletHelpers; | |
| var isString = leafletHelpers.isString; | |
| var addMarkerWatcher = leafletMarkersHelpers.addMarkerWatcher; | |
| var updateMarker = leafletMarkersHelpers.updateMarker; | |
| var listenMarkerEvents = leafletMarkersHelpers.listenMarkerEvents; | |
| var addMarkerToGroup = leafletMarkersHelpers.addMarkerToGroup; | |
| var createMarker = leafletMarkersHelpers.createMarker; | |
| var deleteMarker = leafletMarkersHelpers.deleteMarker; | |
| var $it = leafletIterators; | |
| var _markersWatchOptions = leafletHelpers.watchOptions; | |
| var maybeWatch = leafletWatchHelpers.maybeWatch; | |
| var extendDirectiveControls = leafletDirectiveControlsHelpers.extend; | |
| var _getLMarker = function(leafletMarkers, name, maybeLayerName) { | |
| if (!Object.keys(leafletMarkers).length) return; | |
| if (maybeLayerName && isString(maybeLayerName)) { | |
| if (!leafletMarkers[maybeLayerName] || !Object.keys(leafletMarkers[maybeLayerName]).length) | |
| return; | |
| return leafletMarkers[maybeLayerName][name]; | |
| } | |
| return leafletMarkers[name]; | |
| }; | |
| var _setLMarker = function(lObject, leafletMarkers, name, maybeLayerName) { | |
| if (maybeLayerName && isString(maybeLayerName)) { | |
| if (!isDefined(leafletMarkers[maybeLayerName])) | |
| leafletMarkers[maybeLayerName] = {}; | |
| leafletMarkers[maybeLayerName][name] = lObject; | |
| } else | |
| leafletMarkers[name] = lObject; | |
| return lObject; | |
| }; | |
| var _maybeAddMarkerToLayer = function(layerName, layers, model, marker, doIndividualWatch, map) { | |
| if (!isString(layerName)) { | |
| $log.error(errorHeader + ' A layername must be a string'); | |
| return false; | |
| } | |
| if (!isDefined(layers)) { | |
| $log.error(errorHeader + ' You must add layers to the directive if the markers are going to use this functionality.'); | |
| return false; | |
| } | |
| if (!isDefined(layers.overlays) || !isDefined(layers.overlays[layerName])) { | |
| $log.error(errorHeader + ' A marker can only be added to a layer of type "group"'); | |
| return false; | |
| } | |
| var layerGroup = layers.overlays[layerName]; | |
| if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) { | |
| $log.error(errorHeader + ' Adding a marker to an overlay needs a overlay of the type "group" or "featureGroup"'); | |
| return false; | |
| } | |
| // The marker goes to a correct layer group, so first of all we add it | |
| layerGroup.addLayer(marker); | |
| // The marker is automatically added to the map depending on the visibility | |
| // of the layer, so we only have to open the popup if the marker is in the map | |
| if (!doIndividualWatch && map.hasLayer(marker) && model.focus === true) { | |
| marker.openPopup(); | |
| } | |
| return true; | |
| }; | |
| //TODO: move to leafletMarkersHelpers??? or make a new class/function file (leafletMarkersHelpers is large already) | |
| var _addMarkers = function(mapId, markersToRender, oldModels, map, layers, leafletMarkers, leafletScope, | |
| watchOptions, maybeLayerName, skips) { | |
| for (var newName in markersToRender) { | |
| if (skips[newName]) | |
| continue; | |
| if (newName.search('-') !== -1) { | |
| $log.error('The marker can\'t use a "-" on his key name: "' + newName + '".'); | |
| continue; | |
| } | |
| var model = Helpers.copy(markersToRender[newName]); | |
| var pathToMarker = Helpers.getObjectDotPath(maybeLayerName ? [maybeLayerName, newName] : [newName]); | |
| var maybeLMarker = _getLMarker(leafletMarkers, newName, maybeLayerName); | |
| if (!isDefined(maybeLMarker)) { | |
| //(nmccready) very important to not have model changes when lObject is changed | |
| //this might be desirable in some cases but it causes two-way binding to lObject which is not ideal | |
| //if it is left as the reference then all changes from oldModel vs newModel are ignored | |
| //see _destroy (where modelDiff becomes meaningless if we do not copy here) | |
| var marker = createMarker(model); | |
| var layerName = (model ? model.layer : undefined) || maybeLayerName; //original way takes pref | |
| if (!isDefined(marker)) { | |
| $log.error(errorHeader + ' Received invalid data on the marker ' + newName + '.'); | |
| continue; | |
| } | |
| _setLMarker(marker, leafletMarkers, newName, maybeLayerName); | |
| // Bind message | |
| if (isDefined(model.message)) { | |
| marker.bindPopup(model.message, model.popupOptions); | |
| } | |
| // Add the marker to a cluster group if needed | |
| if (isDefined(model.group)) { | |
| var groupOptions = isDefined(model.groupOption) ? model.groupOption : null; | |
| addMarkerToGroup(marker, model.group, groupOptions, map); | |
| } | |
| // Show label if defined | |
| if (Helpers.LabelPlugin.isLoaded() && isDefined(model.label) && isDefined(model.label.message)) { | |
| marker.bindLabel(model.label.message, model.label.options); | |
| } | |
| // Check if the marker should be added to a layer | |
| if (isDefined(model) && (isDefined(model.layer) || isDefined(maybeLayerName))) { | |
| var pass = _maybeAddMarkerToLayer(layerName, layers, model, marker, | |
| watchOptions.individual.doWatch, map); | |
| if (!pass) | |
| continue; //something went wrong move on in the loop | |
| } else if (!isDefined(model.group)) { | |
| // We do not have a layer attr, so the marker goes to the map layer | |
| map.addLayer(marker); | |
| if (!watchOptions.individual.doWatch && model.focus === true) { | |
| marker.openPopup(); | |
| } | |
| } | |
| if (watchOptions.individual.doWatch) { | |
| addMarkerWatcher(marker, pathToMarker, leafletScope, layers, map, | |
| watchOptions.individual.isDeep); | |
| } | |
| listenMarkerEvents(marker, model, leafletScope, watchOptions.individual.doWatch, map); | |
| leafletMarkerEvents.bindEvents(mapId, marker, pathToMarker, model, leafletScope, layerName); | |
| } else { | |
| var oldModel = isDefined(oldModel) ? oldModels[newName] : undefined; | |
| updateMarker(model, oldModel, maybeLMarker, pathToMarker, leafletScope, layers, map); | |
| } | |
| } | |
| }; | |
| var _seeWhatWeAlreadyHave = function(markerModels, oldMarkerModels, lMarkers, isEqual, cb) { | |
| var hasLogged = false; | |
| var equals = false; | |
| var oldMarker; | |
| var newMarker; | |
| var doCheckOldModel = isDefined(oldMarkerModels); | |
| for (var name in lMarkers) { | |
| if (!hasLogged) { | |
| $log.debug(errorHeader + '[markers] destroy: '); | |
| hasLogged = true; | |
| } | |
| if (doCheckOldModel) { | |
| //might want to make the option (in watch options) to disable deep checking | |
| //ie the options to only check !== (reference check) instead of angular.equals (slow) | |
| newMarker = markerModels[name]; | |
| oldMarker = oldMarkerModels[name]; | |
| equals = angular.equals(newMarker, oldMarker) && isEqual; | |
| } | |
| if (!isDefined(markerModels) || | |
| !Object.keys(markerModels).length || | |
| !isDefined(markerModels[name]) || | |
| !Object.keys(markerModels[name]).length || | |
| equals) { | |
| if (cb && Helpers.isFunction(cb)) | |
| cb(newMarker, oldMarker, name); | |
| } | |
| } | |
| }; | |
| var _destroy = function(markerModels, oldMarkerModels, lMarkers, map, layers) { | |
| _seeWhatWeAlreadyHave(markerModels, oldMarkerModels, lMarkers, false, | |
| function(newMarker, oldMarker, lMarkerName) { | |
| $log.debug(errorHeader + '[marker] is deleting marker: ' + lMarkerName); | |
| deleteMarker(lMarkers[lMarkerName], map, layers); | |
| delete lMarkers[lMarkerName]; | |
| }); | |
| }; | |
| var _getNewModelsToSkipp = function(newModels, oldModels, lMarkers) { | |
| var skips = {}; | |
| _seeWhatWeAlreadyHave(newModels, oldModels, lMarkers, true, | |
| function(newMarker, oldMarker, lMarkerName) { | |
| $log.debug(errorHeader + '[marker] is already rendered, marker: ' + lMarkerName); | |
| skips[lMarkerName] = newMarker; | |
| }); | |
| return skips; | |
| }; | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: ['leaflet', '?layers'], | |
| link: function(scope, element, attrs, controller) { | |
| var mapController = controller[0]; | |
| var leafletScope = mapController.getLeafletScope(); | |
| mapController.getMap().then(function(map) { | |
| var leafletMarkers = {}; | |
| var getLayers; | |
| // If the layers attribute is used, we must wait until the layers are created | |
| if (isDefined(controller[1])) { | |
| getLayers = controller[1].getLayers; | |
| } else { | |
| getLayers = function() { | |
| var deferred = $q.defer(); | |
| deferred.resolve(); | |
| return deferred.promise; | |
| }; | |
| } | |
| var watchOptions = leafletScope.markersWatchOptions || _markersWatchOptions; | |
| // backwards compat | |
| if (isDefined(attrs.watchMarkers)) | |
| watchOptions.doWatch = watchOptions.individual.doWatch = | |
| (!isDefined(attrs.watchMarkers) || Helpers.isTruthy(attrs.watchMarkers)); | |
| var isNested = (isDefined(attrs.markersNested) && Helpers.isTruthy(attrs.markersNested)); | |
| getLayers().then(function(layers) { | |
| var _clean = function(models, oldModels) { | |
| if (isNested) { | |
| $it.each(models, function(markerToMaybeDel, layerName) { | |
| var oldModel = isDefined(oldModel) ? oldModels[layerName] : undefined; | |
| _destroy(markerToMaybeDel, oldModel, leafletMarkers[layerName], map, layers); | |
| }); | |
| return; | |
| } | |
| _destroy(models, oldModels, leafletMarkers, map, layers); | |
| }; | |
| var _create = function(models, oldModels) { | |
| _clean(models, oldModels); | |
| var skips = null; | |
| if (isNested) { | |
| $it.each(models, function(markersToAdd, layerName) { | |
| var oldModel = isDefined(oldModel) ? oldModels[layerName] : undefined; | |
| skips = _getNewModelsToSkipp(models[layerName], oldModel, leafletMarkers[layerName]); | |
| _addMarkers(attrs.id, markersToAdd, oldModels, map, layers, leafletMarkers, leafletScope, | |
| watchOptions, layerName, skips); | |
| }); | |
| return; | |
| } | |
| skips = _getNewModelsToSkipp(models, oldModels, leafletMarkers); | |
| _addMarkers(attrs.id, models, oldModels, map, layers, leafletMarkers, leafletScope, | |
| watchOptions, undefined, skips); | |
| }; | |
| extendDirectiveControls(attrs.id, 'markers', _create, _clean); | |
| leafletData.setMarkers(leafletMarkers, attrs.id); | |
| maybeWatch(leafletScope, 'markers', watchOptions, function(newMarkers, oldMarkers) { | |
| _create(newMarkers, oldMarkers); | |
| }); | |
| }); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').directive('maxbounds', ["$log", "leafletMapDefaults", "leafletBoundsHelpers", "leafletHelpers", function($log, leafletMapDefaults, leafletBoundsHelpers, leafletHelpers) { | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: 'leaflet', | |
| link: function(scope, element, attrs, controller) { | |
| var leafletScope = controller.getLeafletScope(); | |
| var isValidBounds = leafletBoundsHelpers.isValidBounds; | |
| var isNumber = leafletHelpers.isNumber; | |
| controller.getMap().then(function(map) { | |
| leafletScope.$watch('maxbounds', function(maxbounds) { | |
| if (!isValidBounds(maxbounds)) { | |
| // Unset any previous maxbounds | |
| map.setMaxBounds(); | |
| return; | |
| } | |
| var leafletBounds = leafletBoundsHelpers.createLeafletBounds(maxbounds); | |
| if (isNumber(maxbounds.pad)) { | |
| leafletBounds = leafletBounds.pad(maxbounds.pad); | |
| } | |
| map.setMaxBounds(leafletBounds); | |
| if (!attrs.center && !attrs.lfCenter) { | |
| map.fitBounds(leafletBounds); | |
| } | |
| }); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').directive('paths', ["$log", "$q", "leafletData", "leafletMapDefaults", "leafletHelpers", "leafletPathsHelpers", "leafletPathEvents", function($log, $q, leafletData, leafletMapDefaults, leafletHelpers, leafletPathsHelpers, leafletPathEvents) { | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: ['leaflet', '?layers'], | |
| link: function(scope, element, attrs, controller) { | |
| var mapController = controller[0]; | |
| var isDefined = leafletHelpers.isDefined; | |
| var isString = leafletHelpers.isString; | |
| var leafletScope = mapController.getLeafletScope(); | |
| var paths = leafletScope.paths; | |
| var createPath = leafletPathsHelpers.createPath; | |
| var bindPathEvents = leafletPathEvents.bindPathEvents; | |
| var setPathOptions = leafletPathsHelpers.setPathOptions; | |
| mapController.getMap().then(function(map) { | |
| var defaults = leafletMapDefaults.getDefaults(attrs.id); | |
| var getLayers; | |
| // If the layers attribute is used, we must wait until the layers are created | |
| if (isDefined(controller[1])) { | |
| getLayers = controller[1].getLayers; | |
| } else { | |
| getLayers = function() { | |
| var deferred = $q.defer(); | |
| deferred.resolve(); | |
| return deferred.promise; | |
| }; | |
| } | |
| if (!isDefined(paths)) { | |
| return; | |
| } | |
| getLayers().then(function(layers) { | |
| var leafletPaths = {}; | |
| leafletData.setPaths(leafletPaths, attrs.id); | |
| // Should we watch for every specific marker on the map? | |
| var shouldWatch = (!isDefined(attrs.watchPaths) || attrs.watchPaths === 'true'); | |
| // Function for listening every single path once created | |
| var watchPathFn = function(leafletPath, name) { | |
| var clearWatch = leafletScope.$watch('paths["' + name + '"]', function(pathData, old) { | |
| if (!isDefined(pathData)) { | |
| if (isDefined(old.layer)) { | |
| for (var i in layers.overlays) { | |
| var overlay = layers.overlays[i]; | |
| overlay.removeLayer(leafletPath); | |
| } | |
| } | |
| map.removeLayer(leafletPath); | |
| clearWatch(); | |
| return; | |
| } | |
| setPathOptions(leafletPath, pathData.type, pathData); | |
| }, true); | |
| }; | |
| leafletScope.$watchCollection('paths', function(newPaths) { | |
| // Delete paths (by name) from the array | |
| for (var name in leafletPaths) { | |
| if (!isDefined(newPaths[name])) { | |
| map.removeLayer(leafletPaths[name]); | |
| delete leafletPaths[name]; | |
| } | |
| } | |
| // Create the new paths | |
| for (var newName in newPaths) { | |
| if (newName.search('\\$') === 0) { | |
| continue; | |
| } | |
| if (newName.search('-') !== -1) { | |
| $log.error('[AngularJS - Leaflet] The path name "' + newName + '" is not valid. It must not include "-" and a number.'); | |
| continue; | |
| } | |
| if (!isDefined(leafletPaths[newName])) { | |
| var pathData = newPaths[newName]; | |
| var newPath = createPath(newName, newPaths[newName], defaults); | |
| // bind popup if defined | |
| if (isDefined(newPath) && isDefined(pathData.message)) { | |
| newPath.bindPopup(pathData.message, pathData.popupOptions); | |
| } | |
| // Show label if defined | |
| if (leafletHelpers.LabelPlugin.isLoaded() && isDefined(pathData.label) && isDefined(pathData.label.message)) { | |
| newPath.bindLabel(pathData.label.message, pathData.label.options); | |
| } | |
| // Check if the marker should be added to a layer | |
| if (isDefined(pathData) && isDefined(pathData.layer)) { | |
| if (!isString(pathData.layer)) { | |
| $log.error('[AngularJS - Leaflet] A layername must be a string'); | |
| continue; | |
| } | |
| if (!isDefined(layers)) { | |
| $log.error('[AngularJS - Leaflet] You must add layers to the directive if the markers are going to use this functionality.'); | |
| continue; | |
| } | |
| if (!isDefined(layers.overlays) || !isDefined(layers.overlays[pathData.layer])) { | |
| $log.error('[AngularJS - Leaflet] A path can only be added to a layer of type "group"'); | |
| continue; | |
| } | |
| var layerGroup = layers.overlays[pathData.layer]; | |
| if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) { | |
| $log.error('[AngularJS - Leaflet] Adding a path to an overlay needs a overlay of the type "group" or "featureGroup"'); | |
| continue; | |
| } | |
| // Listen for changes on the new path | |
| leafletPaths[newName] = newPath; | |
| // The path goes to a correct layer group, so first of all we add it | |
| layerGroup.addLayer(newPath); | |
| if (shouldWatch) { | |
| watchPathFn(newPath, newName); | |
| } else { | |
| setPathOptions(newPath, pathData.type, pathData); | |
| } | |
| } else if (isDefined(newPath)) { | |
| // Listen for changes on the new path | |
| leafletPaths[newName] = newPath; | |
| map.addLayer(newPath); | |
| if (shouldWatch) { | |
| watchPathFn(newPath, newName); | |
| } else { | |
| setPathOptions(newPath, pathData.type, pathData); | |
| } | |
| } | |
| bindPathEvents(attrs.id, newPath, newName, pathData, leafletScope); | |
| } | |
| } | |
| }); | |
| }); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive').directive('tiles', ["$log", "leafletData", "leafletMapDefaults", "leafletHelpers", function($log, leafletData, leafletMapDefaults, leafletHelpers) { | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: 'leaflet', | |
| link: function(scope, element, attrs, controller) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var leafletScope = controller.getLeafletScope(); | |
| var tiles = leafletScope.tiles; | |
| if (!isDefined(tiles) || !isDefined(tiles.url)) { | |
| $log.warn('[AngularJS - Leaflet] The \'tiles\' definition doesn\'t have the \'url\' property.'); | |
| return; | |
| } | |
| controller.getMap().then(function(map) { | |
| var defaults = leafletMapDefaults.getDefaults(attrs.id); | |
| var tileLayerObj; | |
| leafletScope.$watch('tiles', function(tiles, oldtiles) { | |
| var tileLayerOptions = defaults.tileLayerOptions; | |
| var tileLayerUrl = defaults.tileLayer; | |
| // If no valid tiles are in the scope, remove the last layer | |
| if (!isDefined(tiles.url) && isDefined(tileLayerObj)) { | |
| map.removeLayer(tileLayerObj); | |
| return; | |
| } | |
| // No leafletTiles object defined yet | |
| if (!isDefined(tileLayerObj)) { | |
| if (isDefined(tiles.options)) { | |
| angular.copy(tiles.options, tileLayerOptions); | |
| } | |
| if (isDefined(tiles.url)) { | |
| tileLayerUrl = tiles.url; | |
| } | |
| if (tiles.type === 'wms') { | |
| tileLayerObj = L.tileLayer.wms(tileLayerUrl, tileLayerOptions); | |
| } else { | |
| tileLayerObj = L.tileLayer(tileLayerUrl, tileLayerOptions); | |
| } | |
| tileLayerObj.addTo(map); | |
| leafletData.setTiles(tileLayerObj, attrs.id); | |
| return; | |
| } | |
| // If the options of the tilelayer is changed, we need to redraw the layer | |
| if (isDefined(tiles.url) && isDefined(tiles.options) && | |
| (tiles.type !== oldtiles.type || !angular.equals(tiles.options, tileLayerOptions))) { | |
| map.removeLayer(tileLayerObj); | |
| tileLayerOptions = defaults.tileLayerOptions; | |
| angular.copy(tiles.options, tileLayerOptions); | |
| tileLayerUrl = tiles.url; | |
| if (tiles.type === 'wms') { | |
| tileLayerObj = L.tileLayer.wms(tileLayerUrl, tileLayerOptions); | |
| } else { | |
| tileLayerObj = L.tileLayer(tileLayerUrl, tileLayerOptions); | |
| } | |
| tileLayerObj.addTo(map); | |
| leafletData.setTiles(tileLayerObj, attrs.id); | |
| return; | |
| } | |
| // Only the URL of the layer is changed, update the tiles object | |
| if (isDefined(tiles.url)) { | |
| tileLayerObj.setUrl(tiles.url); | |
| } | |
| }, true); | |
| }); | |
| }, | |
| }; | |
| }]); | |
| /* | |
| Create multiple similar directives for watchOptions to support directiveControl | |
| instead. (when watches are disabled) | |
| NgAnnotate does not work here due to the functional creation | |
| */ | |
| ['markers', 'geojson'].forEach(function(name) { | |
| angular.module('leaflet-directive').directive(name + 'WatchOptions', [ | |
| '$log', '$rootScope', '$q', 'leafletData', 'leafletHelpers', | |
| function($log, $rootScope, $q, leafletData, leafletHelpers) { | |
| var isDefined = leafletHelpers.isDefined, | |
| errorHeader = leafletHelpers.errorHeader, | |
| isObject = leafletHelpers.isObject, | |
| _watchOptions = leafletHelpers.watchOptions; | |
| return { | |
| restrict: 'A', | |
| scope: false, | |
| replace: false, | |
| require: ['leaflet'], | |
| link: function(scope, element, attrs, controller) { | |
| var mapController = controller[0], | |
| leafletScope = mapController.getLeafletScope(); | |
| mapController.getMap().then(function() { | |
| if (isDefined(scope[name + 'WatchOptions'])) { | |
| if (isObject(scope[name + 'WatchOptions'])) | |
| angular.extend(_watchOptions, scope[name + 'WatchOptions']); | |
| else | |
| $log.error(errorHeader + '[' + name + 'WatchOptions] is not an object'); | |
| leafletScope[name + 'WatchOptions'] = _watchOptions; | |
| } | |
| }); | |
| }, | |
| }; | |
| },]); | |
| }); | |
| angular.module('leaflet-directive') | |
| .factory('LeafletEventsHelpersFactory', ["$rootScope", "$q", "$log", "leafletHelpers", function($rootScope, $q, $log, leafletHelpers) { | |
| var safeApply = leafletHelpers.safeApply; | |
| var isDefined = leafletHelpers.isDefined; | |
| var isObject = leafletHelpers.isObject; | |
| var isArray = leafletHelpers.isArray; | |
| var errorHeader = leafletHelpers.errorHeader; | |
| var EventsHelper = function(rootBroadcastName, lObjectType) { | |
| this.rootBroadcastName = rootBroadcastName; | |
| $log.debug('LeafletEventsHelpersFactory: lObjectType: ' + lObjectType + 'rootBroadcastName: ' + rootBroadcastName); | |
| //used to path/key out certain properties based on the type , "markers", "geojson" | |
| this.lObjectType = lObjectType; | |
| }; | |
| EventsHelper.prototype.getAvailableEvents = function() {return [];}; | |
| /* | |
| argument: name: Note this can be a single string or dot notation | |
| Example: | |
| markerModel : { | |
| m1: { lat:_, lon: _} | |
| } | |
| //would yield name of | |
| name = "m1" | |
| If nested: | |
| markerModel : { | |
| cars: { | |
| m1: { lat:_, lon: _} | |
| } | |
| } | |
| //would yield name of | |
| name = "cars.m1" | |
| */ | |
| EventsHelper.prototype.genDispatchEvent = function(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName, extra) { | |
| var _this = this; | |
| maybeMapId = maybeMapId || ''; | |
| if (maybeMapId) | |
| maybeMapId = '.' + maybeMapId; | |
| return function(e) { | |
| var broadcastName = _this.rootBroadcastName + maybeMapId + '.' + eventName; | |
| $log.debug(broadcastName); | |
| _this.fire(leafletScope, broadcastName, logic, e, e.target || lObject, model, name, layerName, extra); | |
| }; | |
| }; | |
| EventsHelper.prototype.fire = function(scope, broadcastName, logic, event, lObject, model, modelName, layerName) { | |
| // Safely broadcast the event | |
| safeApply(scope, function() { | |
| var toSend = { | |
| leafletEvent: event, | |
| leafletObject: lObject, | |
| modelName: modelName, | |
| model: model, | |
| }; | |
| if (isDefined(layerName)) | |
| angular.extend(toSend, {layerName: layerName}); | |
| if (logic === 'emit') { | |
| scope.$emit(broadcastName, toSend); | |
| } else { | |
| $rootScope.$broadcast(broadcastName, toSend); | |
| } | |
| }); | |
| }; | |
| EventsHelper.prototype.bindEvents = function(maybeMapId, lObject, name, model, leafletScope, layerName, extra) { | |
| var events = []; | |
| var logic = 'emit'; | |
| var _this = this; | |
| if (!isDefined(leafletScope.eventBroadcast)) { | |
| // Backward compatibility, if no event-broadcast attribute, all events are broadcasted | |
| events = this.getAvailableEvents(); | |
| } else if (!isObject(leafletScope.eventBroadcast)) { | |
| // Not a valid object | |
| $log.error(errorHeader + 'event-broadcast must be an object check your model.'); | |
| } else { | |
| // We have a possible valid object | |
| if (!isDefined(leafletScope.eventBroadcast[_this.lObjectType])) { | |
| // We do not have events enable/disable do we do nothing (all enabled by default) | |
| events = this.getAvailableEvents(); | |
| } else if (!isObject(leafletScope.eventBroadcast[_this.lObjectType])) { | |
| // Not a valid object | |
| $log.warn(errorHeader + 'event-broadcast.' + [_this.lObjectType] + ' must be an object check your model.'); | |
| } else { | |
| // We have a possible valid map object | |
| // Event propadation logic | |
| if (isDefined(leafletScope.eventBroadcast[this.lObjectType].logic)) { | |
| // We take care of possible propagation logic | |
| if (leafletScope.eventBroadcast[_this.lObjectType].logic !== 'emit' && | |
| leafletScope.eventBroadcast[_this.lObjectType].logic !== 'broadcast') | |
| $log.warn(errorHeader + 'Available event propagation logic are: \'emit\' or \'broadcast\'.'); | |
| } | |
| // Enable / Disable | |
| var eventsEnable = false; | |
| var eventsDisable = false; | |
| if (isDefined(leafletScope.eventBroadcast[_this.lObjectType].enable) && | |
| isArray(leafletScope.eventBroadcast[_this.lObjectType].enable)) | |
| eventsEnable = true; | |
| if (isDefined(leafletScope.eventBroadcast[_this.lObjectType].disable) && | |
| isArray(leafletScope.eventBroadcast[_this.lObjectType].disable)) | |
| eventsDisable = true; | |
| if (eventsEnable && eventsDisable) { | |
| // Both are active, this is an error | |
| $log.warn(errorHeader + 'can not enable and disable events at the same time'); | |
| } else if (!eventsEnable && !eventsDisable) { | |
| // Both are inactive, this is an error | |
| $log.warn(errorHeader + 'must enable or disable events'); | |
| } else { | |
| // At this point the object is OK, lets enable or disable events | |
| if (eventsEnable) { | |
| // Enable events | |
| leafletScope.eventBroadcast[this.lObjectType].enable.forEach(function(eventName) { | |
| // Do we have already the event enabled? | |
| if (events.indexOf(eventName) !== -1) { | |
| // Repeated event, this is an error | |
| $log.warn(errorHeader + 'This event ' + eventName + ' is already enabled'); | |
| } else { | |
| // Does the event exists? | |
| if (_this.getAvailableEvents().indexOf(eventName) === -1) { | |
| // The event does not exists, this is an error | |
| $log.warn(errorHeader + 'This event ' + eventName + ' does not exist'); | |
| } else { | |
| // All ok enable the event | |
| events.push(eventName); | |
| } | |
| } | |
| }); | |
| } else { | |
| // Disable events | |
| events = this.getAvailableEvents(); | |
| leafletScope.eventBroadcast[_this.lObjectType].disable.forEach(function(eventName) { | |
| var index = events.indexOf(eventName); | |
| if (index === -1) { | |
| // The event does not exist | |
| $log.warn(errorHeader + 'This event ' + eventName + ' does not exist or has been already disabled'); | |
| } else { | |
| events.splice(index, 1); | |
| } | |
| }); | |
| } | |
| } | |
| } | |
| } | |
| events.forEach(function(eventName) { | |
| lObject.on(eventName, _this.genDispatchEvent(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName, extra)); | |
| }); | |
| return logic; | |
| }; | |
| return EventsHelper; | |
| }]) | |
| .service('leafletEventsHelpers', ["LeafletEventsHelpersFactory", function(LeafletEventsHelpersFactory) { | |
| return new LeafletEventsHelpersFactory(); | |
| }]); | |
| angular.module('leaflet-directive') | |
| .factory('leafletGeoJsonEvents', ["$rootScope", "$q", "$log", "leafletHelpers", "LeafletEventsHelpersFactory", "leafletData", function($rootScope, $q, $log, leafletHelpers, | |
| LeafletEventsHelpersFactory, leafletData) { | |
| var safeApply = leafletHelpers.safeApply; | |
| var EventsHelper = LeafletEventsHelpersFactory; | |
| var GeoJsonEvents = function() { | |
| EventsHelper.call(this, 'leafletDirectiveGeoJson', 'geojson'); | |
| }; | |
| GeoJsonEvents.prototype = new EventsHelper(); | |
| GeoJsonEvents.prototype.genDispatchEvent = function(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName, extra) { | |
| var base = EventsHelper.prototype.genDispatchEvent.call(this, maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName); | |
| var _this = this; | |
| return function(e) { | |
| if (eventName === 'mouseout') { | |
| if (extra.resetStyleOnMouseout) { | |
| leafletData.getGeoJSON(extra.mapId) | |
| .then(function(leafletGeoJSON) { | |
| //this is broken on nested needs to traverse or user layerName (nested) | |
| var lobj = layerName ? leafletGeoJSON[layerName] : leafletGeoJSON; | |
| lobj.resetStyle(e.target); | |
| }); | |
| } | |
| safeApply(leafletScope, function() { | |
| $rootScope.$broadcast(_this.rootBroadcastName + '.mouseout', e); | |
| }); | |
| } | |
| base(e); //common | |
| }; | |
| }; | |
| GeoJsonEvents.prototype.getAvailableEvents = function() { return [ | |
| 'click', | |
| 'dblclick', | |
| 'mouseover', | |
| 'mouseout', | |
| ]; | |
| }; | |
| return new GeoJsonEvents(); | |
| }]); | |
| angular.module('leaflet-directive') | |
| .factory('leafletLabelEvents', ["$rootScope", "$q", "$log", "leafletHelpers", "LeafletEventsHelpersFactory", function($rootScope, $q, $log, leafletHelpers, LeafletEventsHelpersFactory) { | |
| var Helpers = leafletHelpers; | |
| var EventsHelper = LeafletEventsHelpersFactory; | |
| var LabelEvents = function() { | |
| EventsHelper.call(this, 'leafletDirectiveLabel', 'markers'); | |
| }; | |
| LabelEvents.prototype = new EventsHelper(); | |
| LabelEvents.prototype.genDispatchEvent = function(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) { | |
| var markerName = name.replace('markers.', ''); | |
| return EventsHelper.prototype | |
| .genDispatchEvent.call(this, maybeMapId, eventName, logic, leafletScope, lObject, markerName, model, layerName); | |
| }; | |
| LabelEvents.prototype.getAvailableEvents = function() { | |
| return [ | |
| 'click', | |
| 'dblclick', | |
| 'mousedown', | |
| 'mouseover', | |
| 'mouseout', | |
| 'contextmenu', | |
| ]; | |
| }; | |
| LabelEvents.prototype.genEvents = function(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) { | |
| var _this = this; | |
| var labelEvents = this.getAvailableEvents(); | |
| var scopeWatchName = Helpers.getObjectArrayPath('markers.' + name); | |
| labelEvents.forEach(function(eventName) { | |
| lObject.label.on(eventName, _this.genDispatchEvent( | |
| maybeMapId, eventName, logic, leafletScope, lObject.label, scopeWatchName, model, layerName)); | |
| }); | |
| }; | |
| LabelEvents.prototype.bindEvents = function() {}; | |
| return new LabelEvents(); | |
| }]); | |
| angular.module('leaflet-directive') | |
| .factory('leafletMapEvents', ["$rootScope", "$q", "$log", "leafletHelpers", "leafletEventsHelpers", "leafletIterators", function($rootScope, $q, $log, leafletHelpers, leafletEventsHelpers, leafletIterators) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var fire = leafletEventsHelpers.fire; | |
| var _getAvailableMapEvents = function() { | |
| return [ | |
| 'click', | |
| 'dblclick', | |
| 'mousedown', | |
| 'mouseup', | |
| 'mouseover', | |
| 'mouseout', | |
| 'mousemove', | |
| 'contextmenu', | |
| 'focus', | |
| 'blur', | |
| 'preclick', | |
| 'load', | |
| 'unload', | |
| 'viewreset', | |
| 'movestart', | |
| 'move', | |
| 'moveend', | |
| 'dragstart', | |
| 'drag', | |
| 'dragend', | |
| 'zoomstart', | |
| 'zoomanim', | |
| 'zoomend', | |
| 'zoomlevelschange', | |
| 'resize', | |
| 'autopanstart', | |
| 'layeradd', | |
| 'layerremove', | |
| 'baselayerchange', | |
| 'overlayadd', | |
| 'overlayremove', | |
| 'locationfound', | |
| 'locationerror', | |
| 'popupopen', | |
| 'popupclose', | |
| 'draw:created', | |
| 'draw:edited', | |
| 'draw:deleted', | |
| 'draw:drawstart', | |
| 'draw:drawstop', | |
| 'draw:editstart', | |
| 'draw:editstop', | |
| 'draw:deletestart', | |
| 'draw:deletestop', | |
| ]; | |
| }; | |
| var _genDispatchMapEvent = function(scope, eventName, logic, maybeMapId) { | |
| if (maybeMapId) | |
| maybeMapId = maybeMapId + '.'; | |
| return function(e) { | |
| // Put together broadcast name | |
| var broadcastName = 'leafletDirectiveMap.' + maybeMapId + eventName; | |
| $log.debug(broadcastName); | |
| // Safely broadcast the event | |
| fire(scope, broadcastName, logic, e, e.target, scope); | |
| }; | |
| }; | |
| var _notifyCenterChangedToBounds = function(scope) { | |
| scope.$broadcast('boundsChanged'); | |
| }; | |
| var _notifyCenterUrlHashChanged = function(scope, map, attrs, search) { | |
| if (!isDefined(attrs.urlHashCenter)) { | |
| return; | |
| } | |
| var center = map.getCenter(); | |
| var centerUrlHash = (center.lat).toFixed(4) + ':' + (center.lng).toFixed(4) + ':' + map.getZoom(); | |
| if (!isDefined(search.c) || search.c !== centerUrlHash) { | |
| //$log.debug("notified new center..."); | |
| scope.$emit('centerUrlHash', centerUrlHash); | |
| } | |
| }; | |
| var _addEvents = function(map, mapEvents, contextName, scope, logic) { | |
| leafletIterators.each(mapEvents, function(eventName) { | |
| var context = {}; | |
| context[contextName] = eventName; | |
| map.on(eventName, _genDispatchMapEvent(scope, eventName, logic, map._container.id || ''), context); | |
| }); | |
| }; | |
| return { | |
| getAvailableMapEvents: _getAvailableMapEvents, | |
| genDispatchMapEvent: _genDispatchMapEvent, | |
| notifyCenterChangedToBounds: _notifyCenterChangedToBounds, | |
| notifyCenterUrlHashChanged: _notifyCenterUrlHashChanged, | |
| addEvents: _addEvents, | |
| }; | |
| }]); | |
| angular.module('leaflet-directive') | |
| .factory('leafletMarkerEvents', ["$rootScope", "$q", "$log", "leafletHelpers", "LeafletEventsHelpersFactory", "leafletLabelEvents", function($rootScope, $q, $log, leafletHelpers, LeafletEventsHelpersFactory, leafletLabelEvents) { | |
| var safeApply = leafletHelpers.safeApply; | |
| var isDefined = leafletHelpers.isDefined; | |
| var Helpers = leafletHelpers; | |
| var lblHelp = leafletLabelEvents; | |
| var EventsHelper = LeafletEventsHelpersFactory; | |
| var MarkerEvents = function() { | |
| EventsHelper.call(this, 'leafletDirectiveMarker', 'markers'); | |
| }; | |
| MarkerEvents.prototype = new EventsHelper(); | |
| MarkerEvents.prototype.genDispatchEvent = function(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) { | |
| var handle = EventsHelper.prototype | |
| .genDispatchEvent.call(this, maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName); | |
| return function(e) { | |
| // Broadcast old marker click name for backwards compatibility | |
| if (eventName === 'click') { | |
| safeApply(leafletScope, function() { | |
| $rootScope.$broadcast('leafletDirectiveMarkersClick', name); | |
| }); | |
| } else if (eventName === 'dragend') { | |
| safeApply(leafletScope, function() { | |
| model.lat = lObject.getLatLng().lat; | |
| model.lng = lObject.getLatLng().lng; | |
| }); | |
| if (model.message && model.focus === true) { | |
| lObject.openPopup(); | |
| } | |
| } | |
| handle(e); //common | |
| }; | |
| }; | |
| MarkerEvents.prototype.getAvailableEvents = function() { return [ | |
| 'click', | |
| 'dblclick', | |
| 'mousedown', | |
| 'mouseover', | |
| 'mouseout', | |
| 'contextmenu', | |
| 'dragstart', | |
| 'drag', | |
| 'dragend', | |
| 'move', | |
| 'remove', | |
| 'popupopen', | |
| 'popupclose', | |
| 'touchend', | |
| 'touchstart', | |
| 'touchmove', | |
| 'touchcancel', | |
| 'touchleave', | |
| ]; | |
| }; | |
| MarkerEvents.prototype.bindEvents = function(maybeMapId, lObject, name, model, leafletScope, layerName) { | |
| var logic = EventsHelper.prototype.bindEvents.call(this, maybeMapId, lObject, name, model, leafletScope, layerName); | |
| if (Helpers.LabelPlugin.isLoaded() && isDefined(lObject.label)) { | |
| lblHelp.genEvents(maybeMapId, name, logic, leafletScope, lObject, model, layerName); | |
| } | |
| }; | |
| return new MarkerEvents(); | |
| }]); | |
| angular.module('leaflet-directive') | |
| .factory('leafletPathEvents', ["$rootScope", "$q", "$log", "leafletHelpers", "leafletLabelEvents", "leafletEventsHelpers", function($rootScope, $q, $log, leafletHelpers, leafletLabelEvents, leafletEventsHelpers) { | |
| var isDefined = leafletHelpers.isDefined; | |
| var isObject = leafletHelpers.isObject; | |
| var Helpers = leafletHelpers; | |
| var errorHeader = leafletHelpers.errorHeader; | |
| var lblHelp = leafletLabelEvents; | |
| var fire = leafletEventsHelpers.fire; | |
| /* | |
| TODO (nmccready) This EventsHelper needs to be derrived from leafletEventsHelpers to elminate copy and paste code. | |
| */ | |
| var _genDispatchPathEvent = function(maybeMapId, eventName, logic, leafletScope, lObject, name, model, layerName) { | |
| maybeMapId = maybeMapId || ''; | |
| if (maybeMapId) | |
| maybeMapId = '.' + maybeMapId; | |
| return function(e) { | |
| var broadcastName = 'leafletDirectivePath' + maybeMapId + '.' + eventName; | |
| $log.debug(broadcastName); | |
| fire(leafletScope, broadcastName, logic, e, e.target || lObject, model, name, layerName); | |
| }; | |
| }; | |
| var _bindPathEvents = function(maybeMapId, lObject, name, model, leafletScope) { | |
| var pathEvents = []; | |
| var i; | |
| var eventName; | |
| var logic = 'broadcast'; | |
| if (!isDefined(leafletScope.eventBroadcast)) { | |
| // Backward compatibility, if no event-broadcast attribute, all events are broadcasted | |
| pathEvents = _getAvailablePathEvents(); | |
| } else if (!isObject(leafletScope.eventBroadcast)) { | |
| // Not a valid object | |
| $log.error(errorHeader + 'event-broadcast must be an object check your model.'); | |
| } else { | |
| // We have a possible valid object | |
| if (!isDefined(leafletScope.eventBroadcast.path)) { | |
| // We do not have events enable/disable do we do nothing (all enabled by default) | |
| pathEvents = _getAvailablePathEvents(); | |
| } else if (isObject(leafletScope.eventBroadcast.paths)) { | |
| // Not a valid object | |
| $log.warn(errorHeader + 'event-broadcast.path must be an object check your model.'); | |
| } else { | |
| // We have a possible valid map object | |
| // Event propadation logic | |
| if (leafletScope.eventBroadcast.path.logic !== undefined && leafletScope.eventBroadcast.path.logic !== null) { | |
| // We take care of possible propagation logic | |
| if (leafletScope.eventBroadcast.path.logic !== 'emit' && leafletScope.eventBroadcast.path.logic !== 'broadcast') { | |
| // This is an error | |
| $log.warn(errorHeader + 'Available event propagation logic are: \'emit\' or \'broadcast\'.'); | |
| } else if (leafletScope.eventBroadcast.path.logic === 'emit') { | |
| logic = 'emit'; | |
| } | |
| } | |
| // Enable / Disable | |
| var pathEventsEnable = false; | |
| var pathEventsDisable = false; | |
| if (leafletScope.eventBroadcast.path.enable !== undefined && leafletScope.eventBroadcast.path.enable !== null) { | |
| if (typeof leafletScope.eventBroadcast.path.enable === 'object') { | |
| pathEventsEnable = true; | |
| } | |
| } | |
| if (leafletScope.eventBroadcast.path.disable !== undefined && leafletScope.eventBroadcast.path.disable !== null) { | |
| if (typeof leafletScope.eventBroadcast.path.disable === 'object') { | |
| pathEventsDisable = true; | |
| } | |
| } | |
| if (pathEventsEnable && pathEventsDisable) { | |
| // Both are active, this is an error | |
| $log.warn(errorHeader + 'can not enable and disable events at the same time'); | |
| } else if (!pathEventsEnable && !pathEventsDisable) { | |
| // Both are inactive, this is an error | |
| $log.warn(errorHeader + 'must enable or disable events'); | |
| } else { | |
| // At this point the path object is OK, lets enable or disable events | |
| if (pathEventsEnable) { | |
| // Enable events | |
| for (i = 0; i < leafletScope.eventBroadcast.path.enable.length; i++) { | |
| eventName = leafletScope.eventBroadcast.path.enable[i]; | |
| // Do we have already the event enabled? | |
| if (pathEvents.indexOf(eventName) !== -1) { | |
| // Repeated event, this is an error | |
| $log.warn(errorHeader + 'This event ' + eventName + ' is already enabled'); | |
| } else { | |
| // Does the event exists? | |
| if (_getAvailablePathEvents().indexOf(eventName) === -1) { | |
| // The event does not exists, this is an error | |
| $log.warn(errorHeader + 'This event ' + eventName + ' does not exist'); | |
| } else { | |
| // All ok enable the event | |
| pathEvents.push(eventName); | |
| } | |
| } | |
| } | |
| } else { | |
| // Disable events | |
| pathEvents = _getAvailablePathEvents(); | |
| for (i = 0; i < leafletScope.eventBroadcast.path.disable.length; i++) { | |
| eventName = leafletScope.eventBroadcast.path.disable[i]; | |
| var index = pathEvents.indexOf(eventName); | |
| if (index === -1) { | |
| // The event does not exist | |
| $log.warn(errorHeader + 'This event ' + eventName + ' does not exist or has been already disabled'); | |
| } else { | |
| pathEvents.splice(index, 1); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| for (i = 0; i < pathEvents.length; i++) { | |
| eventName = pathEvents[i]; | |
| lObject.on(eventName, _genDispatchPathEvent(maybeMapId, eventName, logic, leafletScope, pathEvents, name)); | |
| } | |
| if (Helpers.LabelPlugin.isLoaded() && isDefined(lObject.label)) { | |
| lblHelp.genEvents(maybeMapId, name, logic, leafletScope, lObject, model); | |
| } | |
| }; | |
| var _getAvailablePathEvents = function() { | |
| return [ | |
| 'click', | |
| 'dblclick', | |
| 'mousedown', | |
| 'mouseover', | |
| 'mouseout', | |
| 'contextmenu', | |
| 'add', | |
| 'remove', | |
| 'popupopen', | |
| 'popupclose', | |
| ]; | |
| }; | |
| return { | |
| getAvailablePathEvents: _getAvailablePathEvents, | |
| bindPathEvents: _bindPathEvents, | |
| }; | |
| }]); | |
| }(angular)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /**! | |
| * The MIT License | |
| * | |
| * Copyright (c) 2013 the angular-leaflet-directive Team, http://tombatossals.github.io/angular-leaflet-directive | |
| * | |
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |
| * of this software and associated documentation files (the "Software"), to deal | |
| * in the Software without restriction, including without limitation the rights | |
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| * copies of the Software, and to permit persons to whom the Software is | |
| * furnished to do so, subject to the following conditions: | |
| * | |
| * The above copyright notice and this permission notice shall be included in | |
| * all copies or substantial portions of the Software. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| * THE SOFTWARE. | |
| * | |
| * angular-leaflet-directive | |
| * https://github.com/tombatossals/angular-leaflet-directive | |
| * | |
| * @authors https://github.com/tombatossals/angular-leaflet-directive/graphs/contributors | |
| */ | |
| /*! | |
| * angular-leaflet-directive 2015-11-06 | |
| * angular-leaflet-directive - An AngularJS directive to easily interact with Leaflet maps | |
| * git: https://github.com/tombatossals/angular-leaflet-directive | |
| */ | |
| (function(angular){ | |
| 'use strict'; | |
| !function(angular){"use strict";angular.module("leaflet-directive",[]).directive("leaflet",["$q","leafletData","leafletMapDefaults","leafletHelpers","leafletMapEvents",function(a,b,c,d,e){return{restrict:"EA",replace:!0,scope:{center:"=",lfCenter:"=",defaults:"=",maxbounds:"=",bounds:"=",markers:"=",legend:"=",geojson:"=",paths:"=",tiles:"=",layers:"=",controls:"=",decorations:"=",eventBroadcast:"=",markersWatchOptions:"=",geojsonWatchOptions:"="},transclude:!0,template:'<div class="angular-leaflet-map"><div ng-transclude></div></div>',controller:["$scope",function(b){this._leafletMap=a.defer(),this.getMap=function(){return this._leafletMap.promise},this.getLeafletScope=function(){return b}}],link:function(a,f,g,h){function i(){isNaN(g.width)?f.css("width",g.width):f.css("width",g.width+"px")}function j(){isNaN(g.height)?f.css("height",g.height):f.css("height",g.height+"px")}var k=d.isDefined,l=c.setDefaults(a.defaults,g.id),m=e.getAvailableMapEvents(),n=e.addEvents;a.mapId=g.id,b.setDirectiveControls({},g.id),k(g.width)&&(i(),a.$watch(function(){return f[0].getAttribute("width")},function(){i(),o.invalidateSize()})),k(g.height)&&(j(),a.$watch(function(){return f[0].getAttribute("height")},function(){j(),o.invalidateSize()}));var o=new L.Map(f[0],c.getMapCreationDefaults(g.id));if(h._leafletMap.resolve(o),k(g.center)||k(g.lfCenter)||o.setView([l.center.lat,l.center.lng],l.center.zoom),!k(g.tiles)&&!k(g.layers)){var p=L.tileLayer(l.tileLayer,l.tileLayerOptions);p.addTo(o),b.setTiles(p,g.id)}if(k(o.zoomControl)&&k(l.zoomControlPosition)&&o.zoomControl.setPosition(l.zoomControlPosition),k(o.zoomControl)&&l.zoomControl===!1&&o.zoomControl.removeFrom(o),k(o.zoomsliderControl)&&k(l.zoomsliderControl)&&l.zoomsliderControl===!1&&o.zoomsliderControl.removeFrom(o),!k(g.eventBroadcast)){var q="broadcast";n(o,m,"eventName",a,q)}o.whenReady(function(){b.setMap(o,g.id)}),a.$on("$destroy",function(){c.reset(),o.remove(),b.unresolveMap(g.id)}),a.$on("invalidateSize",function(){o.invalidateSize()})}}}]),angular.module("leaflet-directive").factory("leafletBoundsHelpers",["$log","leafletHelpers",function(a,b){function c(a){return angular.isDefined(a)&&angular.isDefined(a.southWest)&&angular.isDefined(a.northEast)&&angular.isNumber(a.southWest.lat)&&angular.isNumber(a.southWest.lng)&&angular.isNumber(a.northEast.lat)&&angular.isNumber(a.northEast.lng)}var d=b.isArray,e=b.isNumber,f=b.isFunction,g=b.isDefined;return{createLeafletBounds:function(a){return c(a)?L.latLngBounds([a.southWest.lat,a.southWest.lng],[a.northEast.lat,a.northEast.lng]):void 0},isValidBounds:c,createBoundsFromArray:function(b){return d(b)&&2===b.length&&d(b[0])&&d(b[1])&&2===b[0].length&&2===b[1].length&&e(b[0][0])&&e(b[0][1])&&e(b[1][0])&&e(b[1][1])?{northEast:{lat:b[0][0],lng:b[0][1]},southWest:{lat:b[1][0],lng:b[1][1]}}:void a.error("[AngularJS - Leaflet] The bounds array is not valid.")},createBoundsFromLeaflet:function(b){if(!(g(b)&&f(b.getNorthEast)&&f(b.getSouthWest)))return void a.error("[AngularJS - Leaflet] The leaflet bounds is not valid object.");var c=b.getNorthEast(),d=b.getSouthWest();return{northEast:{lat:c.lat,lng:c.lng},southWest:{lat:d.lat,lng:d.lng}}}}}]),angular.module("leaflet-directive").factory("leafletControlHelpers",["$rootScope","$log","leafletHelpers","leafletLayerHelpers","leafletMapDefaults",function(a,b,c,d,e){var f=c.isDefined,g=c.isObject,h=d.createLayer,i={},j=c.errorHeader+" [Controls] ",k=function(a,b,c){var d=e.getDefaults(c);if(!d.controls.layers.visible)return!1;var h=!1;return g(a)&&Object.keys(a).forEach(function(b){var c=a[b];f(c.layerOptions)&&c.layerOptions.showOnSelector===!1||(h=!0)}),g(b)&&Object.keys(b).forEach(function(a){var c=b[a];f(c.layerParams)&&c.layerParams.showOnSelector===!1||(h=!0)}),h},l=function(a){var b=e.getDefaults(a),c={collapsed:b.controls.layers.collapsed,position:b.controls.layers.position,autoZIndex:!1};angular.extend(c,b.controls.layers.options);var d;return d=b.controls.layers&&f(b.controls.layers.control)?b.controls.layers.control.apply(this,[[],[],c]):new L.control.layers([],[],c)},m={draw:{isPluginLoaded:function(){return angular.isDefined(L.Control.Draw)?!0:(b.error(j+" Draw plugin is not loaded."),!1)},checkValidParams:function(){return!0},createControl:function(a){return new L.Control.Draw(a)}},scale:{isPluginLoaded:function(){return!0},checkValidParams:function(){return!0},createControl:function(a){return new L.control.scale(a)}},fullscreen:{isPluginLoaded:function(){return angular.isDefined(L.Control.Fullscreen)?!0:(b.error(j+" Fullscreen plugin is not loaded."),!1)},checkValidParams:function(){return!0},createControl:function(a){return new L.Control.Fullscreen(a)}},search:{isPluginLoaded:function(){return angular.isDefined(L.Control.Search)?!0:(b.error(j+" Search plugin is not loaded."),!1)},checkValidParams:function(){return!0},createControl:function(a){return new L.Control.Search(a)}},custom:{},minimap:{isPluginLoaded:function(){return angular.isDefined(L.Control.MiniMap)?!0:(b.error(j+" Minimap plugin is not loaded."),!1)},checkValidParams:function(a){return f(a.layer)?!0:(b.warn(j+' minimap "layer" option should be defined.'),!1)},createControl:function(a){var c=h(a.layer);return f(c)?new L.Control.MiniMap(c,a):void b.warn(j+' minimap control "layer" could not be created.')}}};return{layersControlMustBeVisible:k,isValidControlType:function(a){return-1!==Object.keys(m).indexOf(a)},createControl:function(a,b){return m[a].checkValidParams(b)?m[a].createControl(b):void 0},updateLayersControl:function(a,b,c,d,e,g){var h,j=i[b],m=k(d,e,b);if(f(j)&&c){for(h in g.baselayers)j.removeLayer(g.baselayers[h]);for(h in g.overlays)j.removeLayer(g.overlays[h]);a.removeControl(j),delete i[b]}if(m){j=l(b),i[b]=j;for(h in d){var n=f(d[h].layerOptions)&&d[h].layerOptions.showOnSelector===!1;!n&&f(g.baselayers[h])&&j.addBaseLayer(g.baselayers[h],d[h].name)}for(h in e){var o=f(e[h].layerParams)&&e[h].layerParams.showOnSelector===!1;!o&&f(g.overlays[h])&&j.addOverlay(g.overlays[h],e[h].name)}a.addControl(j)}return m}}}]),angular.module("leaflet-directive").service("leafletData",["$log","$q","leafletHelpers",function(a,b,c){var d=c.getDefer,e=c.getUnresolvedDefer,f=c.setResolvedDefer,g={},h=this,i=function(a){return a.charAt(0).toUpperCase()+a.slice(1)},j=["map","tiles","layers","paths","markers","geoJSON","UTFGrid","decorations","directiveControls"];j.forEach(function(a){g[a]={}}),this.unresolveMap=function(a){var b=c.obtainEffectiveMapId(g.map,a);j.forEach(function(a){g[a][b]=void 0})},j.forEach(function(a){var b=i(a);h["set"+b]=function(b,c){var d=e(g[a],c);d.resolve(b),f(g[a],c)},h["get"+b]=function(b){var c=d(g[a],b);return c.promise}})}]),angular.module("leaflet-directive").service("leafletDirectiveControlsHelpers",["$log","leafletData","leafletHelpers",function(a,b,c){var d=c.isDefined,e=c.isString,f=c.isObject,g=c.errorHeader,h=g+"[leafletDirectiveControlsHelpers",i=function(c,g,i,j){var k=h+".extend] ",l={};if(!d(g))return void a.error(k+"thingToAddName cannot be undefined");if(e(g)&&d(i)&&d(j))l[g]={create:i,clean:j};else{if(!f(g)||d(i)||d(j))return void a.error(k+"incorrect arguments");l=g}b.getDirectiveControls().then(function(a){angular.extend(a,l),b.setDirectiveControls(a,c)})};return{extend:i}}]),angular.module("leaflet-directive").service("leafletGeoJsonHelpers",["leafletHelpers","leafletIterators",function(a,b){var c=a,d=b,e=function(a,b){return this.lat=a,this.lng=b,this},f=function(a){return Array.isArray(a)&&2===a.length?a[1]:c.isDefined(a.type)&&"Point"===a.type?+a.coordinates[1]:+a.lat},g=function(a){return Array.isArray(a)&&2===a.length?a[0]:c.isDefined(a.type)&&"Point"===a.type?+a.coordinates[0]:+a.lng},h=function(a){if(c.isUndefined(a))return!1;if(c.isArray(a)){if(2===a.length&&c.isNumber(a[0])&&c.isNumber(a[1]))return!0}else if(c.isDefined(a.type)&&"Point"===a.type&&c.isArray(a.coordinates)&&2===a.coordinates.length&&c.isNumber(a.coordinates[0])&&c.isNumber(a.coordinates[1]))return!0;var b=d.all(["lat","lng"],function(b){return c.isDefined(a[b])&&c.isNumber(a[b])});return b},i=function(a){if(a&&h(a)){var b=null;if(Array.isArray(a)&&2===a.length)b=new e(a[1],a[0]);else{if(!c.isDefined(a.type)||"Point"!==a.type)return a;b=new e(a.coordinates[1],a.coordinates[0])}return angular.extend(a,b)}};return{getLat:f,getLng:g,validateCoords:h,getCoords:i}}]),angular.module("leaflet-directive").service("leafletHelpers",["$q","$log",function(a,b){function c(a,c){var d,f;if(angular.isDefined(c))d=c;else if(0===Object.keys(a).length)d="main";else if(Object.keys(a).length>=1)for(f in a)a.hasOwnProperty(f)&&(d=f);else b.error(e+"- You have more than 1 map on the DOM, you must provide the map ID to the leafletData.getXXX call");return d}function d(b,d){var e,f=c(b,d);return angular.isDefined(b[f])&&b[f].resolvedDefer!==!0?e=b[f].defer:(e=a.defer(),b[f]={defer:e,resolvedDefer:!1}),e}var e="[AngularJS - Leaflet] ",f=angular.copy,g=f,h=function(a,b){var c;if(a&&angular.isObject(a))return null!==b&&angular.isString(b)?(c=a,b.split(".").forEach(function(a){c&&(c=c[a])}),c):b},i=function(a){return a.split(".").reduce(function(a,b){return a+'["'+b+'"]'})},j=function(a){return a.reduce(function(a,b){return a+"."+b})},k=function(a){return angular.isDefined(a)&&null!==a},l=function(a){return!k(a)},m=/([\:\-\_]+(.))/g,n=/^moz([A-Z])/,o=/^((?:x|data)[\:\-_])/i,p=function(a){return a.replace(m,function(a,b,c,d){return d?c.toUpperCase():c}).replace(n,"Moz$1")},q=function(a){return p(a.replace(o,""))};return{camelCase:p,directiveNormalize:q,copy:f,clone:g,errorHeader:e,getObjectValue:h,getObjectArrayPath:i,getObjectDotPath:j,defaultTo:function(a,b){return k(a)?a:b},isTruthy:function(a){return"true"===a||a===!0},isEmpty:function(a){return 0===Object.keys(a).length},isUndefinedOrEmpty:function(a){return angular.isUndefined(a)||null===a||0===Object.keys(a).length},isDefined:k,isUndefined:l,isNumber:angular.isNumber,isString:angular.isString,isArray:angular.isArray,isObject:angular.isObject,isFunction:angular.isFunction,equals:angular.equals,isValidCenter:function(a){return angular.isDefined(a)&&angular.isNumber(a.lat)&&angular.isNumber(a.lng)&&angular.isNumber(a.zoom)},isValidPoint:function(a){return angular.isDefined(a)?angular.isArray(a)?2===a.length&&angular.isNumber(a[0])&&angular.isNumber(a[1]):angular.isNumber(a.lat)&&angular.isNumber(a.lng):!1},isSameCenterOnMap:function(a,b){var c=b.getCenter(),d=b.getZoom();return a.lat&&a.lng&&c.lat.toFixed(4)===a.lat.toFixed(4)&&c.lng.toFixed(4)===a.lng.toFixed(4)&&d===a.zoom?!0:!1},safeApply:function(a,b){var c=a.$root.$$phase;"$apply"===c||"$digest"===c?a.$eval(b):a.$evalAsync(b)},obtainEffectiveMapId:c,getDefer:function(a,b){var e,f=c(a,b);return e=angular.isDefined(a[f])&&a[f].resolvedDefer!==!1?a[f].defer:d(a,b)},getUnresolvedDefer:d,setResolvedDefer:function(a,b){var d=c(a,b);a[d].resolvedDefer=!0},rangeIsSupported:function(){var a=document.createElement("input");return a.setAttribute("type","range"),"range"===a.type},FullScreenControlPlugin:{isLoaded:function(){return angular.isDefined(L.Control.Fullscreen)}},MiniMapControlPlugin:{isLoaded:function(){return angular.isDefined(L.Control.MiniMap)}},AwesomeMarkersPlugin:{isLoaded:function(){return angular.isDefined(L.AwesomeMarkers)&&angular.isDefined(L.AwesomeMarkers.Icon)},is:function(a){return this.isLoaded()?a instanceof L.AwesomeMarkers.Icon:!1},equal:function(a,b){return this.isLoaded()&&this.is(a)?angular.equals(a,b):!1}},VectorMarkersPlugin:{isLoaded:function(){return angular.isDefined(L.VectorMarkers)&&angular.isDefined(L.VectorMarkers.Icon)},is:function(a){return this.isLoaded()?a instanceof L.VectorMarkers.Icon:!1},equal:function(a,b){return this.isLoaded()&&this.is(a)?angular.equals(a,b):!1}},DomMarkersPlugin:{isLoaded:function(){return angular.isDefined(L.DomMarkers)&&angular.isDefined(L.DomMarkers.Icon)?!0:!1},is:function(a){return this.isLoaded()?a instanceof L.DomMarkers.Icon:!1},equal:function(a,b){return this.isLoaded()&&this.is(a)?angular.equals(a,b):!1}},PolylineDecoratorPlugin:{isLoaded:function(){return angular.isDefined(L.PolylineDecorator)?!0:!1},is:function(a){return this.isLoaded()?a instanceof L.PolylineDecorator:!1},equal:function(a,b){return this.isLoaded()&&this.is(a)?angular.equals(a,b):!1}},MakiMarkersPlugin:{isLoaded:function(){return angular.isDefined(L.MakiMarkers)&&angular.isDefined(L.MakiMarkers.Icon)?!0:!1},is:function(a){return this.isLoaded()?a instanceof L.MakiMarkers.Icon:!1},equal:function(a,b){return this.isLoaded()&&this.is(a)?angular.equals(a,b):!1}},ExtraMarkersPlugin:{isLoaded:function(){return angular.isDefined(L.ExtraMarkers)&&angular.isDefined(L.ExtraMarkers.Icon)?!0:!1},is:function(a){return this.isLoaded()?a instanceof L.ExtraMarkers.Icon:!1},equal:function(a,b){return this.isLoaded()&&this.is(a)?angular.equals(a,b):!1}},LabelPlugin:{isLoaded:function(){return angular.isDefined(L.Label)},is:function(a){return this.isLoaded()?a instanceof L.MarkerClusterGroup:!1}},MarkerClusterPlugin:{isLoaded:function(){return angular.isDefined(L.MarkerClusterGroup)},is:function(a){return this.isLoaded()?a instanceof L.MarkerClusterGroup:!1}},GoogleLayerPlugin:{isLoaded:function(){return angular.isDefined(L.Google)},is:function(a){return this.isLoaded()?a instanceof L.Google:!1}},LeafletProviderPlugin:{isLoaded:function(){return angular.isDefined(L.TileLayer.Provider)},is:function(a){return this.isLoaded()?a instanceof L.TileLayer.Provider:!1}},ChinaLayerPlugin:{isLoaded:function(){return angular.isDefined(L.tileLayer.chinaProvider)}},HeatLayerPlugin:{isLoaded:function(){return angular.isDefined(L.heatLayer)}},WebGLHeatMapLayerPlugin:{isLoaded:function(){return angular.isDefined(L.TileLayer.WebGLHeatMap)}},BingLayerPlugin:{isLoaded:function(){return angular.isDefined(L.BingLayer)},is:function(a){return this.isLoaded()?a instanceof L.BingLayer:!1}},WFSLayerPlugin:{isLoaded:function(){return void 0!==L.GeoJSON.WFS},is:function(a){return this.isLoaded()?a instanceof L.GeoJSON.WFS:!1}},AGSBaseLayerPlugin:{isLoaded:function(){return void 0!==L.esri&&void 0!==L.esri.basemapLayer},is:function(a){return this.isLoaded()?a instanceof L.esri.basemapLayer:!1}},AGSLayerPlugin:{isLoaded:function(){return void 0!==lvector&&void 0!==lvector.AGS},is:function(a){return this.isLoaded()?a instanceof lvector.AGS:!1}},AGSFeatureLayerPlugin:{isLoaded:function(){return void 0!==L.esri&&void 0!==L.esri.featureLayer},is:function(a){return this.isLoaded()?a instanceof L.esri.featureLayer:!1}},AGSTiledMapLayerPlugin:{isLoaded:function(){return void 0!==L.esri&&void 0!==L.esri.tiledMapLayer},is:function(a){return this.isLoaded()?a instanceof L.esri.tiledMapLayer:!1}},AGSDynamicMapLayerPlugin:{isLoaded:function(){return void 0!==L.esri&&void 0!==L.esri.dynamicMapLayer},is:function(a){return this.isLoaded()?a instanceof L.esri.dynamicMapLayer:!1}},AGSImageMapLayerPlugin:{isLoaded:function(){return void 0!==L.esri&&void 0!==L.esri.imageMapLayer},is:function(a){return this.isLoaded()?a instanceof L.esri.imageMapLayer:!1}},AGSClusteredLayerPlugin:{isLoaded:function(){return void 0!==L.esri&&void 0!==L.esri.clusteredFeatureLayer},is:function(a){return this.isLoaded()?a instanceof L.esri.clusteredFeatureLayer:!1}},AGSHeatmapLayerPlugin:{isLoaded:function(){return void 0!==L.esri&&void 0!==L.esri.heatmapFeatureLayer},is:function(a){return this.isLoaded()?a instanceof L.esri.heatmapFeatureLayer:!1}},YandexLayerPlugin:{isLoaded:function(){return angular.isDefined(L.Yandex)},is:function(a){return this.isLoaded()?a instanceof L.Yandex:!1}},GeoJSONPlugin:{isLoaded:function(){return angular.isDefined(L.TileLayer.GeoJSON)},is:function(a){return this.isLoaded()?a instanceof L.TileLayer.GeoJSON:!1}},UTFGridPlugin:{isLoaded:function(){return angular.isDefined(L.UtfGrid)},is:function(a){return this.isLoaded()?a instanceof L.UtfGrid:(b.error("[AngularJS - Leaflet] No UtfGrid plugin found."),!1)}},CartoDB:{isLoaded:function(){return cartodb},is:function(){return!0}},Leaflet:{DivIcon:{is:function(a){return a instanceof L.DivIcon},equal:function(a,b){return this.is(a)?angular.equals(a,b):!1}},Icon:{is:function(a){return a instanceof L.Icon},equal:function(a,b){return this.is(a)?angular.equals(a,b):!1}}},watchOptions:{doWatch:!0,isDeep:!0,individual:{doWatch:!0,isDeep:!0}}}}]),angular.module("leaflet-directive").service("leafletIterators",["$log","leafletHelpers",function(a,b){var c,d=b,e=b.errorHeader+"leafletIterators: ",f=Object.keys,g=d.isFunction,h=d.isObject,i=Math.pow(2,53)-1,j=function(a){var b=null!==a&&a.length;return d.isNumber(b)&&b>=0&&i>=b},k=function(a){return a},l=function(a){return function(b){return null===b?void 0:b[a]}},m=function(a,b,c){if(void 0===b)return a;switch(null===c?3:c){case 1:return function(c){return a.call(b,c)};case 2:return function(c,d){return a.call(b,c,d)};case 3:return function(c,d,e){return a.call(b,c,d,e)};case 4:return function(c,d,e,f){return a.call(b,c,d,e,f)}}return function(){return a.apply(b,arguments)}},n=function(a,b){return function(c){var d=arguments.length;if(2>d||null===c)return c;for(var e=1;d>e;e++)for(var f=arguments[e],g=a(f),h=g.length,i=0;h>i;i++){var j=g[i];b&&void 0!==c[j]||(c[j]=f[j])}return c}},o=null;c=o=n(f);var p,q=function(a,b){var c=f(b),d=c.length;if(null===a)return!d;for(var e=Object(a),g=0;d>g;g++){var h=c[g];if(b[h]!==e[h]||!(h in e))return!1}return!0},r=null;p=r=function(a){return a=c({},a),function(b){return q(b,a)}};var s,t=function(a,b,c){return null===a?k:g(a)?m(a,b,c):h(a)?p(a):l(a)},u=null;s=u=function(a,b,c){b=t(b,c);for(var d=!j(a)&&f(a),e=(d||a).length,g=0;e>g;g++){var h=d?d[g]:g;if(!b(a[h],h,a))return!1}return!0};var v=function(b,c,f,g){return f||d.isDefined(b)&&d.isDefined(c)?d.isFunction(c)?!1:(g=d.defaultTo(c,"cb"),a.error(e+g+" is not a function"),!0):!0},w=function(a,b,c){if(!v(void 0,c,!0,"internalCb")&&!v(a,b))for(var d in a)a.hasOwnProperty(d)&&c(a[d],d)},x=function(a,b){w(a,b,function(a,c){b(a,c)})};return{each:x,forEach:x,every:s,all:u}}]),angular.module("leaflet-directive").factory("leafletLayerHelpers",["$rootScope","$log","$q","leafletHelpers","leafletIterators",function($rootScope,$log,$q,leafletHelpers,leafletIterators){function isValidLayerType(a){return isString(a.type)?-1===Object.keys(layerTypes).indexOf(a.type)?($log.error("[AngularJS - Leaflet] A layer must have a valid type: "+Object.keys(layerTypes)),!1):layerTypes[a.type].mustHaveUrl&&!isString(a.url)?($log.error("[AngularJS - Leaflet] A base layer must have an url"),!1):layerTypes[a.type].mustHaveData&&!isDefined(a.data)?($log.error('[AngularJS - Leaflet] The base layer must have a "data" array attribute'),!1):layerTypes[a.type].mustHaveLayer&&!isDefined(a.layer)?($log.error("[AngularJS - Leaflet] The type of layer "+a.type+" must have an layer defined"),!1):layerTypes[a.type].mustHaveBounds&&!isDefined(a.bounds)?($log.error("[AngularJS - Leaflet] The type of layer "+a.type+" must have bounds defined"),!1):layerTypes[a.type].mustHaveKey&&!isDefined(a.key)?($log.error("[AngularJS - Leaflet] The type of layer "+a.type+" must have key defined"),!1):!0:($log.error("[AngularJS - Leaflet] A layer must have a valid type defined."),!1)}function createLayer(a){if(isValidLayerType(a)){if(!isString(a.name))return void $log.error("[AngularJS - Leaflet] A base layer must have a name");isObject(a.layerParams)||(a.layerParams={}),isObject(a.layerOptions)||(a.layerOptions={});for(var b in a.layerParams)a.layerOptions[b]=a.layerParams[b];var c={url:a.url,data:a.data,options:a.layerOptions,layer:a.layer,icon:a.icon,type:a.layerType,bounds:a.bounds,key:a.key,apiKey:a.apiKey,pluginOptions:a.pluginOptions,user:a.user};return layerTypes[a.type].createLayer(c)}}function safeAddLayer(a,b){b&&"function"==typeof b.addTo?b.addTo(a):a.addLayer(b)}function safeRemoveLayer(a,b,c){if(isDefined(c)&&isDefined(c.loadedDefer))if(angular.isFunction(c.loadedDefer)){var d=c.loadedDefer();$log.debug("Loaded Deferred",d);var e=d.length;if(e>0)for(var f=function(){e--,0===e&&a.removeLayer(b)},g=0;g<d.length;g++)d[g].promise.then(f);else a.removeLayer(b)}else c.loadedDefer.promise.then(function(){a.removeLayer(b)});else a.removeLayer(b)}var Helpers=leafletHelpers,isString=leafletHelpers.isString,isObject=leafletHelpers.isObject,isArray=leafletHelpers.isArray,isDefined=leafletHelpers.isDefined,errorHeader=leafletHelpers.errorHeader,$it=leafletIterators,utfGridCreateLayer=function(a){if(!Helpers.UTFGridPlugin.isLoaded())return void $log.error("[AngularJS - Leaflet] The UTFGrid plugin is not loaded.");var b=new L.UtfGrid(a.url,a.pluginOptions);return b.on("mouseover",function(a){$rootScope.$broadcast("leafletDirectiveMap.utfgridMouseover",a)}),b.on("mouseout",function(a){$rootScope.$broadcast("leafletDirectiveMap.utfgridMouseout",a)}),b.on("click",function(a){$rootScope.$broadcast("leafletDirectiveMap.utfgridClick",a)}),b.on("mousemove",function(a){$rootScope.$broadcast("leafletDirectiveMap.utfgridMousemove",a)}),b},layerTypes={xyz:{mustHaveUrl:!0,createLayer:function(a){return L.tileLayer(a.url,a.options)}},mapbox:{mustHaveKey:!0,createLayer:function(a){var b=3;isDefined(a.options.version)&&4===a.options.version&&(b=a.options.version);var c=3===b?"//{s}.tiles.mapbox.com/v3/"+a.key+"/{z}/{x}/{y}.png":"//api.tiles.mapbox.com/v4/"+a.key+"/{z}/{x}/{y}.png?access_token="+a.apiKey;return L.tileLayer(c,a.options)}},geoJSON:{mustHaveUrl:!0,createLayer:function(a){return Helpers.GeoJSONPlugin.isLoaded()?new L.TileLayer.GeoJSON(a.url,a.pluginOptions,a.options):void 0}},geoJSONShape:{mustHaveUrl:!1,createLayer:function(a){return new L.GeoJSON(a.data,a.options)}},geoJSONAwesomeMarker:{mustHaveUrl:!1,createLayer:function(a){return new L.geoJson(a.data,{pointToLayer:function(b,c){return L.marker(c,{icon:L.AwesomeMarkers.icon(a.icon)})}})}},geoJSONVectorMarker:{mustHaveUrl:!1,createLayer:function(a){return new L.geoJson(a.data,{pointToLayer:function(b,c){return L.marker(c,{icon:L.VectorMarkers.icon(a.icon)})}})}},utfGrid:{mustHaveUrl:!0,createLayer:utfGridCreateLayer},cartodbTiles:{mustHaveKey:!0,createLayer:function(a){var b="//"+a.user+".cartodb.com/api/v1/map/"+a.key+"/{z}/{x}/{y}.png";return L.tileLayer(b,a.options)}},cartodbUTFGrid:{mustHaveKey:!0,mustHaveLayer:!0,createLayer:function(a){return a.url="//"+a.user+".cartodb.com/api/v1/map/"+a.key+"/"+a.layer+"/{z}/{x}/{y}.grid.json",utfGridCreateLayer(a)}},cartodbInteractive:{mustHaveKey:!0,mustHaveLayer:!0,createLayer:function(a){var b="//"+a.user+".cartodb.com/api/v1/map/"+a.key+"/{z}/{x}/{y}.png",c=L.tileLayer(b,a.options);a.url="//"+a.user+".cartodb.com/api/v1/map/"+a.key+"/"+a.layer+"/{z}/{x}/{y}.grid.json";var d=utfGridCreateLayer(a);return L.layerGroup([c,d])}},wms:{mustHaveUrl:!0,createLayer:function(a){return L.tileLayer.wms(a.url,a.options)}},wmts:{mustHaveUrl:!0,createLayer:function(a){return L.tileLayer.wmts(a.url,a.options)}},wfs:{mustHaveUrl:!0,mustHaveLayer:!0,createLayer:function(params){if(Helpers.WFSLayerPlugin.isLoaded()){var options=angular.copy(params.options);return options.crs&&"string"==typeof options.crs&&(options.crs=eval(options.crs)),new L.GeoJSON.WFS(params.url,params.layer,options)}}},group:{mustHaveUrl:!1,createLayer:function(a){var b=[];return $it.each(a.options.layers,function(a){b.push(createLayer(a))}),a.options.loadedDefer=function(){var b=[];if(isDefined(a.options.layers))for(var c=0;c<a.options.layers.length;c++){var d=a.options.layers[c].layerOptions.loadedDefer;isDefined(d)&&b.push(d)}return b},L.layerGroup(b)}},featureGroup:{mustHaveUrl:!1,createLayer:function(){return L.featureGroup()}},google:{mustHaveUrl:!1,createLayer:function(a){var b=a.type||"SATELLITE";if(Helpers.GoogleLayerPlugin.isLoaded())return new L.Google(b,a.options)}},here:{mustHaveUrl:!1,createLayer:function(a){var b=a.provider||"HERE.terrainDay";if(Helpers.LeafletProviderPlugin.isLoaded())return new L.TileLayer.Provider(b,a.options)}},china:{mustHaveUrl:!1,createLayer:function(a){var b=a.type||"";if(Helpers.ChinaLayerPlugin.isLoaded())return L.tileLayer.chinaProvider(b,a.options)}},agsBase:{mustHaveLayer:!0,createLayer:function(a){return Helpers.AGSBaseLayerPlugin.isLoaded()?L.esri.basemapLayer(a.layer,a.options):void 0}},ags:{mustHaveUrl:!0,createLayer:function(a){if(Helpers.AGSLayerPlugin.isLoaded()){var b=angular.copy(a.options);angular.extend(b,{url:a.url});var c=new lvector.AGS(b);return c.onAdd=function(a){this.setMap(a)},c.onRemove=function(){this.setMap(null)},c}}},agsFeature:{mustHaveUrl:!0,createLayer:function(a){if(!Helpers.AGSFeatureLayerPlugin.isLoaded())return void $log.warn(errorHeader+" The esri plugin is not loaded.");a.options.url=a.url;var b=L.esri.featureLayer(a.options),c=function(){isDefined(a.options.loadedDefer)&&a.options.loadedDefer.resolve()};return b.on("loading",function(){a.options.loadedDefer=$q.defer(),b.off("load",c),b.on("load",c)}),b}},agsTiled:{mustHaveUrl:!0,createLayer:function(a){return Helpers.AGSTiledMapLayerPlugin.isLoaded()?(a.options.url=a.url,L.esri.tiledMapLayer(a.options)):void $log.warn(errorHeader+" The esri plugin is not loaded.")}},agsDynamic:{mustHaveUrl:!0,createLayer:function(a){return Helpers.AGSDynamicMapLayerPlugin.isLoaded()?(a.options.url=a.url,L.esri.dynamicMapLayer(a.options)):void $log.warn(errorHeader+" The esri plugin is not loaded.")}},agsImage:{mustHaveUrl:!0,createLayer:function(a){return Helpers.AGSImageMapLayerPlugin.isLoaded()?(a.options.url=a.url,L.esri.imageMapLayer(a.options)):void $log.warn(errorHeader+" The esri plugin is not loaded.")}},agsClustered:{mustHaveUrl:!0,createLayer:function(a){return Helpers.AGSClusteredLayerPlugin.isLoaded()?Helpers.MarkerClusterPlugin.isLoaded()?L.esri.clusteredFeatureLayer(a.url,a.options):void $log.warn(errorHeader+" The markercluster plugin is not loaded."):void $log.warn(errorHeader+" The esri clustered layer plugin is not loaded.")}},agsHeatmap:{mustHaveUrl:!0,createLayer:function(a){return Helpers.AGSHeatmapLayerPlugin.isLoaded()?Helpers.HeatLayerPlugin.isLoaded()?L.esri.heatmapFeatureLayer(a.url,a.options):void $log.warn(errorHeader+" The heatlayer plugin is not loaded."):void $log.warn(errorHeader+" The esri heatmap layer plugin is not loaded.")}},markercluster:{mustHaveUrl:!1,createLayer:function(a){return Helpers.MarkerClusterPlugin.isLoaded()?new L.MarkerClusterGroup(a.options):void $log.warn(errorHeader+" The markercluster plugin is not loaded.")}},bing:{mustHaveUrl:!1,createLayer:function(a){return Helpers.BingLayerPlugin.isLoaded()?new L.BingLayer(a.key,a.options):void 0}},webGLHeatmap:{mustHaveUrl:!1,mustHaveData:!0,createLayer:function(a){if(Helpers.WebGLHeatMapLayerPlugin.isLoaded()){var b=new L.TileLayer.WebGLHeatMap(a.options);return isDefined(a.data)&&b.setData(a.data),b}}},heat:{mustHaveUrl:!1,mustHaveData:!0,createLayer:function(a){if(Helpers.HeatLayerPlugin.isLoaded()){var b=new L.heatLayer;return isArray(a.data)&&b.setLatLngs(a.data),isObject(a.options)&&b.setOptions(a.options),b}}},yandex:{mustHaveUrl:!1,createLayer:function(a){var b=a.type||"map";if(Helpers.YandexLayerPlugin.isLoaded())return new L.Yandex(b,a.options)}},imageOverlay:{mustHaveUrl:!0,mustHaveBounds:!0,createLayer:function(a){return L.imageOverlay(a.url,a.bounds,a.options)}},iip:{mustHaveUrl:!0,createLayer:function(a){return L.tileLayer.iip(a.url,a.options)}},custom:{createLayer:function(a){return a.layer instanceof L.Class?angular.copy(a.layer):void $log.error("[AngularJS - Leaflet] A custom layer must be a leaflet Class")}},cartodb:{mustHaveUrl:!0,createLayer:function(a){return cartodb.createLayer(a.map,a.url)}}};return{createLayer:createLayer,safeAddLayer:safeAddLayer,safeRemoveLayer:safeRemoveLayer}}]),angular.module("leaflet-directive").factory("leafletLegendHelpers",function(){var a=function(a,b,c,d){if(a.innerHTML="",b.error)a.innerHTML+='<div class="info-title alert alert-danger">'+b.error.message+"</div>";else if("arcgis"===c)for(var e=0;e<b.layers.length;e++){var f=b.layers[e];a.innerHTML+='<div class="info-title" data-layerid="'+f.layerId+'">'+f.layerName+"</div>";for(var g=0;g<f.legend.length;g++){var h=f.legend[g];a.innerHTML+='<div class="inline" data-layerid="'+f.layerId+'"><img src="data:'+h.contentType+";base64,"+h.imageData+'" /></div><div class="info-label" data-layerid="'+f.layerId+'">'+h.label+"</div>"}}else"image"===c&&(a.innerHTML='<img src="'+d+'"/>')},b=function(b,c,d,e){return function(){var f=L.DomUtil.create("div",c);return L.Browser.touch?L.DomEvent.on(f,"click",L.DomEvent.stopPropagation):(L.DomEvent.disableClickPropagation(f),L.DomEvent.on(f,"mousewheel",L.DomEvent.stopPropagation)),a(f,b,d,e),f}},c=function(a,b){return function(){for(var c=L.DomUtil.create("div",b),d=0;d<a.colors.length;d++)c.innerHTML+='<div class="outline"><i style="background:'+a.colors[d]+'"></i></div><div class="info-label">'+a.labels[d]+"</div>";return L.Browser.touch?L.DomEvent.on(c,"click",L.DomEvent.stopPropagation):(L.DomEvent.disableClickPropagation(c),L.DomEvent.on(c,"mousewheel",L.DomEvent.stopPropagation)),c}};return{getOnAddLegend:b,getOnAddArrayLegend:c,updateLegend:a}}),angular.module("leaflet-directive").factory("leafletMapDefaults",["$q","leafletHelpers",function(a,b){function c(){return{keyboard:!0,dragging:!0,worldCopyJump:!1,doubleClickZoom:!0,scrollWheelZoom:!0,tap:!0,touchZoom:!0,zoomControl:!0,zoomsliderControl:!1,zoomControlPosition:"topleft",attributionControl:!0,controls:{layers:{visible:!0,position:"topright",collapsed:!0}},nominatim:{server:" http://nominatim.openstreetmap.org/search"},crs:L.CRS.EPSG3857,tileLayer:"//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",tileLayerOptions:{attribution:'© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'},path:{weight:10,opacity:1,color:"#0000ff"},center:{lat:0,lng:0,zoom:1}}}var d=b.isDefined,e=b.isObject,f=b.obtainEffectiveMapId,g={};return{reset:function(){g={}},getDefaults:function(a){var b=f(g,a);return g[b]},getMapCreationDefaults:function(a){var b=f(g,a),c=g[b],e={maxZoom:c.maxZoom,keyboard:c.keyboard,dragging:c.dragging,zoomControl:c.zoomControl,doubleClickZoom:c.doubleClickZoom,scrollWheelZoom:c.scrollWheelZoom,tap:c.tap,touchZoom:c.touchZoom,attributionControl:c.attributionControl,worldCopyJump:c.worldCopyJump,crs:c.crs};if(d(c.minZoom)&&(e.minZoom=c.minZoom),d(c.zoomAnimation)&&(e.zoomAnimation=c.zoomAnimation),d(c.fadeAnimation)&&(e.fadeAnimation=c.fadeAnimation),d(c.markerZoomAnimation)&&(e.markerZoomAnimation=c.markerZoomAnimation),c.map)for(var h in c.map)e[h]=c.map[h];return e},setDefaults:function(a,b){var h=c();d(a)&&(h.doubleClickZoom=d(a.doubleClickZoom)?a.doubleClickZoom:h.doubleClickZoom,h.scrollWheelZoom=d(a.scrollWheelZoom)?a.scrollWheelZoom:h.doubleClickZoom,h.tap=d(a.tap)?a.tap:h.tap,h.touchZoom=d(a.touchZoom)?a.touchZoom:h.doubleClickZoom,h.zoomControl=d(a.zoomControl)?a.zoomControl:h.zoomControl,h.zoomsliderControl=d(a.zoomsliderControl)?a.zoomsliderControl:h.zoomsliderControl,h.attributionControl=d(a.attributionControl)?a.attributionControl:h.attributionControl,h.tileLayer=d(a.tileLayer)?a.tileLayer:h.tileLayer,h.zoomControlPosition=d(a.zoomControlPosition)?a.zoomControlPosition:h.zoomControlPosition,h.keyboard=d(a.keyboard)?a.keyboard:h.keyboard,h.dragging=d(a.dragging)?a.dragging:h.dragging,d(a.controls)&&angular.extend(h.controls,a.controls),e(a.crs)?h.crs=a.crs:d(L.CRS[a.crs])&&(h.crs=L.CRS[a.crs]),d(a.center)&&angular.copy(a.center,h.center),d(a.tileLayerOptions)&&angular.copy(a.tileLayerOptions,h.tileLayerOptions),d(a.maxZoom)&&(h.maxZoom=a.maxZoom),d(a.minZoom)&&(h.minZoom=a.minZoom),d(a.zoomAnimation)&&(h.zoomAnimation=a.zoomAnimation),d(a.fadeAnimation)&&(h.fadeAnimation=a.fadeAnimation),d(a.markerZoomAnimation)&&(h.markerZoomAnimation=a.markerZoomAnimation),d(a.worldCopyJump)&&(h.worldCopyJump=a.worldCopyJump),d(a.map)&&(h.map=a.map),d(a.path)&&(h.path=a.path));var i=f(g,b);return g[i]=h,h}}}]),angular.module("leaflet-directive").service("leafletMarkersHelpers",["$rootScope","$timeout","leafletHelpers","$log","$compile","leafletGeoJsonHelpers",function(a,b,c,d,e,f){var g=c.isDefined,h=c.defaultTo,i=c.MarkerClusterPlugin,j=c.AwesomeMarkersPlugin,k=c.VectorMarkersPlugin,l=c.MakiMarkersPlugin,m=c.ExtraMarkersPlugin,n=c.DomMarkersPlugin,o=c.safeApply,p=c,q=c.isString,r=c.isNumber,s=c.isObject,t={},u=f,v=c.errorHeader,w=function(a){ | |
| var b="";return["_icon","_latlng","_leaflet_id","_map","_shadow"].forEach(function(c){b+=c+": "+h(a[c],"undefined")+" \n"}),"[leafletMarker] : \n"+b},x=function(a,b){var c=b?console:d;c.debug(w(a))},y=function(b){if(g(b)&&g(b.type)&&"awesomeMarker"===b.type)return j.isLoaded()||d.error(v+" The AwesomeMarkers Plugin is not loaded."),new L.AwesomeMarkers.icon(b);if(g(b)&&g(b.type)&&"vectorMarker"===b.type)return k.isLoaded()||d.error(v+" The VectorMarkers Plugin is not loaded."),new L.VectorMarkers.icon(b);if(g(b)&&g(b.type)&&"makiMarker"===b.type)return l.isLoaded()||d.error(v+"The MakiMarkers Plugin is not loaded."),new L.MakiMarkers.icon(b);if(g(b)&&g(b.type)&&"extraMarker"===b.type)return m.isLoaded()||d.error(v+"The ExtraMarkers Plugin is not loaded."),new L.ExtraMarkers.icon(b);if(g(b)&&g(b.type)&&"div"===b.type)return new L.divIcon(b);if(g(b)&&g(b.type)&&"dom"===b.type){n.isLoaded()||d.error(v+"The DomMarkers Plugin is not loaded.");var c=angular.isFunction(b.getMarkerScope)?b.getMarkerScope():a,f=e(b.template)(c),h=angular.copy(b);return h.element=f[0],new L.DomMarkers.icon(h)}if(g(b)&&g(b.type)&&"icon"===b.type)return b.icon;var i="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAGmklEQVRYw7VXeUyTZxjvNnfELFuyIzOabermMZEeQC/OclkO49CpOHXOLJl/CAURuYbQi3KLgEhbrhZ1aDwmaoGqKII6odATmH/scDFbdC7LvFqOCc+e95s2VG50X/LLm/f4/Z7neY/ne18aANCmAr5E/xZf1uDOkTcGcWR6hl9247tT5U7Y6SNvWsKT63P58qbfeLJG8M5qcgTknrvvrdDbsT7Ml+tv82X6vVxJE33aRmgSyYtcWVMqX97Yv2JvW39UhRE2HuyBL+t+gK1116ly06EeWFNlAmHxlQE0OMiV6mQCScusKRlhS3QLeVJdl1+23h5dY4FNB3thrbYboqptEFlphTC1hSpJnbRvxP4NWgsE5Jyz86QNNi/5qSUTGuFk1gu54tN9wuK2wc3o+Wc13RCmsoBwEqzGcZsxsvCSy/9wJKf7UWf1mEY8JWfewc67UUoDbDjQC+FqK4QqLVMGGR9d2wurKzqBk3nqIT/9zLxRRjgZ9bqQgub+DdoeCC03Q8j+0QhFhBHR/eP3U/zCln7Uu+hihJ1+bBNffLIvmkyP0gpBZWYXhKussK6mBz5HT6M1Nqpcp+mBCPXosYQfrekGvrjewd59/GvKCE7TbK/04/ZV5QZYVWmDwH1mF3xa2Q3ra3DBC5vBT1oP7PTj4C0+CcL8c7C2CtejqhuCnuIQHaKHzvcRfZpnylFfXsYJx3pNLwhKzRAwAhEqG0SpusBHfAKkxw3w4627MPhoCH798z7s0ZnBJ/MEJbZSbXPhER2ih7p2ok/zSj2cEJDd4CAe+5WYnBCgR2uruyEw6zRoW6/DWJ/OeAP8pd/BGtzOZKpG8oke0SX6GMmRk6GFlyAc59K32OTEinILRJRchah8HQwND8N435Z9Z0FY1EqtxUg+0SO6RJ/mmXz4VuS+DpxXC3gXmZwIL7dBSH4zKE50wESf8qwVgrP1EIlTO5JP9Igu0aexdh28F1lmAEGJGfh7jE6ElyM5Rw/FDcYJjWhbeiBYoYNIpc2FT/SILivp0F1ipDWk4BIEo2VuodEJUifhbiltnNBIXPUFCMpthtAyqws/BPlEF/VbaIxErdxPphsU7rcCp8DohC+GvBIPJS/tW2jtvTmmAeuNO8BNOYQeG8G/2OzCJ3q+soYB5i6NhMaKr17FSal7GIHheuV3uSCY8qYVuEm1cOzqdWr7ku/R0BDoTT+DT+ohCM6/CCvKLKO4RI+dXPeAuaMqksaKrZ7L3FE5FIFbkIceeOZ2OcHO6wIhTkNo0ffgjRGxEqogXHYUPHfWAC/lADpwGcLRY3aeK4/oRGCKYcZXPVoeX/kelVYY8dUGf8V5EBRbgJXT5QIPhP9ePJi428JKOiEYhYXFBqou2Guh+p/mEB1/RfMw6rY7cxcjTrneI1FrDyuzUSRm9miwEJx8E/gUmqlyvHGkneiwErR21F3tNOK5Tf0yXaT+O7DgCvALTUBXdM4YhC/IawPU+2PduqMvuaR6eoxSwUk75ggqsYJ7VicsnwGIkZBSXKOUww73WGXyqP+J2/b9c+gi1YAg/xpwck3gJuucNrh5JvDPvQr0WFXf0piyt8f8/WI0hV4pRxxkQZdJDfDJNOAmM0Ag8jyT6hz0WGXWuP94Yh2jcfjmXAGvHCMslRimDHYuHuDsy2QtHuIavznhbYURq5R57KpzBBRZKPJi8eQg48h4j8SDdowifdIrEVdU+gbO6QNvRRt4ZBthUaZhUnjlYObNagV3keoeru3rU7rcuceqU1mJBxy+BWZYlNEBH+0eH4vRiB+OYybU2hnblYlTvkHinM4m54YnxSyaZYSF6R3jwgP7udKLGIX6r/lbNa9N6y5MFynjWDtrHd75ZvTYAPO/6RgF0k76mQla3FGq7dO+cH8sKn0Vo7nDllwAhqwLPkxrHwWmHJOo+AKJ4rab5OgrM7rVu8eWb2Pu0Dh4eDgXoOfvp7Y7QeqknRmvcTBEyq9m/HQQSCSz6LHq3z0yzsNySRfMS253wl2KyRDbcZPcfJKjZmSEOjcxyi+Y8dUOtsIEH6R2wNykdqrkYJ0RV92H0W58pkfQk7cKevsLK10Py8SdMGfXNXATY+pPbyJR/ET6n9nIfztNtZYRV9XniQu9IA2vOVgy4ir7GCLVmmd+zjkH0eAF9Po6K61pmCXHxU5rHMYd1ftc3owjwRSVRzLjKvqZEty6cRUD7jGqiOdu5HG6MdHjNcNYGqfDm5YRzLBBCCDl/2bk8a8gdbqcfwECu62Fg/HrggAAAABJRU5ErkJggg==",o="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAApCAYAAACoYAD2AAAC5ElEQVRYw+2YW4/TMBCF45S0S1luXZCABy5CgLQgwf//S4BYBLTdJLax0fFqmB07nnQfEGqkIydpVH85M+NLjPe++dcPc4Q8Qh4hj5D/AaQJx6H/4TMwB0PeBNwU7EGQAmAtsNfAzoZkgIa0ZgLMa4Aj6CxIAsjhjOCoL5z7Glg1JAOkaicgvQBXuncwJAWjksLtBTWZe04CnYRktUGdilALppZBOgHGZcBzL6OClABvMSVIzyBjazOgrvACf1ydC5mguqAVg6RhdkSWQFj2uxfaq/BrIZOLEWgZdALIDvcMcZLD8ZbLC9de4yR1sYMi4G20S4Q/PWeJYxTOZn5zJXANZHIxAd4JWhPIloTJZhzMQduM89WQ3MUVAE/RnhAXpTycqys3NZALOBbB7kFrgLesQl2h45Fcj8L1tTSohUwuxhy8H/Qg6K7gIs+3kkaigQCOcyEXCHN07wyQazhrmIulvKMQAwMcmLNqyCVyMAI+BuxSMeTk3OPikLY2J1uE+VHQk6ANrhds+tNARqBeaGc72cK550FP4WhXmFmcMGhTwAR1ifOe3EvPqIegFmF+C8gVy0OfAaWQPMR7gF1OQKqGoBjq90HPMP01BUjPOqGFksC4emE48tWQAH0YmvOgF3DST6xieJgHAWxPAHMuNhrImIdvoNOKNWIOcE+UXE0pYAnkX6uhWsgVXDxHdTfCmrEEmMB2zMFimLVOtiiajxiGWrbU52EeCdyOwPEQD8LqyPH9Ti2kgYMf4OhSKB7qYILbBv3CuVTJ11Y80oaseiMWOONc/Y7kJYe0xL2f0BaiFTxknHO5HaMGMublKwxFGzYdWsBF174H/QDknhTHmHHN39iWFnkZx8lPyM8WHfYELmlLKtgWNmFNzQcC1b47gJ4hL19i7o65dhH0Negbca8vONZoP7doIeOC9zXm8RjuL0Gf4d4OYaU5ljo3GYiqzrWQHfJxA6ALhDpVKv9qYeZA8eM3EhfPSCmpuD0AAAAASUVORK5CYII=";return g(b)&&g(b.iconUrl)?new L.Icon(b):new L.Icon.Default({iconUrl:i,shadowUrl:o,iconSize:[25,41],iconAnchor:[12,41],popupAnchor:[1,-34],shadowSize:[41,41]})},z=function(a){g(t[a])&&t.splice(a,1)},A=function(){t={}},B=function(a,b,c){if(a.closePopup(),g(c)&&g(c.overlays))for(var d in c.overlays)if((c.overlays[d]instanceof L.LayerGroup||c.overlays[d]instanceof L.FeatureGroup)&&c.overlays[d].hasLayer(a))return void c.overlays[d].removeLayer(a);if(g(t))for(var e in t)t[e].hasLayer(a)&&t[e].removeLayer(a);b.hasLayer(a)&&b.removeLayer(a)},C=function(a,b){var c=a._popup._container.offsetHeight,d=new L.Point(a._popup._containerLeft,-c-a._popup._containerBottom),e=b.layerPointToContainerPoint(d);null!==e&&a._popup._adjustPan()},D=function(a,b){e(a._popup._contentNode)(b)},E=function(a,c,d){var e=a._popup._contentNode.innerText||a._popup._contentNode.textContent;e.length<1&&b(function(){E(a,c,d)});var f=a._popup._contentNode.offsetWidth;return a._popup._updateLayout(),a._popup._updatePosition(),a._popup.options.autoPan&&C(a,d),f},F=function(b,c,e){var f=angular.isFunction(c.getMessageScope)?c.getMessageScope():a,h=g(c.compileMessage)?c.compileMessage:!0;if(h){if(!g(b._popup)||!g(b._popup._contentNode))return d.error(v+"Popup is invalid or does not have any content."),!1;D(b,f),E(b,c,e)}},G=function(b,c){var d=angular.isFunction(c.getMessageScope)?c.getMessageScope():a,f=angular.isFunction(c.getLabelScope)?c.getLabelScope():d,h=g(c.compileMessage)?c.compileMessage:!0;p.LabelPlugin.isLoaded()&&g(c.label)&&(g(c.label.options)&&c.label.options.noHide===!0&&b.showLabel(),h&&g(b.label)&&e(b.label._container)(f))},H=function(a,b,c,e,f,h,i){if(g(b)){if(!u.validateCoords(a))return d.warn("There are problems with lat-lng data, please verify your marker model"),void B(c,i,h);var j=a===b;if(g(a.iconAngle)&&b.iconAngle!==a.iconAngle&&c.setIconAngle(a.iconAngle),q(a.layer)||q(b.layer)&&(g(h.overlays[b.layer])&&h.overlays[b.layer].hasLayer(c)&&(h.overlays[b.layer].removeLayer(c),c.closePopup()),i.hasLayer(c)||i.addLayer(c)),(r(a.opacity)||r(parseFloat(a.opacity)))&&a.opacity!==b.opacity&&c.setOpacity(a.opacity),q(a.layer)&&b.layer!==a.layer){if(q(b.layer)&&g(h.overlays[b.layer])&&h.overlays[b.layer].hasLayer(c)&&h.overlays[b.layer].removeLayer(c),c.closePopup(),i.hasLayer(c)&&i.removeLayer(c),!g(h.overlays[a.layer]))return void d.error(v+"You must use a name of an existing layer");var k=h.overlays[a.layer];if(!(k instanceof L.LayerGroup||k instanceof L.FeatureGroup))return void d.error(v+'A marker can only be added to a layer of type "group" or "featureGroup"');k.addLayer(c),i.hasLayer(c)&&a.focus===!0&&c.openPopup()}if(a.draggable!==!0&&b.draggable===!0&&g(c.dragging)&&c.dragging.disable(),a.draggable===!0&&b.draggable!==!0&&(c.dragging?c.dragging.enable():L.Handler.MarkerDrag&&(c.dragging=new L.Handler.MarkerDrag(c),c.options.draggable=!0,c.dragging.enable())),s(a.icon)||s(b.icon)&&(c.setIcon(y()),c.closePopup(),c.unbindPopup(),q(a.message)&&c.bindPopup(a.message,a.popupOptions)),s(a.icon)&&s(b.icon)&&!angular.equals(a.icon,b.icon)){var l=!1;c.dragging&&(l=c.dragging.enabled()),c.setIcon(y(a.icon)),l&&c.dragging.enable(),c.closePopup(),c.unbindPopup(),q(a.message)&&(c.bindPopup(a.message,a.popupOptions),i.hasLayer(c)&&a.focus===!0&&c.openPopup())}!q(a.message)&&q(b.message)&&(c.closePopup(),c.unbindPopup()),p.LabelPlugin.isLoaded()&&(g(a.label)&&g(a.label.message)?"label"in b&&"message"in b.label&&!angular.equals(a.label.message,b.label.message)?c.updateLabelContent(a.label.message):!angular.isFunction(c.getLabel)||angular.isFunction(c.getLabel)&&!g(c.getLabel())?(c.bindLabel(a.label.message,a.label.options),G(c,a)):G(c,a):(!("label"in a)||"message"in a.label)&&angular.isFunction(c.unbindLabel)&&c.unbindLabel()),q(a.message)&&!q(b.message)&&c.bindPopup(a.message,a.popupOptions),q(a.message)&&q(b.message)&&a.message!==b.message&&c.setPopupContent(a.message);var m=!1;a.focus!==!0&&b.focus===!0&&(c.closePopup(),m=!0),(a.focus===!0&&(!g(b.focus)||b.focus===!1)||j&&a.focus===!0)&&(c.openPopup(),m=!0),b.zIndexOffset!==a.zIndexOffset&&c.setZIndexOffset(a.zIndexOffset);var n=c.getLatLng(),o=q(a.layer)&&p.MarkerClusterPlugin.is(h.overlays[a.layer]);o?m?(a.lat!==b.lat||a.lng!==b.lng)&&(h.overlays[a.layer].removeLayer(c),c.setLatLng([a.lat,a.lng]),h.overlays[a.layer].addLayer(c)):n.lat!==a.lat||n.lng!==a.lng?(h.overlays[a.layer].removeLayer(c),c.setLatLng([a.lat,a.lng]),h.overlays[a.layer].addLayer(c)):a.lat!==b.lat||a.lng!==b.lng?(h.overlays[a.layer].removeLayer(c),c.setLatLng([a.lat,a.lng]),h.overlays[a.layer].addLayer(c)):s(a.icon)&&s(b.icon)&&!angular.equals(a.icon,b.icon)&&(h.overlays[a.layer].removeLayer(c),h.overlays[a.layer].addLayer(c)):(n.lat!==a.lat||n.lng!==a.lng)&&c.setLatLng([a.lat,a.lng])}};return{resetMarkerGroup:z,resetMarkerGroups:A,deleteMarker:B,manageOpenPopup:F,manageOpenLabel:G,createMarker:function(a){if(!g(a)||!u.validateCoords(a))return void d.error(v+"The marker definition is not valid.");var b=u.getCoords(a);if(!g(b))return void d.error(v+"Unable to get coordinates from markerData.");var c={icon:y(a.icon),title:g(a.title)?a.title:"",draggable:g(a.draggable)?a.draggable:!1,clickable:g(a.clickable)?a.clickable:!0,riseOnHover:g(a.riseOnHover)?a.riseOnHover:!1,zIndexOffset:g(a.zIndexOffset)?a.zIndexOffset:0,iconAngle:g(a.iconAngle)?a.iconAngle:0};for(var e in a)a.hasOwnProperty(e)&&!c.hasOwnProperty(e)&&(c[e]=a[e]);var f=new L.marker(b,c);return q(a.message)||f.unbindPopup(),f},addMarkerToGroup:function(a,b,c,e){return q(b)?i.isLoaded()?(g(t[b])||(t[b]=new L.MarkerClusterGroup(c),e.addLayer(t[b])),void t[b].addLayer(a)):void d.error(v+"The MarkerCluster plugin is not loaded."):void d.error(v+"The marker group you have specified is invalid.")},listenMarkerEvents:function(a,b,c,d,e){a.on("popupopen",function(){o(c,function(){(g(a._popup)||g(a._popup._contentNode))&&(b.focus=!0,F(a,b,e))})}),a.on("popupclose",function(){o(c,function(){b.focus=!1})}),a.on("add",function(){o(c,function(){"label"in b&&G(a,b)})})},updateMarker:H,addMarkerWatcher:function(a,b,c,d,e,f){var i=p.getObjectArrayPath("markers."+b);f=h(f,!0);var j=c.$watch(i,function(f,h){return g(f)?void H(f,h,a,b,c,d,e):(B(a,e,d),void j())},f)},string:w,log:x}}]),angular.module("leaflet-directive").factory("leafletPathsHelpers",["$rootScope","$log","leafletHelpers",function(a,b,c){function d(a){return a.filter(function(a){return k(a)}).map(function(a){return e(a)})}function e(a){return i(a)?new L.LatLng(a[0],a[1]):new L.LatLng(a.lat,a.lng)}function f(a){return a.map(function(a){return d(a)})}function g(a,b){for(var c={},d=0;d<l.length;d++){var e=l[d];h(a[e])?c[e]=a[e]:h(b.path[e])&&(c[e]=b.path[e])}return c}var h=c.isDefined,i=c.isArray,j=c.isNumber,k=c.isValidPoint,l=["stroke","weight","color","opacity","fill","fillColor","fillOpacity","dashArray","lineCap","lineJoin","clickable","pointerEvents","className","smoothFactor","noClip"],m=function(a,b){for(var c={},d=0;d<l.length;d++){var e=l[d];h(b[e])&&(c[e]=b[e])}a.setStyle(b)},n=function(a){if(!i(a))return!1;for(var b=0;b<a.length;b++){var c=a[b];if(!k(c))return!1}return!0},o={polyline:{isValid:function(a){var b=a.latlngs;return n(b)},createPath:function(a){return new L.Polyline([],a)},setPath:function(a,b){a.setLatLngs(d(b.latlngs)),m(a,b)}},multiPolyline:{isValid:function(a){var b=a.latlngs;if(!i(b))return!1;for(var c in b){var d=b[c];if(!n(d))return!1}return!0},createPath:function(a){return new L.multiPolyline([[[0,0],[1,1]]],a)},setPath:function(a,b){a.setLatLngs(f(b.latlngs)),m(a,b)}},polygon:{isValid:function(a){var b=a.latlngs;return n(b)},createPath:function(a){return new L.Polygon([],a)},setPath:function(a,b){a.setLatLngs(d(b.latlngs)),m(a,b)}},multiPolygon:{isValid:function(a){var b=a.latlngs;if(!i(b))return!1;for(var c in b){var d=b[c];if(!n(d))return!1}return!0},createPath:function(a){return new L.MultiPolygon([[[0,0],[1,1],[0,1]]],a)},setPath:function(a,b){a.setLatLngs(f(b.latlngs)),m(a,b)}},rectangle:{isValid:function(a){var b=a.latlngs;if(!i(b)||2!==b.length)return!1;for(var c in b){var d=b[c];if(!k(d))return!1}return!0},createPath:function(a){return new L.Rectangle([[0,0],[1,1]],a)},setPath:function(a,b){a.setBounds(new L.LatLngBounds(d(b.latlngs))),m(a,b)}},circle:{isValid:function(a){var b=a.latlngs;return k(b)&&j(a.radius)},createPath:function(a){return new L.Circle([0,0],1,a)},setPath:function(a,b){a.setLatLng(e(b.latlngs)),h(b.radius)&&a.setRadius(b.radius),m(a,b)}},circleMarker:{isValid:function(a){var b=a.latlngs;return k(b)&&j(a.radius)},createPath:function(a){return new L.CircleMarker([0,0],a)},setPath:function(a,b){a.setLatLng(e(b.latlngs)),h(b.radius)&&a.setRadius(b.radius),m(a,b)}}},p=function(a){var b={};return a.latlngs&&(b.latlngs=a.latlngs),a.radius&&(b.radius=a.radius),b};return{setPathOptions:function(a,b,c){h(b)||(b="polyline"),o[b].setPath(a,c)},createPath:function(a,c,d){h(c.type)||(c.type="polyline");var e=g(c,d),f=p(c);return o[c.type].isValid(f)?o[c.type].createPath(e):void b.error("[AngularJS - Leaflet] Invalid data passed to the "+c.type+" path")}}}]),angular.module("leaflet-directive").service("leafletWatchHelpers",function(){var a=function(a,b,c,d,e){var f=a[b](c,function(a,b){e(a,b),d.doWatch||f()},d.isDeep);return f},b=function(b,c,d,e){return a(b,"$watch",c,d,e)},c=function(b,c,d,e){return a(b,"$watchCollection",c,d,e)};return{maybeWatch:b,maybeWatchCollection:c}}),angular.module("leaflet-directive").factory("nominatimService",["$q","$http","leafletHelpers","leafletMapDefaults",function(a,b,c,d){var e=c.isDefined;return{query:function(c,f){var g=d.getDefaults(f),h=g.nominatim.server,i=a.defer();return b.get(h,{params:{format:"json",limit:1,q:c}}).success(function(a){a.length>0&&e(a[0].boundingbox)?i.resolve(a[0]):i.reject("[Nominatim] Invalid address")}),i.promise}}}]),angular.module("leaflet-directive").directive("bounds",["$log","$timeout","$http","leafletHelpers","nominatimService","leafletBoundsHelpers",function(a,b,c,d,e,f){return{restrict:"A",scope:!1,replace:!1,require:["leaflet"],link:function(c,g,h,i){var j=d.isDefined,k=f.createLeafletBounds,l=i[0].getLeafletScope(),m=i[0],n=d.errorHeader+" [Bounds] ",o=function(a){return 0===a._southWest.lat&&0===a._southWest.lng&&0===a._northEast.lat&&0===a._northEast.lng};m.getMap().then(function(d){l.$on("boundsChanged",function(a){var c=a.currentScope,e=d.getBounds();if(!o(e)&&!c.settingBoundsFromScope){c.settingBoundsFromLeaflet=!0;var f={northEast:{lat:e._northEast.lat,lng:e._northEast.lng},southWest:{lat:e._southWest.lat,lng:e._southWest.lng},options:e.options};angular.equals(c.bounds,f)||(c.bounds=f),b(function(){c.settingBoundsFromLeaflet=!1})}});var f;l.$watch("bounds",function(g){if(!c.settingBoundsFromLeaflet){if(j(g.address)&&g.address!==f)return c.settingBoundsFromScope=!0,e.query(g.address,h.id).then(function(a){var b=a.boundingbox,c=[[b[0],b[2]],[b[1],b[3]]];d.fitBounds(c)},function(b){a.error(n+" "+b+".")}),f=g.address,void b(function(){c.settingBoundsFromScope=!1});var i=k(g);i&&!d.getBounds().equals(i)&&(c.settingBoundsFromScope=!0,d.fitBounds(i,g.options),b(function(){c.settingBoundsFromScope=!1}))}},!0)})}}}]);var centerDirectiveTypes=["center","lfCenter"],centerDirectives={};centerDirectiveTypes.forEach(function(a){centerDirectives[a]=["$log","$q","$location","$timeout","leafletMapDefaults","leafletHelpers","leafletBoundsHelpers","leafletMapEvents",function(b,c,d,e,f,g,h,i){var j,k=g.isDefined,l=g.isNumber,m=g.isSameCenterOnMap,n=g.safeApply,o=g.isValidCenter,p=h.isValidBounds,q=g.isUndefinedOrEmpty,r=g.errorHeader,s=function(a,b){return k(a)&&p(a)&&q(b)};return{restrict:"A",scope:!1,replace:!1,require:"leaflet",controller:function(){j=c.defer(),this.getCenter=function(){return j.promise}},link:function(c,g,p,q){var t=q.getLeafletScope(),u=t[a];q.getMap().then(function(c){var g=f.getDefaults(p.id);if(-1!==p[a].search("-"))return b.error(r+' The "center" variable can\'t use a "-" on its key name: "'+p[a]+'".'),void c.setView([g.center.lat,g.center.lng],g.center.zoom);if(s(t.bounds,u))c.fitBounds(h.createLeafletBounds(t.bounds),t.bounds.options),u=c.getCenter(),n(t,function(b){angular.extend(b[a],{lat:c.getCenter().lat,lng:c.getCenter().lng,zoom:c.getZoom(),autoDiscover:!1})}),n(t,function(a){var b=c.getBounds();a.bounds={northEast:{lat:b._northEast.lat,lng:b._northEast.lng},southWest:{lat:b._southWest.lat,lng:b._southWest.lng}}});else{if(!k(u))return b.error(r+' The "center" property is not defined in the main scope'),void c.setView([g.center.lat,g.center.lng],g.center.zoom);k(u.lat)&&k(u.lng)||k(u.autoDiscover)||angular.copy(g.center,u)}var q,v;if("yes"===p.urlHashCenter){var w=function(){var a,b=d.search();if(k(b.c)){var c=b.c.split(":");3===c.length&&(a={lat:parseFloat(c[0]),lng:parseFloat(c[1]),zoom:parseInt(c[2],10)})}return a};q=w(),t.$on("$locationChangeSuccess",function(b){var d=b.currentScope,e=w();k(e)&&!m(e,c)&&angular.extend(d[a],{lat:e.lat,lng:e.lng,zoom:e.zoom})})}t.$watch(a,function(a){return t.settingCenterFromLeaflet?void 0:(k(q)&&(angular.copy(q,a),q=void 0),o(a)||a.autoDiscover===!0?a.autoDiscover===!0?(l(a.zoom)||c.setView([g.center.lat,g.center.lng],g.center.zoom),void(l(a.zoom)&&a.zoom>g.center.zoom?c.locate({setView:!0,maxZoom:a.zoom}):k(g.maxZoom)?c.locate({setView:!0,maxZoom:g.maxZoom}):c.locate({setView:!0}))):void(v&&m(a,c)||(t.settingCenterFromScope=!0,c.setView([a.lat,a.lng],a.zoom),i.notifyCenterChangedToBounds(t,c),e(function(){t.settingCenterFromScope=!1}))):void b.warn(r+" invalid 'center'"))},!0),c.whenReady(function(){v=!0}),c.on("moveend",function(){j.resolve(),i.notifyCenterUrlHashChanged(t,c,p,d.search()),m(u,c)||t.settingCenterFromScope||(t.settingCenterFromLeaflet=!0,n(t,function(b){t.settingCenterFromScope||angular.extend(b[a],{lat:c.getCenter().lat,lng:c.getCenter().lng,zoom:c.getZoom(),autoDiscover:!1}),i.notifyCenterChangedToBounds(t,c),e(function(){t.settingCenterFromLeaflet=!1})}))}),u.autoDiscover===!0&&c.on("locationerror",function(){b.warn(r+" The Geolocation API is unauthorized on this page."),o(u)?(c.setView([u.lat,u.lng],u.zoom),i.notifyCenterChangedToBounds(t,c)):(c.setView([g.center.lat,g.center.lng],g.center.zoom),i.notifyCenterChangedToBounds(t,c))})})}}}]}),centerDirectiveTypes.forEach(function(a){angular.module("leaflet-directive").directive(a,centerDirectives[a])}),angular.module("leaflet-directive").directive("controls",["$log","leafletHelpers","leafletControlHelpers",function(a,b,c){return{restrict:"A",scope:!1,replace:!1,require:"?^leaflet",link:function(d,e,f,g){if(g){var h=c.createControl,i=c.isValidControlType,j=g.getLeafletScope(),k=b.isDefined,l=b.isArray,m={},n=b.errorHeader+" [Controls] ";g.getMap().then(function(b){j.$watchCollection("controls",function(c){for(var d in m)k(c[d])||(b.hasControl(m[d])&&b.removeControl(m[d]),delete m[d]);for(var e in c){var f,g=k(c[e].type)?c[e].type:e;if(!i(g))return void a.error(n+" Invalid control type: "+g+".");if("custom"!==g)f=h(g,c[e]),b.addControl(f),m[e]=f;else{var j=c[e];if(l(j))for(var o in j){var p=j[o];b.addControl(p),m[e]=k(m[e])?m[e].concat([p]):[p]}else b.addControl(j),m[e]=j}}})})}}}}]),angular.module("leaflet-directive").directive("decorations",["$log","leafletHelpers",function(a,b){return{restrict:"A",scope:!1,replace:!1,require:"leaflet",link:function(c,d,e,f){function g(b){return k(b)&&k(b.coordinates)&&(j.isLoaded()||a.error("[AngularJS - Leaflet] The PolylineDecorator Plugin is not loaded.")),L.polylineDecorator(b.coordinates)}function h(a,b){return k(a)&&k(b)&&k(b.coordinates)&&k(b.patterns)?(a.setPaths(b.coordinates),a.setPatterns(b.patterns),a):void 0}var i=f.getLeafletScope(),j=b.PolylineDecoratorPlugin,k=b.isDefined,l={};f.getMap().then(function(a){i.$watch("decorations",function(b){for(var c in l)k(b[c])&&angular.equals(b[c],l)||(a.removeLayer(l[c]),delete l[c]);for(var d in b){var e=b[d],f=g(e);k(f)&&(l[d]=f,a.addLayer(f),h(f,e))}},!0)})}}}]),angular.module("leaflet-directive").directive("eventBroadcast",["$log","$rootScope","leafletHelpers","leafletMapEvents","leafletIterators",function(a,b,c,d,e){return{restrict:"A",scope:!1,replace:!1,require:"leaflet",link:function(b,f,g,h){var i=c.isObject,j=c.isDefined,k=h.getLeafletScope(),l=k.eventBroadcast,m=d.getAvailableMapEvents(),n=d.addEvents;h.getMap().then(function(b){var c=[],d="broadcast";j(l.map)?i(l.map)?("emit"!==l.map.logic&&"broadcast"!==l.map.logic?a.warn("[AngularJS - Leaflet] Available event propagation logic are: 'emit' or 'broadcast'."):d=l.map.logic,i(l.map.enable)&&l.map.enable.length>=0?e.each(l.map.enable,function(a){-1===c.indexOf(a)&&-1!==m.indexOf(a)&&c.push(a)}):a.warn("[AngularJS - Leaflet] event-broadcast.map.enable must be an object check your model.")):a.warn("[AngularJS - Leaflet] event-broadcast.map must be an object check your model."):c=m,n(b,c,"eventName",k,d)})}}}]),angular.module("leaflet-directive").directive("geojson",["$log","$rootScope","leafletData","leafletHelpers","leafletWatchHelpers","leafletDirectiveControlsHelpers","leafletIterators","leafletGeoJsonEvents",function(a,b,c,d,e,f,g,h){var i=e.maybeWatch,j=d.watchOptions,k=f.extend,l=d,m=g;return{restrict:"A",scope:!1,replace:!1,require:"leaflet",link:function(a,b,e,f){var g=d.isDefined,n=f.getLeafletScope(),o={},p=!1;f.getMap().then(function(a){var b=n.geojsonWatchOptions||j,f=function(a,b){var c;return c=angular.isFunction(a.onEachFeature)?a.onEachFeature:function(c,f){d.LabelPlugin.isLoaded()&&g(c.properties.description)&&f.bindLabel(c.properties.description),h.bindEvents(e.id,f,null,c,n,b,{resetStyleOnMouseout:a.resetStyleOnMouseout,mapId:e.id})}},q=l.isDefined(e.geojsonNested)&&l.isTruthy(e.geojsonNested),r=function(){if(o){var b=function(b){g(b)&&a.hasLayer(b)&&a.removeLayer(b)};return q?void m.each(o,function(a){b(a)}):void b(o)}},s=function(b,d){var h=angular.copy(b);if(g(h)&&g(h.data)){var i=f(h,d);g(h.options)||(h.options={style:h.style,filter:h.filter,onEachFeature:i,pointToLayer:h.pointToLayer});var j=L.geoJson(h.data,h.options);d&&l.isString(d)?o[d]=j:o=j,j.addTo(a),p||(p=!0,c.setGeoJSON(o,e.id))}},t=function(a){if(r(),q){if(!a||!Object.keys(a).length)return;return void m.each(a,function(a,b){s(a,b)})}s(a)};k(e.id,"geojson",t,r),i(n,"geojson",b,function(a){t(a)})})}}}]),angular.module("leaflet-directive").directive("layercontrol",["$filter","$log","leafletData","leafletHelpers",function(a,b,c,d){return{restrict:"E",scope:{icons:"=?",autoHideOpacity:"=?",showGroups:"=?",title:"@",baseTitle:"@",overlaysTitle:"@"},replace:!0,transclude:!1,require:"^leaflet",controller:["$scope","$element","$sce",function(a,e,f){b.debug("[Angular Directive - Layers] layers",a,e);var g=d.safeApply,h=d.isDefined;angular.extend(a,{baselayer:"",oldGroup:"",layerProperties:{},groupProperties:{},rangeIsSupported:d.rangeIsSupported(),changeBaseLayer:function(b,e){d.safeApply(a,function(d){d.baselayer=b,c.getMap().then(function(e){c.getLayers().then(function(c){if(!e.hasLayer(c.baselayers[b])){for(var f in d.layers.baselayers)d.layers.baselayers[f].icon=d.icons.unradio,e.hasLayer(c.baselayers[f])&&e.removeLayer(c.baselayers[f]);e.addLayer(c.baselayers[b]),d.layers.baselayers[b].icon=a.icons.radio}})})}),e.preventDefault()},moveLayer:function(b,c,d){var e=Object.keys(a.layers.baselayers).length;if(c>=1+e&&c<=a.overlaysArray.length+e){var f;for(var h in a.layers.overlays)if(a.layers.overlays[h].index===c){f=a.layers.overlays[h];break}f&&g(a,function(){f.index=b.index,b.index=c})}d.stopPropagation(),d.preventDefault()},initIndex:function(b,c){var d=Object.keys(a.layers.baselayers).length;b.index=h(b.index)?b.index:c+d+1},initGroup:function(b){a.groupProperties[b]=a.groupProperties[b]?a.groupProperties[b]:{}},toggleOpacity:function(b,c){if(c.visible){if(a.autoHideOpacity&&!a.layerProperties[c.name].opacityControl)for(var d in a.layerProperties)a.layerProperties[d].opacityControl=!1;a.layerProperties[c.name].opacityControl=!a.layerProperties[c.name].opacityControl}b.stopPropagation(),b.preventDefault()},toggleLegend:function(b){a.layerProperties[b.name].showLegend=!a.layerProperties[b.name].showLegend},showLegend:function(b){return b.legend&&a.layerProperties[b.name].showLegend},unsafeHTML:function(a){return f.trustAsHtml(a)},getOpacityIcon:function(b){return b.visible&&a.layerProperties[b.name].opacityControl?a.icons.close:a.icons.open},getGroupIcon:function(b){return b.visible?a.icons.check:a.icons.uncheck},changeOpacity:function(b){var d=a.layerProperties[b.name].opacity;c.getMap().then(function(e){c.getLayers().then(function(c){var f;for(var g in a.layers.overlays)if(a.layers.overlays[g]===b){f=c.overlays[g];break}e.hasLayer(f)&&(f.setOpacity&&f.setOpacity(d/100),f.getLayers&&f.eachLayer&&f.eachLayer(function(a){a.setOpacity&&a.setOpacity(d/100)}))})})},changeGroupVisibility:function(b){if(h(a.groupProperties[b])){var c=a.groupProperties[b].visible;for(var d in a.layers.overlays){var e=a.layers.overlays[d];e.group===b&&(e.visible=c)}}}});var i=e.get(0);L.Browser.touch?L.DomEvent.on(i,"click",L.DomEvent.stopPropagation):(L.DomEvent.disableClickPropagation(i),L.DomEvent.on(i,"mousewheel",L.DomEvent.stopPropagation))}],template:'<div class="angular-leaflet-control-layers" ng-show="overlaysArray.length"><h4 ng-if="title">{{ title }}</h4><div class="lf-baselayers"><h5 class="lf-title" ng-if="baseTitle">{{ baseTitle }}</h5><div class="lf-row" ng-repeat="(key, layer) in baselayersArray"><label class="lf-icon-bl" ng-click="changeBaseLayer(key, $event)"><input class="leaflet-control-layers-selector" type="radio" name="lf-radio" ng-show="false" ng-checked="baselayer === key" ng-value="key" /> <i class="lf-icon lf-icon-radio" ng-class="layer.icon"></i><div class="lf-text">{{layer.name}}</div></label></div></div><div class="lf-overlays"><h5 class="lf-title" ng-if="overlaysTitle">{{ overlaysTitle }}</h5><div class="lf-container"><div class="lf-row" ng-repeat="layer in (o = (overlaysArray | orderBy:\'index\':order))" ng-init="initIndex(layer, $index)"><label class="lf-icon-ol-group" ng-if="showGroups && layer.group && layer.group != o[$index-1].group"><input class="lf-control-layers-selector" type="checkbox" ng-show="false" ng-change="changeGroupVisibility(layer.group)" ng-model="groupProperties[layer.group].visible"/> <i class="lf-icon lf-icon-check" ng-class="getGroupIcon(groupProperties[layer.group])"></i><div class="lf-text">{{ layer.group }}</div></label><label class="lf-icon-ol"><input class="lf-control-layers-selector" type="checkbox" ng-show="false" ng-model="layer.visible"/> <i class="lf-icon lf-icon-check" ng-class="layer.icon"></i><div class="lf-text">{{layer.name}}</div></label><div class="lf-icons"><i class="lf-icon lf-up" ng-class="icons.up" ng-click="moveLayer(layer, layer.index - orderNumber, $event)"></i> <i class="lf-icon lf-down" ng-class="icons.down" ng-click="moveLayer(layer, layer.index + orderNumber, $event)"></i> <i class="lf-icon lf-toggle-legend" ng-class="icons.toggleLegend" ng-if="layer.legend" ng-click="toggleLegend(layer)"></i> <i class="lf-icon lf-open" ng-class="getOpacityIcon(layer)" ng-click="toggleOpacity($event, layer)"></i></div><div class="lf-legend" ng-if="showLegend(layer)" ng-bind-html="unsafeHTML(layer.legend)"></div><div class="lf-opacity clearfix" ng-if="layer.visible && layerProperties[layer.name].opacityControl"><label ng-if="rangeIsSupported" class="pull-left" style="width: 50%">0</label><label ng-if="rangeIsSupported" class="pull-left text-right" style="width: 50%">100</label><input ng-if="rangeIsSupported" class="clearfix" type="range" min="0" max="100" class="lf-opacity-control" ng-model="layerProperties[layer.name].opacity" ng-change="changeOpacity(layer)"/><h6 ng-if="!rangeIsSupported">Range is not supported in this browser</h6></div></div></div></div></div>',link:function(a,b,e,f){var g=d.isDefined,h=f.getLeafletScope(),i=h.layers;a.$watch("icons",function(){var b={uncheck:"fa fa-square-o",check:"fa fa-check-square-o",radio:"fa fa-dot-circle-o",unradio:"fa fa-circle-o",up:"fa fa-angle-up",down:"fa fa-angle-down",open:"fa fa-angle-double-down",close:"fa fa-angle-double-up",toggleLegend:"fa fa-pencil-square-o"};g(a.icons)?(angular.extend(b,a.icons),angular.extend(a.icons,b)):a.icons=b}),e.order=!g(e.order)||"normal"!==e.order&&"reverse"!==e.order?"normal":e.order,a.order="normal"===e.order,a.orderNumber="normal"===e.order?-1:1,a.layers=i,f.getMap().then(function(b){h.$watch("layers.baselayers",function(d){var e={};c.getLayers().then(function(c){var f;for(f in d){var g=d[f];g.icon=a.icons[b.hasLayer(c.baselayers[f])?"radio":"unradio"],e[f]=g}a.baselayersArray=e})}),h.$watch("layers.overlays",function(b){var d=[],e={};c.getLayers().then(function(c){var f;for(f in b){var h=b[f];h.icon=a.icons[h.visible?"check":"uncheck"],d.push(h),g(a.layerProperties[h.name])||(a.layerProperties[h.name]={opacity:g(h.layerOptions.opacity)?100*h.layerOptions.opacity:100,opacityControl:!1,showLegend:!0}),g(h.group)&&(g(a.groupProperties[h.group])||(a.groupProperties[h.group]={visible:!1}),e[h.group]=g(e[h.group])?e[h.group]:{count:0,visibles:0},e[h.group].count++,h.visible&&e[h.group].visibles++),g(h.index)&&c.overlays[f].setZIndex&&c.overlays[f].setZIndex(b[f].index)}for(f in e)a.groupProperties[f].visible=e[f].visibles===e[f].count;a.overlaysArray=d})},!0)})}}}]),angular.module("leaflet-directive").directive("layers",["$log","$q","leafletData","leafletHelpers","leafletLayerHelpers","leafletControlHelpers",function(a,b,c,d,e,f){return{restrict:"A",scope:!1,replace:!1,require:"leaflet",controller:["$scope",function(a){a._leafletLayers=b.defer(),this.getLayers=function(){return a._leafletLayers.promise}}],link:function(a,b,g,h){var i=d.isDefined,j={},k=h.getLeafletScope(),l=k.layers,m=e.createLayer,n=e.safeAddLayer,o=e.safeRemoveLayer,p=f.updateLayersControl,q=!1;h.getMap().then(function(b){a._leafletLayers.resolve(j),c.setLayers(j,g.id),j.baselayers={},j.overlays={};var d=g.id,e=!1;for(var f in l.baselayers){var h=m(l.baselayers[f]);i(h)?(j.baselayers[f]=h,l.baselayers[f].top===!0&&(n(b,j.baselayers[f]),e=!0)):delete l.baselayers[f]}!e&&Object.keys(j.baselayers).length>0&&n(b,j.baselayers[Object.keys(l.baselayers)[0]]);for(f in l.overlays){var r=m(l.overlays[f]);i(r)?(j.overlays[f]=r,l.overlays[f].visible===!0&&n(b,j.overlays[f])):delete l.overlays[f]}k.$watch("layers.baselayers",function(a,c){if(angular.equals(a,c))return q=p(b,d,q,a,l.overlays,j),!0;for(var e in j.baselayers)(!i(a[e])||a[e].doRefresh)&&(b.hasLayer(j.baselayers[e])&&b.removeLayer(j.baselayers[e]),delete j.baselayers[e],a[e]&&a[e].doRefresh&&(a[e].doRefresh=!1));for(var f in a)if(i(j.baselayers[f]))a[f].top!==!0||b.hasLayer(j.baselayers[f])?a[f].top===!1&&b.hasLayer(j.baselayers[f])&&b.removeLayer(j.baselayers[f]):n(b,j.baselayers[f]);else{var g=m(a[f]);i(g)&&(j.baselayers[f]=g,a[f].top===!0&&n(b,j.baselayers[f]))}var h=!1;for(var k in j.baselayers)if(b.hasLayer(j.baselayers[k])){h=!0;break}!h&&Object.keys(j.baselayers).length>0&&n(b,j.baselayers[Object.keys(j.baselayers)[0]]),q=p(b,d,q,a,l.overlays,j)},!0),k.$watch("layers.overlays",function(a,c){if(angular.equals(a,c))return q=p(b,d,q,l.baselayers,a,j),!0;for(var e in j.overlays)if(!i(a[e])||a[e].doRefresh){if(b.hasLayer(j.overlays[e])){var f=i(a[e])?a[e].layerOptions:null;o(b,j.overlays[e],f)}delete j.overlays[e],a[e]&&a[e].doRefresh&&(a[e].doRefresh=!1)}for(var g in a){if(i(j.overlays[g]))a[g].visible&&!b.hasLayer(j.overlays[g])?n(b,j.overlays[g]):a[g].visible===!1&&b.hasLayer(j.overlays[g])&&o(b,j.overlays[g],a[g].layerOptions);else{ | |
| var h=m(a[g]);if(!i(h))continue;j.overlays[g]=h,a[g].visible===!0&&n(b,j.overlays[g])}a[g].visible&&b._loaded&&a[g].data&&"heatmap"===a[g].type&&(j.overlays[g].setData(a[g].data),j.overlays[g].update())}q=p(b,d,q,l.baselayers,a,j)},!0)})}}}]),angular.module("leaflet-directive").directive("legend",["$log","$http","leafletHelpers","leafletLegendHelpers",function(a,b,c,d){return{restrict:"A",scope:!1,replace:!1,require:"leaflet",link:function(e,f,g,h){var i,j,k,l,m=c.isArray,n=c.isDefined,o=c.isFunction,p=h.getLeafletScope(),q=p.legend;p.$watch("legend",function(a){n(a)&&(i=a.legendClass?a.legendClass:"legend",j=a.position||"bottomright",l=a.type||"arcgis")},!0),h.getMap().then(function(c){p.$watch("legend",function(b){return n(b)?n(b.url)||"arcgis"!==l||m(b.colors)&&m(b.labels)&&b.colors.length===b.labels.length?n(b.url)?void a.info("[AngularJS - Leaflet] loading legend service."):(n(k)&&(k.removeFrom(c),k=null),k=L.control({position:j}),"arcgis"===l&&(k.onAdd=d.getOnAddArrayLegend(b,i)),void k.addTo(c)):void a.warn("[AngularJS - Leaflet] legend.colors and legend.labels must be set."):void(n(k)&&(k.removeFrom(c),k=null))}),p.$watch("legend.url",function(e){n(e)&&b.get(e).success(function(a){n(k)?d.updateLegend(k.getContainer(),a,l,e):(k=L.control({position:j}),k.onAdd=d.getOnAddLegend(a,i,l,e),k.addTo(c)),n(q.loadedData)&&o(q.loadedData)&&q.loadedData()}).error(function(){a.warn("[AngularJS - Leaflet] legend.url not loaded.")})})})}}}]),angular.module("leaflet-directive").directive("markers",["$log","$rootScope","$q","leafletData","leafletHelpers","leafletMapDefaults","leafletMarkersHelpers","leafletMarkerEvents","leafletIterators","leafletWatchHelpers","leafletDirectiveControlsHelpers",function(a,b,c,d,e,f,g,h,i,j,k){var l=e.isDefined,m=e.errorHeader,n=e,o=e.isString,p=g.addMarkerWatcher,q=g.updateMarker,r=g.listenMarkerEvents,s=g.addMarkerToGroup,t=g.createMarker,u=g.deleteMarker,v=i,w=e.watchOptions,x=j.maybeWatch,y=k.extend,z=function(a,b,c){if(Object.keys(a).length){if(c&&o(c)){if(!a[c]||!Object.keys(a[c]).length)return;return a[c][b]}return a[b]}},A=function(a,b,c,d){return d&&o(d)?(l(b[d])||(b[d]={}),b[d][c]=a):b[c]=a,a},B=function(b,c,d,e,f,g){if(!o(b))return a.error(m+" A layername must be a string"),!1;if(!l(c))return a.error(m+" You must add layers to the directive if the markers are going to use this functionality."),!1;if(!l(c.overlays)||!l(c.overlays[b]))return a.error(m+' A marker can only be added to a layer of type "group"'),!1;var h=c.overlays[b];return h instanceof L.LayerGroup||h instanceof L.FeatureGroup?(h.addLayer(e),!f&&g.hasLayer(e)&&d.focus===!0&&e.openPopup(),!0):(a.error(m+' Adding a marker to an overlay needs a overlay of the type "group" or "featureGroup"'),!1)},C=function(b,c,d,e,f,g,i,j,k,o){for(var u in c)if(!o[u])if(-1===u.search("-")){var v=n.copy(c[u]),w=n.getObjectDotPath(k?[k,u]:[u]),x=z(g,u,k);if(l(x)){var y=l(y)?d[u]:void 0;q(v,y,x,w,i,f,e)}else{var C=t(v),D=(v?v.layer:void 0)||k;if(!l(C)){a.error(m+" Received invalid data on the marker "+u+".");continue}if(A(C,g,u,k),l(v.message)&&C.bindPopup(v.message,v.popupOptions),l(v.group)){var E=l(v.groupOption)?v.groupOption:null;s(C,v.group,E,e)}if(n.LabelPlugin.isLoaded()&&l(v.label)&&l(v.label.message)&&C.bindLabel(v.label.message,v.label.options),l(v)&&(l(v.layer)||l(k))){var F=B(D,f,v,C,j.individual.doWatch,e);if(!F)continue}else l(v.group)||(e.addLayer(C),j.individual.doWatch||v.focus!==!0||C.openPopup());j.individual.doWatch&&p(C,w,i,f,e,j.individual.isDeep),r(C,v,i,j.individual.doWatch,e),h.bindEvents(b,C,w,v,i,D)}}else a.error('The marker can\'t use a "-" on his key name: "'+u+'".')},D=function(b,c,d,e,f){var g,h,i=!1,j=!1,k=l(c);for(var o in d)i||(a.debug(m+"[markers] destroy: "),i=!0),k&&(h=b[o],g=c[o],j=angular.equals(h,g)&&e),l(b)&&Object.keys(b).length&&l(b[o])&&Object.keys(b[o]).length&&!j||f&&n.isFunction(f)&&f(h,g,o)},E=function(b,c,d,e,f){D(b,c,d,!1,function(b,c,g){a.debug(m+"[marker] is deleting marker: "+g),u(d[g],e,f),delete d[g]})},F=function(b,c,d){var e={};return D(b,c,d,!0,function(b,c,d){a.debug(m+"[marker] is already rendered, marker: "+d),e[d]=b}),e};return{restrict:"A",scope:!1,replace:!1,require:["leaflet","?layers"],link:function(a,b,e,f){var g=f[0],h=g.getLeafletScope();g.getMap().then(function(a){var b,g={};b=l(f[1])?f[1].getLayers:function(){var a=c.defer();return a.resolve(),a.promise};var i=h.markersWatchOptions||w;l(e.watchMarkers)&&(i.doWatch=i.individual.doWatch=!l(e.watchMarkers)||n.isTruthy(e.watchMarkers));var j=l(e.markersNested)&&n.isTruthy(e.markersNested);b().then(function(b){var c=function(c,d){return j?void v.each(c,function(c,e){var f=l(f)?d[e]:void 0;E(c,f,g[e],a,b)}):void E(c,d,g,a,b)},f=function(d,f){c(d,f);var k=null;return j?void v.each(d,function(c,j){var m=l(m)?f[j]:void 0;k=F(d[j],m,g[j]),C(e.id,c,f,a,b,g,h,i,j,k)}):(k=F(d,f,g),void C(e.id,d,f,a,b,g,h,i,void 0,k))};y(e.id,"markers",f,c),d.setMarkers(g,e.id),x(h,"markers",i,function(a,b){f(a,b)})})})}}}]),angular.module("leaflet-directive").directive("maxbounds",["$log","leafletMapDefaults","leafletBoundsHelpers","leafletHelpers",function(a,b,c,d){return{restrict:"A",scope:!1,replace:!1,require:"leaflet",link:function(a,b,e,f){var g=f.getLeafletScope(),h=c.isValidBounds,i=d.isNumber;f.getMap().then(function(a){g.$watch("maxbounds",function(b){if(!h(b))return void a.setMaxBounds();var d=c.createLeafletBounds(b);i(b.pad)&&(d=d.pad(b.pad)),a.setMaxBounds(d),e.center||e.lfCenter||a.fitBounds(d)})})}}}]),angular.module("leaflet-directive").directive("paths",["$log","$q","leafletData","leafletMapDefaults","leafletHelpers","leafletPathsHelpers","leafletPathEvents",function(a,b,c,d,e,f,g){return{restrict:"A",scope:!1,replace:!1,require:["leaflet","?layers"],link:function(h,i,j,k){var l=k[0],m=e.isDefined,n=e.isString,o=l.getLeafletScope(),p=o.paths,q=f.createPath,r=g.bindPathEvents,s=f.setPathOptions;l.getMap().then(function(f){var g,h=d.getDefaults(j.id);g=m(k[1])?k[1].getLayers:function(){var a=b.defer();return a.resolve(),a.promise},m(p)&&g().then(function(b){var d={};c.setPaths(d,j.id);var g=!m(j.watchPaths)||"true"===j.watchPaths,i=function(a,c){var d=o.$watch('paths["'+c+'"]',function(c,e){if(!m(c)){if(m(e.layer))for(var g in b.overlays){var h=b.overlays[g];h.removeLayer(a)}return f.removeLayer(a),void d()}s(a,c.type,c)},!0)};o.$watchCollection("paths",function(c){for(var k in d)m(c[k])||(f.removeLayer(d[k]),delete d[k]);for(var l in c)if(0!==l.search("\\$"))if(-1===l.search("-")){if(!m(d[l])){var p=c[l],t=q(l,c[l],h);if(m(t)&&m(p.message)&&t.bindPopup(p.message,p.popupOptions),e.LabelPlugin.isLoaded()&&m(p.label)&&m(p.label.message)&&t.bindLabel(p.label.message,p.label.options),m(p)&&m(p.layer)){if(!n(p.layer)){a.error("[AngularJS - Leaflet] A layername must be a string");continue}if(!m(b)){a.error("[AngularJS - Leaflet] You must add layers to the directive if the markers are going to use this functionality.");continue}if(!m(b.overlays)||!m(b.overlays[p.layer])){a.error('[AngularJS - Leaflet] A path can only be added to a layer of type "group"');continue}var u=b.overlays[p.layer];if(!(u instanceof L.LayerGroup||u instanceof L.FeatureGroup)){a.error('[AngularJS - Leaflet] Adding a path to an overlay needs a overlay of the type "group" or "featureGroup"');continue}d[l]=t,u.addLayer(t),g?i(t,l):s(t,p.type,p)}else m(t)&&(d[l]=t,f.addLayer(t),g?i(t,l):s(t,p.type,p));r(j.id,t,l,p,o)}}else a.error('[AngularJS - Leaflet] The path name "'+l+'" is not valid. It must not include "-" and a number.')})})})}}}]),angular.module("leaflet-directive").directive("tiles",["$log","leafletData","leafletMapDefaults","leafletHelpers",function(a,b,c,d){return{restrict:"A",scope:!1,replace:!1,require:"leaflet",link:function(e,f,g,h){var i=d.isDefined,j=h.getLeafletScope(),k=j.tiles;return i(k)&&i(k.url)?void h.getMap().then(function(a){var d,e=c.getDefaults(g.id);j.$watch("tiles",function(c,f){var h=e.tileLayerOptions,j=e.tileLayer;return!i(c.url)&&i(d)?void a.removeLayer(d):i(d)?!i(c.url)||!i(c.options)||c.type===f.type&&angular.equals(c.options,h)?void(i(c.url)&&d.setUrl(c.url)):(a.removeLayer(d),h=e.tileLayerOptions,angular.copy(c.options,h),j=c.url,d="wms"===c.type?L.tileLayer.wms(j,h):L.tileLayer(j,h),d.addTo(a),void b.setTiles(d,g.id)):(i(c.options)&&angular.copy(c.options,h),i(c.url)&&(j=c.url),d="wms"===c.type?L.tileLayer.wms(j,h):L.tileLayer(j,h),d.addTo(a),void b.setTiles(d,g.id))},!0)}):void a.warn("[AngularJS - Leaflet] The 'tiles' definition doesn't have the 'url' property.")}}}]),["markers","geojson"].forEach(function(a){angular.module("leaflet-directive").directive(a+"WatchOptions",["$log","$rootScope","$q","leafletData","leafletHelpers",function(b,c,d,e,f){var g=f.isDefined,h=f.errorHeader,i=f.isObject,j=f.watchOptions;return{restrict:"A",scope:!1,replace:!1,require:["leaflet"],link:function(c,d,e,f){var k=f[0],l=k.getLeafletScope();k.getMap().then(function(){g(c[a+"WatchOptions"])&&(i(c[a+"WatchOptions"])?angular.extend(j,c[a+"WatchOptions"]):b.error(h+"["+a+"WatchOptions] is not an object"),l[a+"WatchOptions"]=j)})}}}])}),angular.module("leaflet-directive").factory("LeafletEventsHelpersFactory",["$rootScope","$q","$log","leafletHelpers",function(a,b,c,d){var e=d.safeApply,f=d.isDefined,g=d.isObject,h=d.isArray,i=d.errorHeader,j=function(a,b){this.rootBroadcastName=a,c.debug("LeafletEventsHelpersFactory: lObjectType: "+b+"rootBroadcastName: "+a),this.lObjectType=b};return j.prototype.getAvailableEvents=function(){return[]},j.prototype.genDispatchEvent=function(a,b,d,e,f,g,h,i,j){var k=this;return a=a||"",a&&(a="."+a),function(l){var m=k.rootBroadcastName+a+"."+b;c.debug(m),k.fire(e,m,d,l,l.target||f,h,g,i,j)}},j.prototype.fire=function(b,c,d,g,h,i,j,k){e(b,function(){var e={leafletEvent:g,leafletObject:h,modelName:j,model:i};f(k)&&angular.extend(e,{layerName:k}),"emit"===d?b.$emit(c,e):a.$broadcast(c,e)})},j.prototype.bindEvents=function(a,b,d,e,j,k,l){var m=[],n="emit",o=this;if(f(j.eventBroadcast))if(g(j.eventBroadcast))if(f(j.eventBroadcast[o.lObjectType]))if(g(j.eventBroadcast[o.lObjectType])){f(j.eventBroadcast[this.lObjectType].logic)&&"emit"!==j.eventBroadcast[o.lObjectType].logic&&"broadcast"!==j.eventBroadcast[o.lObjectType].logic&&c.warn(i+"Available event propagation logic are: 'emit' or 'broadcast'.");var p=!1,q=!1;f(j.eventBroadcast[o.lObjectType].enable)&&h(j.eventBroadcast[o.lObjectType].enable)&&(p=!0),f(j.eventBroadcast[o.lObjectType].disable)&&h(j.eventBroadcast[o.lObjectType].disable)&&(q=!0),p&&q?c.warn(i+"can not enable and disable events at the same time"):p||q?p?j.eventBroadcast[this.lObjectType].enable.forEach(function(a){-1!==m.indexOf(a)?c.warn(i+"This event "+a+" is already enabled"):-1===o.getAvailableEvents().indexOf(a)?c.warn(i+"This event "+a+" does not exist"):m.push(a)}):(m=this.getAvailableEvents(),j.eventBroadcast[o.lObjectType].disable.forEach(function(a){var b=m.indexOf(a);-1===b?c.warn(i+"This event "+a+" does not exist or has been already disabled"):m.splice(b,1)})):c.warn(i+"must enable or disable events")}else c.warn(i+"event-broadcast."+[o.lObjectType]+" must be an object check your model.");else m=this.getAvailableEvents();else c.error(i+"event-broadcast must be an object check your model.");else m=this.getAvailableEvents();return m.forEach(function(c){b.on(c,o.genDispatchEvent(a,c,n,j,b,d,e,k,l))}),n},j}]).service("leafletEventsHelpers",["LeafletEventsHelpersFactory",function(a){return new a}]),angular.module("leaflet-directive").factory("leafletGeoJsonEvents",["$rootScope","$q","$log","leafletHelpers","LeafletEventsHelpersFactory","leafletData",function(a,b,c,d,e,f){var g=d.safeApply,h=e,i=function(){h.call(this,"leafletDirectiveGeoJson","geojson")};return i.prototype=new h,i.prototype.genDispatchEvent=function(b,c,d,e,i,j,k,l,m){var n=h.prototype.genDispatchEvent.call(this,b,c,d,e,i,j,k,l),o=this;return function(b){"mouseout"===c&&(m.resetStyleOnMouseout&&f.getGeoJSON(m.mapId).then(function(a){var c=l?a[l]:a;c.resetStyle(b.target)}),g(e,function(){a.$broadcast(o.rootBroadcastName+".mouseout",b)})),n(b)}},i.prototype.getAvailableEvents=function(){return["click","dblclick","mouseover","mouseout"]},new i}]),angular.module("leaflet-directive").factory("leafletLabelEvents",["$rootScope","$q","$log","leafletHelpers","LeafletEventsHelpersFactory",function(a,b,c,d,e){var f=d,g=e,h=function(){g.call(this,"leafletDirectiveLabel","markers")};return h.prototype=new g,h.prototype.genDispatchEvent=function(a,b,c,d,e,f,h,i){var j=f.replace("markers.","");return g.prototype.genDispatchEvent.call(this,a,b,c,d,e,j,h,i)},h.prototype.getAvailableEvents=function(){return["click","dblclick","mousedown","mouseover","mouseout","contextmenu"]},h.prototype.genEvents=function(a,b,c,d,e,g,h,i){var j=this,k=this.getAvailableEvents(),l=f.getObjectArrayPath("markers."+g);k.forEach(function(b){e.label.on(b,j.genDispatchEvent(a,b,c,d,e.label,l,h,i))})},h.prototype.bindEvents=function(){},new h}]),angular.module("leaflet-directive").factory("leafletMapEvents",["$rootScope","$q","$log","leafletHelpers","leafletEventsHelpers","leafletIterators",function(a,b,c,d,e,f){var g=d.isDefined,h=e.fire,i=function(){return["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","contextmenu","focus","blur","preclick","load","unload","viewreset","movestart","move","moveend","dragstart","drag","dragend","zoomstart","zoomanim","zoomend","zoomlevelschange","resize","autopanstart","layeradd","layerremove","baselayerchange","overlayadd","overlayremove","locationfound","locationerror","popupopen","popupclose","draw:created","draw:edited","draw:deleted","draw:drawstart","draw:drawstop","draw:editstart","draw:editstop","draw:deletestart","draw:deletestop"]},j=function(a,b,d,e){return e&&(e+="."),function(f){var g="leafletDirectiveMap."+e+b;c.debug(g),h(a,g,d,f,f.target,a)}},k=function(a){a.$broadcast("boundsChanged")},l=function(a,b,c,d){if(g(c.urlHashCenter)){var e=b.getCenter(),f=e.lat.toFixed(4)+":"+e.lng.toFixed(4)+":"+b.getZoom();g(d.c)&&d.c===f||a.$emit("centerUrlHash",f)}},m=function(a,b,c,d,e){f.each(b,function(b){var f={};f[c]=b,a.on(b,j(d,b,e,a._container.id||""),f)})};return{getAvailableMapEvents:i,genDispatchMapEvent:j,notifyCenterChangedToBounds:k,notifyCenterUrlHashChanged:l,addEvents:m}}]),angular.module("leaflet-directive").factory("leafletMarkerEvents",["$rootScope","$q","$log","leafletHelpers","LeafletEventsHelpersFactory","leafletLabelEvents",function(a,b,c,d,e,f){var g=d.safeApply,h=d.isDefined,i=d,j=f,k=e,l=function(){k.call(this,"leafletDirectiveMarker","markers")};return l.prototype=new k,l.prototype.genDispatchEvent=function(b,c,d,e,f,h,i,j){var l=k.prototype.genDispatchEvent.call(this,b,c,d,e,f,h,i,j);return function(b){"click"===c?g(e,function(){a.$broadcast("leafletDirectiveMarkersClick",h)}):"dragend"===c&&(g(e,function(){i.lat=f.getLatLng().lat,i.lng=f.getLatLng().lng}),i.message&&i.focus===!0&&f.openPopup()),l(b)}},l.prototype.getAvailableEvents=function(){return["click","dblclick","mousedown","mouseover","mouseout","contextmenu","dragstart","drag","dragend","move","remove","popupopen","popupclose","touchend","touchstart","touchmove","touchcancel","touchleave"]},l.prototype.bindEvents=function(a,b,c,d,e,f){var g=k.prototype.bindEvents.call(this,a,b,c,d,e,f);i.LabelPlugin.isLoaded()&&h(b.label)&&j.genEvents(a,c,g,e,b,d,f)},new l}]),angular.module("leaflet-directive").factory("leafletPathEvents",["$rootScope","$q","$log","leafletHelpers","leafletLabelEvents","leafletEventsHelpers",function(a,b,c,d,e,f){var g=d.isDefined,h=d.isObject,i=d,j=d.errorHeader,k=e,l=f.fire,m=function(a,b,d,e,f,g,h,i){return a=a||"",a&&(a="."+a),function(j){var k="leafletDirectivePath"+a+"."+b;c.debug(k),l(e,k,d,j,j.target||f,h,g,i)}},n=function(a,b,d,e,f){var l,n,p=[],q="broadcast";if(g(f.eventBroadcast))if(h(f.eventBroadcast))if(g(f.eventBroadcast.path))if(h(f.eventBroadcast.paths))c.warn(j+"event-broadcast.path must be an object check your model.");else{void 0!==f.eventBroadcast.path.logic&&null!==f.eventBroadcast.path.logic&&("emit"!==f.eventBroadcast.path.logic&&"broadcast"!==f.eventBroadcast.path.logic?c.warn(j+"Available event propagation logic are: 'emit' or 'broadcast'."):"emit"===f.eventBroadcast.path.logic&&(q="emit"));var r=!1,s=!1;if(void 0!==f.eventBroadcast.path.enable&&null!==f.eventBroadcast.path.enable&&"object"==typeof f.eventBroadcast.path.enable&&(r=!0),void 0!==f.eventBroadcast.path.disable&&null!==f.eventBroadcast.path.disable&&"object"==typeof f.eventBroadcast.path.disable&&(s=!0),r&&s)c.warn(j+"can not enable and disable events at the same time");else if(r||s)if(r)for(l=0;l<f.eventBroadcast.path.enable.length;l++)n=f.eventBroadcast.path.enable[l],-1!==p.indexOf(n)?c.warn(j+"This event "+n+" is already enabled"):-1===o().indexOf(n)?c.warn(j+"This event "+n+" does not exist"):p.push(n);else for(p=o(),l=0;l<f.eventBroadcast.path.disable.length;l++){n=f.eventBroadcast.path.disable[l];var t=p.indexOf(n);-1===t?c.warn(j+"This event "+n+" does not exist or has been already disabled"):p.splice(t,1)}else c.warn(j+"must enable or disable events")}else p=o();else c.error(j+"event-broadcast must be an object check your model.");else p=o();for(l=0;l<p.length;l++)n=p[l],b.on(n,m(a,n,q,f,p,d));i.LabelPlugin.isLoaded()&&g(b.label)&&k.genEvents(a,d,q,f,b,e)},o=function(){return["click","dblclick","mousedown","mouseover","mouseout","contextmenu","add","remove","popupopen","popupclose"]};return{getAvailablePathEvents:o,bindPathEvents:n}}])}(angular); | |
| }(angular)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| �PNG | |