diff --git a/.gitignore b/.gitignore index 4e5cc436..46b2c0bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,32 @@ -temp +# OS +# =========== +.DS_Store +Thumbs.db + +# Project +# =========== +dist/angular-leaflet-directive.pre.js +dist/angular-leaflet-directive.min.no-header.js +js/angular-leaflet-directive-webpage.ngmin.js + +# Related ecosystem +# =========== node_modules -libpeerconnection.log +bower_components +coverage +saucelabs.json + +# General +# =========== +temp +*.log *.swp .*.swp *~ *.iml .idea .project -node_modules -dist/angular-leaflet-directive.pre.js -dist/angular-leaflet-directive.min.no-header.js -js/angular-leaflet-directive-webpage.ngmin.js -coverage -bower_components -saucelabs.json +core lib tags .tags diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 00000000..2f4841ec --- /dev/null +++ b/.jscsrc @@ -0,0 +1,3 @@ +{ + "preset": "airbnb" +} diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 00000000..054b6ae3 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,42 @@ +{ + "node": true, + "browser": true, + "esnext": true, + "bitwise": true, + "curly": false, + "eqeqeq": true, + "immed": true, + "indent": 4, + "latedef": true, + "newcap": true, + "noarg": true, + "regexp": true, + "undef": true, + "unused": true, + "trailing": true, + "smarttabs": true, + "globals": { + "angular": false, + "L": false, + "lvector": false, + "cartodb": false, + "jasmine": false, + "isCommonJS": false, + "exports": false, + "spyOn": false, + "it": false, + "xit": false, + "expect": false, + "runs": false, + "waits": false, + "waitsFor": false, + "beforeEach": false, + "afterEach": false, + "describe": false, + "xdescribe": false, + "protractor": false, + "browser": false, + "by": false, + "element": false + } +} diff --git a/.travis.yml b/.travis.yml index 693eaa37..21389c23 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,27 @@ +sudo: false language: node_js - +cache: + directories: + - node_modules +notifications: + email: false node_js: - - "0.10" + - '4' +before_install: + - npm i -g npm@^2.0.0 +before_script: + - npm prune + - npm install -g grunt-cli + - npm install -g bower + - bower install --config.interactive=false +after_success: + - npm run semantic-release +branches: + except: + - "/^v\\d+\\.\\d+\\.\\d+$/" env: global: - secure: "Ugov4QqHxEN4976jaQvtQigwwB7wiG0vxiE4pIDiZKJ67py0d0kLZXI4CzNs8zV5EOrkR+ug2cs9vTmA8CdSmhQcx4SVwFoim/ReoQb9AK76+tgEso+F3nZpE1jeIorKN2/LAXtwkHOZa9WaDwhMlCULJxJ8DZoMsXkc5Xq3c6A=" - secure: "QW7a9wCfc4u+MGnPyLzE+HHRhAhTf0a1mqixoUB2MVNL/hZ7+nXAOL/oz3LxodPpwH3NEl4RyqteGS15XpJvZKuKXiyHWbrfSLHz7DD1LYuIzc7UOgyBTXF0C97DP5ae7zui+qvDOe67ud+qBerroP9jdcx+mSVQgMIAfF1uWY4=" - secure: "gflE27IYzgjICndyY7800KdoNKem0oMWKtIjXQuSTJFuWJvBVWkUajT8maNbv1+c46r6iFptd27m5Arzl9hqAh2deHqLxwRGqietcY737q7oRJzKRfA4MGycF8fKHEh8U5KupXTC7UXuESLWGA+bpWA6KNJ5CImAw2MWJXmsX9c=" - -before_script: -  - npm install -g grunt-cli -  - npm install -g bower - - bower install --config.interactive=false diff --git a/CHANGELOG.md b/CHANGELOG.md index 713641bf..6f3f1de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,62 @@ + +### 0.9.0 (2015-10-12) + +#### Breaking changes + +* **events:** refactor(rootScope map events): If the id attribute is set for the leaflet directive then the id will be used in the rootScope leaflet events. Example: ``, Will fire `leafletDirectiveMap.firstMap.click` ([d22b3f0](https://github.com/tombatossals/angular-leaflet-directive/commit/d22b3f0)) + +#### Bug Fixes + +* **build:** Added "core" to .gitignore to avoid more "core" files inside distributed version ([2ff48c3e](https://github.com/tombatossals/angular-leaflet-directive/commit/2ff48c3e)) + +#### Features + +* **Leaflet.vector-markers:** Add support for Leaflet plugin 'Leaflet.vector-markers' ([eb386a1](https://github.com/tombatossals/angular-leaflet-directive/commit/eb386a1)) +* **Nokia Maps:** Added Nokia here maps. ([83b71ef](https://github.com/tombatossals/angular-leaflet-directive/commit/83b71ef)) + + +### 0.8.8 (2015-09-04) + + +#### Bug Fixes + +* **center:** + * Fix bug with scope.center via @ageblade ([7e718c5f](https://github.com/tombatossals/angular-leaflet-directive/commit/7e718c5f)) + * Fix bug with scope.center ([277ebc58](https://github.com/tombatossals/angular-leaflet-directive/commit/277ebc58)) + + +#### Features + +* **layers:** Add support for Leaflet.TileLayer.IIP ([ec0fe740](https://github.com/tombatossals/angular-leaflet-directive/commit/ec0fe740)) +* **lf-center:** lfCenter or 'lf-center' added which is a dupe of center. center to be deprecated ([06b5a3fa](https://github.com/tombatossals/angular-leaflet-directive/commit/06b5a3fa)) + + +#### Breaking changes + +* **logger:** Add new independent logger requirement to replace Angular $log. Remember to include angular-simple-logger before Angular-Leaflet from your bower assets. ([4f35bf6](https://github.com/tombatossals/angular-leaflet-directive/commit/4f35bf6)) + + + +### 0.8.7 (2015-08-26) + + +#### Bug Fixes + +* **code:** Deleted uneeded file ([5be6c453](https://github.com/tombatossals/angular-leaflet-directive/commit/5be6c453)) +* **controls:** Solved a problem with loading custom controls, as reported by @adgoncal here: ([a1843f20](https://github.com/tombatossals/angular-leaflet-directive/commit/a1843f20)) +* **dependencies:** + * remove dependency font-awesome ([f735e856](https://github.com/tombatossals/angular-leaflet-directive/commit/f735e856)) + * utfgrid now specifies main file ([79c6a252](https://github.com/tombatossals/angular-leaflet-directive/commit/79c6a252)) +* **paths:** Better log description with a path inside overlay error ([a02c3046](https://github.com/tombatossals/angular-leaflet-directive/commit/a02c3046)) + + +#### Features + +* **examples:** + * Added new example of loading custom controls ([979a7333](https://github.com/tombatossals/angular-leaflet-directive/commit/979a7333)) + * Compiled the examples with the new GeoGJSON Shape Layer added by @stev-0 here: h ([1f5e86a2](https://github.com/tombatossals/angular-leaflet-directive/commit/1f5e86a2)) + + ### 0.8.6 (2015-07-28) diff --git a/Gruntfile.js b/Gruntfile.js index 3bf01262..4fe611df 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,5 +1,6 @@ -global._ = require('lodash'); - module.exports = function (grunt) { + require('load-grunt-config')(grunt); + grunt.config('pkg', grunt.file.readJSON('package.json')); + }; diff --git a/LICENSE b/LICENSE index b8e9e728..d295fad2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2012-2013 https://github.com/tombatossals/angular-leaflet-directive +Copyright (c) https://github.com/tombatossals/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 diff --git a/README.md b/README.md index 834bf04d..cd81f16a 100644 --- a/README.md +++ b/README.md @@ -1,114 +1,47 @@ -# angular-leaflet-directive -## [tombatossals](http://github.com/tombatossals/angular-leaflet-directive) - main upstream -[![Join the chat at https://gitter.im/tombatossals/angular-leaflet-directive](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tombatossals/angular-leaflet-directive?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +# Angular Leaflet Directive -[![Build Status](https://travis-ci.org/tombatossals/angular-leaflet-directive.png)](https://travis-ci.org/tombatossals/angular-leaflet-directive) +[AngularJS](http://angularjs.org/) directive for the [Leaflet](http://www.leafletjs.com/) Javascript +Library. This software aims to easily embed maps managed by Leaflet on your project. -[![Dependencies](https://david-dm.org/tombatossals/angular-leaflet-directive.svg)](https://david-dm.org/tombatossals/angular-leaflet-directive)  -[![Dependencies](https://david-dm.org/tombatossals/angular-leaflet-directive/dev-status.svg)](https://david-dm.org/tombatossals/angular-leaflet-directive)  +### [tombatossals/angular-leaflet-directive](http://github.com/tombatossals/angular-leaflet-directive) +This is a personal project, which has been coded by me helped by many people for some years. I'm evolving it frequently, actually I'm making the code transition to Leaflet 1.0 and Angular 2. If you need enterprise for older versions, sorry, I can't give you more support that my spare time allows me. If you want to help with the actual code it would be really appreciated, but first of all, please, read the * [CONTRIBUTING documentation](https://github.com/tombatossals/angular-leaflet-directive/blob/master/CONTRIBUTING.md) -[![Coverage + +[![Build Status](https://travis-ci.org/tombatossals/angular-leaflet-directive.png?branch=master)](https://travis-ci.org/tombatossals/angular-leaflet-directive) [![Dependencies](https://david-dm.org/tombatossals/angular-leaflet-directive.svg)](https://david-dm.org/tombatossals/angular-leaflet-directive)  +[![Dependencies](https://david-dm.org/tombatossals/angular-leaflet-directive/dev-status.svg)](https://david-dm.org/tombatossals/angular-leaflet-directive) [![Coverage Status](https://coveralls.io/repos/tombatossals/angular-leaflet-directive/badge.png?branch=master)](http://tombatossals.github.io/angular-leaflet-directive/coverage/PhantomJS%201.9.7%20%28Linux%29/lcov-report/dist/angular-leaflet-directive.js.html) +[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) + +### [angular-ui](http://github.com/angular-ui/ui-leaflet) +If you need better response time with your doubts and needs with the code of version 0.9.0, take a look at the [angular-ui](http://github.com/angular-ui/ui-leaflet) fork of this project, it's lead by really awesome developers which have helped me evolving the project for some time. + +[![Build Status](https://travis-ci.org/angular-ui/ui-leaflet.png?branch=master)](https://travis-ci.org/angular-ui/ui-leaflet) [![Dependencies](https://david-dm.org/angular-ui/ui-leaflet.svg)](https://david-dm.org/angular-ui/ui-leaflet)  +[![Dependencies](https://david-dm.org/angular-ui/ui-leaflet/dev-status.svg)](https://david-dm.org/angular-ui/ui-leaflet) [![Coverage +Status](https://coveralls.io/repos/angular-ui/ui-leaflet/badge.png?branch=master)](http://realtymaps.github.io/ui-leaflet/coverage/PhantomJS%201.9.7%20%28Linux%29/lcov-report/dist/ui-leaflet.js.html) + +## Examples + +[Browse all the examples](http://tombatossals.github.io/angular-leaflet-directive/examples/0000-viewer.html) added by the community to learn about the directive and its possibilities. + +## Documentation -## [realtymaps](http://github.com/realtymaps/angular-leaflet-directive) -[![Build Status](https://travis-ci.org/realtymaps/angular-leaflet-directive.png)](https://travis-ci.org/realtymaps/angular-leaflet-directive) - -[![Dependencies](https://david-dm.org/realtymaps/angular-leaflet-directive.svg)](https://david-dm.org/realtymaps/angular-leaflet-directive)  -[![Dependencies](https://david-dm.org/realtymaps/angular-leaflet-directive/dev-status.svg)](https://david-dm.org/realtymaps/angular-leaflet-directive)  - -[![Coverage -Status](https://coveralls.io/repos/realtymaps/angular-leaflet-directive/badge.png?branch=master)](http://realtymaps.github.io/angular-leaflet-directive/coverage/PhantomJS%201.9.7%20%28Linux%29/lcov-report/dist/angular-leaflet-directive.js.html) - - -[AngularJS](http://angularjs.org/) directive for the Leaflet Javascript -Library. This software aims to easily embed maps managed by leaflet on your -[Leaflet](http://leaflet.cloudmade.com) project. - -You can browse all the examples added by the community to learn about the directive and its possibilities here: - -http://tombatossals.github.io/angular-leaflet-directive/examples/0000-viewer.html - -Or you can see some examples directly: - -* [Basic example](http://tombatossals.github.io/angular-leaflet-directive/examples/0100-basic-first-example.html) -* [Center example](http://tombatossals.github.io/angular-leaflet-directive/examples/0101-basic-center-example.html) -* [Center autodiscover example](http://tombatossals.github.io/angular-leaflet-directive/examples/0102-basic-center-autodiscover-example.html ) -* [Center with url hash example](http://tombatossals.github.io/angular-leaflet-directive/examples/0103-basic-center-url-hash-example.html) -* [Custom parameters example](http://tombatossals.github.io/angular-leaflet-directive/examples/0104-basic-custom-parameters-example.html) -* [Draw controls example](http://tombatossals.github.io/angular-leaflet-directive/examples/0401-controls-draw-example.html) -* [Bounds example](http://tombatossals.github.io/angular-leaflet-directive/examples/0105-basic-bounds-example.html) -* [MaxBounds example](http://tombatossals.github.io/angular-leaflet-directive/examples/0106-basic-maxbounds-example.html) -* [Tiles example](http://tombatossals.github.io/angular-leaflet-directive/examples/0107-basic-tiles-example.html) -* [Tile zoom changer example](http://tombatossals.github.io/angular-leaflet-directive/examples/0108-basic-tiles-zoom-changer-example.html) -* [Layers simple example](http://tombatossals.github.io/angular-leaflet-directive/examples/0201-layers-simple-example.html) -* [Overlays simple example](http://tombatossals.github.io/angular-leaflet-directive/examples/0202-layers-overlays-simple-example.html) -* [ImageOverlay simple example](http://tombatossals.github.io/angular-leaflet-directive/examples/0202-layers-overlays-simple-example.html) -* [Dynamic add/remove layers/overlays example](http://tombatossals.github.io/angular-leaflet-directive/examples/0204-layers-dynamic-addition-example.html) -* [Google Maps example](http://tombatossals.github.io/angular-leaflet-directive/examples/0205-layers-googlemaps-example.html) -* [Hide a layer in the layer selector example](http://tombatossals.github.io/angular-leaflet-directive/examples/0207-layers-hide-baselayer-on-selector-example.html) -* [ESRI Dynamic Layer example](http://tombatossals.github.io/angular-leaflet-directive/examples/0208-layers-esri-dynamic-layer-example.html) -* [ESRI Legend example](http://tombatossals.github.io/angular-leaflet-directive/examples/0209-layers-esri-legend-service-example.html) -* [Paths Simple example](http://tombatossals.github.io/angular-leaflet-directive/examples/0300-paths-simple-example.html) -* [Paths Types example](http://tombatossals.github.io/angular-leaflet-directive/examples/0301-paths-types-example.html) -* [Paths example](http://tombatossals.github.io/angular-leaflet-directive/examples/0304-paths-advanced-example.html) -* [Single marker example](http://tombatossals.github.io/angular-leaflet-directive/examples/0500-markers-simple-example.html) -* [Marker with label example](http://tombatossals.github.io/angular-leaflet-directive/examples/0505-markers-label-example.html) -* [Marker change opacity example](http://tombatossals.github.io/angular-leaflet-directive/examples/0507-markers-change-opacity-example.html) -* [Marker with Angular templates example](http://tombatossals.github.io/angular-leaflet-directive/examples/0514-markers-angular-template-example.html) -* [Marker with group clustering example](http://tombatossals.github.io/angular-leaflet-directive/examples/0508-markers-clustering-example.html) -* [Marker with group clustering example (10000 markers)](http://tombatossals.github.io/angular-leaflet-directive/examples/0511-markers-clustering-10000-markers-example.html) -* [Marker with group clustering example without overlays](http://tombatossals.github.io/angular-leaflet-directive/examples/0509-markers-clustering-without-overlays-example.html) -* [Marker groups example](http://tombatossals.github.io/angular-leaflet-directive/examples/0506-markers-groups-example.html) -* [Marker icons properties example](http://tombatossals.github.io/angular-leaflet-directive/examples/0503-markers-icons-example.html) -* [Markers dynamic add/remove example](http://tombatossals.github.io/angular-leaflet-directive/examples/0502-markers-add-remove-example.html) -* [Marker addition example](http://tombatossals.github.io/angular-leaflet-directive/examples/0501-markers-events-add-example.html) -* [Legend example](http://tombatossals.github.io/angular-leaflet-directive/examples/0600-mixed-image-legend-example.html) -* [GeoJson example](http://tombatossals.github.io/angular-leaflet-directive/examples/0113-basic-geojson-simple-example.html) -* [HeatMap example](http://tombatossals.github.io/angular-leaflet-directive/examples/0221-layers-heatmap-example.html) -* [Decoration example](http://tombatossals.github.io/angular-leaflet-directive/examples/0306-paths-decorations-simple-example.html) -* [UTFGrid example](http://tombatossals.github.io/angular-leaflet-directive/examples/0214-layers-utfgrid-example.html) -* [Events example](http://tombatossals.github.io/angular-leaflet-directive/examples/0115-basic-events-example.html) -* [Accessing the leaflet map object](http://tombatossals.github.io/angular-leaflet-directive/examples/0116-basic-access-leaflet-object-example.html) -* [Accessing the leaflet map object of two maps](http://tombatossals.github.io/angular-leaflet-directive/examples/0119-basic-double-map-access-map-object-example.html) -* [Two maps events](http://tombatossals.github.io/angular-leaflet-directive/examples/0118-basic-double-map-events-example.html) -* [Two maps with markers and events](http://tombatossals.github.io/angular-leaflet-directive/examples/0515-markers-two-maps-events-example.html) -* [Two maps sharing attributes](http://tombatossals.github.io/angular-leaflet-directive/examples/0120-basic-double-map-sharing-attributes-example.html) -* [Center map with GeoIP](http://tombatossals.github.io/angular-leaflet-directive/examples/0109-basic-center-geoip-example.html) - -To see it in action, go to the main page where you can find more examples and -some documentation: - - * http://tombatossals.github.com/angular-leaflet-directive - - -## How to use it - -You must include the leaflet-directive dependency on your angular module: +Still working on it. In the meantime, take a look at this URL for some minimal descriptions: https://tombatossals.github.com/angular-leaflet-directive + +## Getting started/How to use it + +Include the `leaflet-directive` dependency on your Angular module: ``` -var app = angular.module("demoapp", ["leaflet-directive"]); +var app = angular.module('demoapp', ['leaflet-directive']); ``` -After that, you can change the default values of the directive (if you want) on -your angular controller. For example, you can change the tiles source, the -maxzoom on the leaflet map or the polyline path properties. +After that, you are ready to rock. Just define some objects with the basic configuration you want reflected in your map and the rendered map will obey you. Also, you can modify that configuration dinamically if you need to. Let's see an example. -```javascript -angular.extend($scope, { - defaults: { - tileLayer: "http://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png", - maxZoom: 14, - path: { - weight: 10, - color: '#800000', - opacity: 1 - } - } -}); -``` +### center -If you want to set the start of the map to a precise position, you can define -the "center" property of the scope (lat, lng, zoom). It will be updated +If you want to set the map view to a precise position, you can define +the "center" property of the scope (lat, lng, zoom). It will also be updated interacting on the scope and on the leaflet map in two-way binding. Example: + ```javascript angular.extend($scope, { center: { @@ -119,37 +52,13 @@ angular.extend($scope, { }); ``` -If you need to run any method on the map object, use ```leafletData``` as following (notice the map object is returned in a form of a promise): - -```javascript -angular.module('myModule').controller('MapController', ['$scope', 'leafletData', - function($scope, leafletData) { - leafletData.getMap().then(function(map) { - L.GeoIP.centerMapOnPosition(map, 15); - }); - } -]); -``` - -Finally, you must include the markup directive on your HTML page, like this: +Finally, you must include the markup directive on your HTML page. One important thing is that you must define the map width&height, as attributes of the directive or with CSS code, as you wish. ```html - + ``` -If you want to have more than one map on the page and access their respective map objects, add an *id* attribute to your leaflet directive in HTML, like this: +If you want to have more than one map on the page and access their respective map objects, add an *id* attribute to your leaflet directive in HTML: ```html - -``` - -And then you can use this id in ```getMap()``` like this: - -```javascript -angular.module('myModule').controller('MapController', ['$scope', 'leafletData', - function($scope, leafletData) { - leafletData.getMap('mymap').then(function(map) { - L.GeoIP.centerMapOnPosition(map, 15); - }); - } -]); + ``` diff --git a/bower.json b/bower.json index d97732cd..b4f65832 100644 --- a/bower.json +++ b/bower.json @@ -2,7 +2,7 @@ "name": "angular-leaflet-directive", "author": "https://github.com/tombatossals/angular-leaflet-directive/graphs/contributors", "description": "angular-leaflet-directive - An AngularJS directive to easily interact with Leaflet maps", - "version": "0.8.6", + "version": "0.10.0", "homepage": "http://tombatossals.github.io/angular-leaflet-directive/", "keywords": [ "angularjs", @@ -31,27 +31,24 @@ "leaflet-tilelayer-geojson": "*", "Leaflet.utfgrid": "danzel/Leaflet.utfgrid", "Leaflet.awesome-markers": "*", + "leaflet-providers": "*", + "leaflet.vector-markers": "*", "webgl-heatmap-leaflet": "*", "leaflet-plugins": "*", "esri-leaflet": "*", "proj4": "*", - "font-awesome": "~4.3.x", + "font-awesome": "*", "proj4leaflet": "*", "Leaflet.MakiMarkers": "*", "Leaflet.heat": "https://github.com/Leaflet/Leaflet.heat/archive/gh-pages.tar.gz", "Leaflet.ExtraMarkers": "https://github.com/coryasilva/Leaflet.ExtraMarkers/archive/v1.0.1.tar.gz", "Leaflet.fullscreen": "http://github.com/Leaflet/Leaflet.fullscreen/archive/v0.0.4.tar.gz", "Leaflet.PolylineDecorator": "bbecquet/Leaflet.PolylineDecorator", - "ionrangeslider": "~1.9.3", - "leaflet-minimap": "~2.2.0", + "ionrangeslider": "*", + "leaflet-minimap": "*", "esri-leaflet-clustered-feature-layer": "~1.0.x", "esri-leaflet-heatmap-feature-layer": "~1.0.x", - "leaflet-search": "~1.5.8" - }, - "overrides": { - "Leaflet.utfgrid": { - "main": "dist/leaflet.utfgrid.js" - } + "leaflet-search": "*" }, "ignore": [ "**/.*", diff --git a/core b/core deleted file mode 100644 index 687fd3fc..00000000 Binary files a/core and /dev/null differ diff --git a/dist/angular-leaflet-directive.js b/dist/angular-leaflet-directive.js index 291f86f7..b4e92c96 100644 --- a/dist/angular-leaflet-directive.js +++ b/dist/angular-leaflet-directive.js @@ -1,1211 +1,1385 @@ +/**! + * 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 0.8.6 2015-07-28 +* 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", "leafletEvents", function ($q, leafletData, leafletMapDefaults, leafletHelpers, leafletEvents) { - return { - restrict: "EA", - replace: true, - scope: { - center : '=', - defaults : '=', - maxbounds : '=', - bounds : '=', - markers : '=', - legend : '=', - geojson : '=', - paths : '=', - tiles : '=', - layers : '=', - controls : '=', - decorations : '=', - eventBroadcast : '=', - markersWatchOptions : '=', - geojsonWatchOptions : '=' - }, - transclude: true, - template: '
', - controller: ["$scope", function ($scope) { - this._leafletMap = $q.defer(); - this.getMap = function () { - return this._leafletMap.promise; - }; +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: '
', + controller: ["$scope", function($scope) { + this._leafletMap = $q.defer(); + this.getMap = function() { + return this._leafletMap.promise; + }; - this.getLeafletScope = function() { - return $scope; - }; - }], + this.getLeafletScope = function() { + return $scope; + }; + }], - link: function(scope, element, attrs, ctrl) { - var isDefined = leafletHelpers.isDefined, - defaults = leafletMapDefaults.setDefaults(scope.defaults, attrs.id), - mapEvents = leafletEvents.getAvailableMapEvents(), - addEvents = leafletEvents.addEvents; + 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); + 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'); - } - } + // 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'); - } - } + 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 width attribute defined update css + // Then watch if bound property changes and update css + if (isDefined(attrs.width)) { + updateWidth(); - // 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(); - }); - } + scope.$watch( + function() { + return element[0].getAttribute('width'); + }, - // Create the Leaflet Map Object with the options - var map = new L.Map(element[0], leafletMapDefaults.getMapCreationDefaults(attrs.id)); - ctrl._leafletMap.resolve(map); + function() { + updateWidth(); + map.invalidateSize(); + }); + } - if (!isDefined(attrs.center)) { - map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); - } + // If the height attribute defined update css + // Then watch if bound property changes and update css + if (isDefined(attrs.height)) { + updateHeight(); - // 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); - } + scope.$watch( + function() { + return element[0].getAttribute('height'); + }, - // Set zoom control configuration - if (isDefined(map.zoomControl) && - isDefined(defaults.zoomControlPosition)) { - map.zoomControl.setPosition(defaults.zoomControlPosition); - } + function() { + updateHeight(); + map.invalidateSize(); + }); + } - if (isDefined(map.zoomControl) && - defaults.zoomControl===false) { - map.zoomControl.removeFrom(map); - } + // 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(map.zoomsliderControl) && - isDefined(defaults.zoomsliderControl) && - defaults.zoomsliderControl===false) { - map.zoomsliderControl.removeFrom(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); + } - // if no event-broadcast attribute, all events are broadcasted - if (!isDefined(attrs.eventBroadcast)) { - var logic = "broadcast"; - addEvents(map, mapEvents, "eventName", scope, logic); - } + // Set zoom control configuration + if (isDefined(map.zoomControl) && + isDefined(defaults.zoomControlPosition)) { + map.zoomControl.setPosition(defaults.zoomControlPosition); + } - // Resolve the map object to the promises - map.whenReady(function() { - leafletData.setMap(map, attrs.id); - }); + if (isDefined(map.zoomControl) && defaults.zoomControl === false) { + map.zoomControl.removeFrom(map); + } - scope.$on('$destroy', function () { - leafletMapDefaults.reset(); - map.remove(); - leafletData.unresolveMap(attrs.id); - }); + if (isDefined(map.zoomsliderControl) && + isDefined(defaults.zoomsliderControl) && + defaults.zoomsliderControl === false) { + map.zoomsliderControl.removeFrom(map); + } - //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(); - }); - } - }; + // 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) { +angular.module('leaflet-directive').factory('leafletBoundsHelpers', ["$log", "leafletHelpers", function($log, leafletHelpers) { - var isArray = leafletHelpers.isArray, - isNumber = leafletHelpers.isNumber, - isFunction = leafletHelpers.isFunction, - isDefined = leafletHelpers.isDefined; + 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); - } + 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 ]); - } + 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], }, + }; + }, - isValidBounds: _isValidBounds, + createBoundsFromLeaflet: function(lfBounds) { + if (!(isDefined(lfBounds) && isFunction(lfBounds.getNorthEast) && isFunction(lfBounds.getSouthWest))) { + $log.error('[AngularJS - Leaflet] The leaflet bounds is not valid object.'); + return; + } - 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; - } + var northEast = lfBounds.getNorthEast(); + var southWest = lfBounds.getSouthWest(); - return { - northEast: { - lat: boundsArray[0][0], - lng: boundsArray[0][1] - }, - southWest: { - lat: boundsArray[1][0], - lng: boundsArray[1][1] - } - }; + return { + northEast: { + lat: northEast.lat, + lng: northEast.lng, }, - - 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(), - southWest = lfBounds.getSouthWest(); - - return { - northEast: { - lat: northEast.lat, - lng: northEast.lng - }, - southWest: { - lat: southWest.lat, - lng: southWest.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; - } +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; + 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(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; - } - }); + 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 atLeastOneControlItemMustBeShown; + }; - return control; + var _createLayersControl = function(mapId) { + var defaults = leafletMapDefaults.getDefaults(mapId); + var controlOptions = { + collapsed: defaults.controls.layers.collapsed, + position: defaults.controls.layers.position, + autoZIndex: false, }; - 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); - } - }, - minimap: { - isPluginLoaded: function() { - if (!angular.isDefined(L.Control.MiniMap)) { - $log.error(errorHeader + ' Minimap plugin is not loaded.'); - return false; - } + angular.extend(controlOptions, defaults.controls.layers.options); - 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); + 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); + } - if (!isDefined(layer)) { - $log.warn(errorHeader + ' minimap control "layer" could not be created.'); - return; - } + return control; + }; - return new L.Control.MiniMap(layer, params); - } + var controlTypes = { + draw: { + isPluginLoaded: function() { + if (!angular.isDefined(L.Control.Draw)) { + $log.error(errorHeader + ' Draw plugin is not loaded.'); + return false; } - }; - return { - layersControlMustBeVisible: _controlLayersMustBeVisible, + return true; + }, - isValidControlType: function(type) { - return Object.keys(controlTypes).indexOf(type) !== -1; - }, + checkValidParams: function(/* params */) { + return true; + }, + + createControl: function(params) { + return new L.Control.Draw(params); + }, + }, + scale: { + isPluginLoaded: function() { + return true; + }, - createControl: function (type, params) { - if (!controlTypes[type].checkValidParams(params)) { - return; - } + 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 controlTypes[type].createControl(params); - }, + 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; + } - updateLayersControl: function(map, mapId, loaded, baselayers, overlays, leafletLayers) { - var i; - var _layersControl = _controls[mapId]; - var mustBeLoaded = _controlLayersMustBeVisible(baselayers, overlays, mapId); + return true; + }, - 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]; - } + 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; + } - 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); - } - } + return true; + }, - map.addControl(_layersControl); - } - return mustBeLoaded; + checkValidParams: function(params) { + if (!isDefined(params.layer)) { + $log.warn(errorHeader + ' minimap "layer" option should be defined.'); + return false; } - }; -}]); -angular.module("leaflet-directive").service('leafletData', ["$log", "$q", "leafletHelpers", function ($log, $q, leafletHelpers) { - var getDefer = leafletHelpers.getDefer, - getUnresolvedDefer = leafletHelpers.getUnresolvedDefer, - setResolvedDefer = leafletHelpers.setResolvedDefer; + return true; + }, - var _private = {}; - var self = this; + createControl: function(params) { + var layer = createLayer(params.layer); - var upperFirst = function (string) { - return string.charAt(0).toUpperCase() + string.slice(1); - }; + if (!isDefined(layer)) { + $log.warn(errorHeader + ' minimap control "layer" could not be created.'); + return; + } - 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] = {}; - }); + return new L.Control.MiniMap(layer, params); + }, + }, + }; - this.unresolveMap = function (scopeId) { - var id = leafletHelpers.obtainEffectiveMapId(_private.map, scopeId); - _privateItems.forEach(function (itemName) { - _private[itemName][id] = undefined; - }); - }; + return { + layersControlMustBeVisible: _controlLayersMustBeVisible, - //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); - }; + isValidControlType: function(type) { + return Object.keys(controlTypes).indexOf(type) !== -1; + }, - self['get' + name] = function (scopeId) { - var defer = getDefer(_private[itemName], scopeId); - return defer.promise; - }; - }); -}]); + createControl: function(type, params) { + if (!controlTypes[type].checkValidParams(params)) { + return; + } -angular.module("leaflet-directive") -.service('leafletDirectiveControlsHelpers', ["$log", "leafletData", "leafletHelpers", function ($log, leafletData, leafletHelpers) { - var _isDefined = leafletHelpers.isDefined, - _isString = leafletHelpers.isString, - _isObject = leafletHelpers.isObject, - _mainErrorHeader = leafletHelpers.errorHeader; + return controlTypes[type].createControl(params); + }, - var _errorHeader = _mainErrorHeader + '[leafletDirectiveControlsHelpers'; + updateLayersControl: function(map, mapId, loaded, baselayers, overlays, leafletLayers) { + var i; + var _layersControl = _controls[mapId]; + var mustBeLoaded = _controlLayersMustBeVisible(baselayers, overlays, mapId); - 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 (isDefined(_layersControl) && loaded) { + for (i in leafletLayers.baselayers) { + _layersControl.removeLayer(leafletLayers.baselayers[i]); } - if(_isString(thingToAddName) && _isDefined(createFn) && _isDefined(cleanFn)){ - extender[thingToAddName] = { - create: createFn, - clean: cleanFn - }; + for (i in leafletLayers.overlays) { + _layersControl.removeLayer(leafletLayers.overlays[i]); } - else if(_isObject(thingToAddName) && !_isDefined(createFn) && !_isDefined(cleanFn)){ - extender = thingToAddName; + + 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); + } } - else{ - $log.error(_fnHeader + 'incorrect arguments'); - return; + + 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); + } } - //add external control to create / destroy markers without a watch - leafletData.getDirectiveControls().then(function(controls){ - angular.extend(controls, extender); - leafletData.setDirectiveControls(controls, id); - }); - }; + map.addControl(_layersControl); + } - return { - extend: _extend - }; + return mustBeLoaded; + }, + }; }]); -angular.module("leaflet-directive").factory('leafletEvents', - ["leafletMapEvents", "leafletMarkerEvents", "leafletPathEvents", "leafletIterators", function (leafletMapEvents, leafletMarkerEvents, leafletPathEvents, leafletIterators) { - //NOTE THIS SHOULD BE DEPRECATED infavor of getting a specific events helper - var instance = angular.extend({}, - leafletMapEvents, { - bindMarkerEvents: leafletMarkerEvents.bindEvents, - getAvailableMarkerEvents: leafletMarkerEvents.getAvailableEvents - }, leafletPathEvents); - - var genDispatchMapEvent = instance.genDispatchMapEvent; - - instance.addEvents = function(map, mapEvents, contextName, scope, logic){ - leafletIterators.each(mapEvents, function(eventName) { - var context = {}; - context[contextName] = eventName; - map.on(eventName, genDispatchMapEvent(scope, eventName, logic), context); - }); - }; +angular.module('leaflet-directive').service('leafletData', ["$log", "$q", "leafletHelpers", function($log, $q, leafletHelpers) { + var getDefer = leafletHelpers.getDefer, + getUnresolvedDefer = leafletHelpers.getUnresolvedDefer, + setResolvedDefer = leafletHelpers.setResolvedDefer; - return instance; -}]); + var _private = {}; + var self = this; -angular.module("leaflet-directive") -.service('leafletGeoJsonHelpers', ["leafletHelpers", "leafletIterators", function (leafletHelpers, leafletIterators) { - var lHlp = leafletHelpers, - lIt = leafletIterators; - var Point = function(lat,lng){ - this.lat = lat; - this.lng = lng; - return this; - }; + var upperFirst = function(string) { + return string.charAt(0).toUpperCase() + string.slice(1); + }; - 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 _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); }; - 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; - } + self['get' + name] = function(scopeId) { + var defer = getDefer(_private[itemName], scopeId); + return defer.promise; }; + }); +}]); - 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; - } - } +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 ret = lIt.all(['lat', 'lng'], function(pos){ - return lHlp.isDefined(coords[pos]) && lHlp.isNumber(coords[pos]); - }); - return ret; - }; + var _errorHeader = _mainErrorHeader + '[leafletDirectiveControlsHelpers'; - 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 - }; + 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; + } - return { - getLat: _getLat, - getLng: _getLng, - validateCoords: _validateCoords, - getCoords: _getCoords - }; - }]); + //add external control to create / destroy markers without a watch + leafletData.getDirectiveControls().then(function(controls) { + angular.extend(controls, extender); + leafletData.setDirectiveControls(controls, id); + }); + }; -angular.module("leaflet-directive").factory('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 + return { + extend: _extend, + }; +}]); - 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; - }; +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; + }; - /* - 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 + '"]'; - }); - }; + 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; + } + }; - /* Object Dot Notation - _getObjectPath(["bike","one","two"]) - returns: - "bike.one.two" - */ - var _getObjectDotPath = function(arrayOfStrings){ - return arrayOfStrings.reduce(function(previous, current) { - return previous + '.' + current; - }); - }; + 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; + } + }; - function _obtainEffectiveMapId(d, mapId) { - var id, 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 if (Object.keys(d).length === 0) { - id = "main"; - } 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; - } + var _validateCoords = function(coords) { + if (lHlp.isUndefined(coords)) { + return false; + } - return id; + 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; + } } - function _getUnresolvedDefer(d, mapId) { - var id = _obtainEffectiveMapId(d, mapId), - defer; + var ret = lIt.all(['lat', 'lng'], function(pos) { + return lHlp.isDefined(coords[pos]) && lHlp.isNumber(coords[pos]); + }); - if (!angular.isDefined(d[id]) || d[id].resolvedDefer === true) { - defer = $q.defer(); - d[id] = { - defer: defer, - resolvedDefer: false - }; - } else { - defer = d[id].defer; - } + return ret; + }; - return defer; + var _getCoords = function(value) { + if (!value || !_validateCoords(value)) { + return; } - var _isDefined = function(value) { - return angular.isDefined(value) && value !== null; - }; - var _isUndefined = function(value){ - return !_isDefined(value); - }; + 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; + } - return { - 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; - }, + //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 + }; - //Determine if a reference is undefined or {} - isUndefinedOrEmpty: function (value) { - return (angular.isUndefined(value) || value === null) || Object.keys(value).length === 0; - }, + return { + getLat: _getLat, + getLng: _getLng, + validateCoords: _validateCoords, + getCoords: _getCoords, + }; +}]); - // 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); - }, +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 - 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); - }, + 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; + } - 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; - }, + obj = object; + pathStr.split('.').forEach(function(value) { + if (obj) { + obj = obj[value]; + } + }); - safeApply: function($scope, fn) { - var phase = $scope.$root.$$phase; - if (phase === '$apply' || phase === '$digest') { - $scope.$eval(fn); - } else { - $scope.$evalAsync(fn); - } - }, + return obj; + }; - obtainEffectiveMapId: _obtainEffectiveMapId, + /* + 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 + '"]'; + }); + }; - getDefer: function(d, mapId) { - var id = _obtainEffectiveMapId(d, mapId), - defer; - if (!angular.isDefined(d[id]) || d[id].resolvedDefer === false) { - defer = _getUnresolvedDefer(d, mapId); - } else { - defer = d[id].defer; - } - return defer; - }, + /* Object Dot Notation + _getObjectPath(["bike","one","two"]) + returns: + "bike.one.two" + */ + var _getObjectDotPath = function(arrayOfStrings) { + return arrayOfStrings.reduce(function(previous, current) { + return previous + '.' + current; + }); + }; - getUnresolvedDefer: _getUnresolvedDefer, + 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; + } - setResolvedDefer: function(d, mapId) { - var id = _obtainEffectiveMapId(d, mapId); - d[id].resolvedDefer = true; - }, + return id; + } - rangeIsSupported: function() { - var testrange = document.createElement('input'); - testrange.setAttribute('type', 'range'); - return testrange.type === 'range'; - }, + function _getUnresolvedDefer(d, mapId) { + var id = _obtainEffectiveMapId(d, mapId); + var defer; - FullScreenControlPlugin: { - isLoaded: function() { - return angular.isDefined(L.Control.Fullscreen); - } - }, + if (!angular.isDefined(d[id]) || d[id].resolvedDefer === true) { + defer = $q.defer(); + d[id] = { + defer: defer, + resolvedDefer: false, + }; + } else { + defer = d[id].defer; + } - MiniMapControlPlugin: { - isLoaded: function() { - return angular.isDefined(L.Control.MiniMap); - } - }, + return defer; + } - 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; - } - } - }, + var _isDefined = function(value) { + return angular.isDefined(value) && value !== null; + }; - 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; - } - } - }, + var _isUndefined = function(value) { + return !_isDefined(value); + }; - 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; - } - } - }, - 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; - } - } + // 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; }, - 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; - } - } + + equal: function(iconA, iconB) { + if (this.is(iconA)) { + return angular.equals(iconA, iconB); + } else { + return false; + } }, - CartoDB: { - isLoaded: function(){ - return cartodb; - }, - is: function(/*layer*/) { - return true; - /* - if (this.isLoaded()) { - return layer instanceof L.TileLayer.GeoJSON; - } else { - return false; - }*/ - } + }, + Icon: { + is: function(icon) { + return icon instanceof L.Icon; }, - 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; - } - } - } + + 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 + }, + }, + /* + 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 (sets $watch(function,isDeep)) - individual - doWatch:boolean - isDeep:boolean - */ - //legacy defaults - watchOptions: { - doWatch:true, - isDeep: true, - individual:{ - doWatch:true, - isDeep: true - } - } - }; + 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) { +angular.module('leaflet-directive').service('leafletIterators', ["$log", "leafletHelpers", function($log, leafletHelpers) { - var lHlp = leafletHelpers, - errorHeader = leafletHelpers.errorHeader + 'leafletIterators: '; + var lHlp = leafletHelpers; + var errorHeader = leafletHelpers.errorHeader + 'leafletIterators: '; //BEGIN COPY from underscore var _keys = Object.keys; @@ -1219,7 +1393,7 @@ angular.module('leaflet-directive').service('leafletIterators', ["$log", "leafle var _isArrayLike = function(collection) { var length = collection !== null && collection.length; - return lHlp.isNumber(length) && length >= 0 && length <= MAX_ARRAY_INDEX; + return lHlp.isNumber(length) && length >= 0 && length <= MAX_ARRAY_INDEX; }; // Keep the identity function around for default iteratees. @@ -1242,12 +1416,15 @@ angular.module('leaflet-directive').service('leafletIterators', ["$log", "leafle 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); }; @@ -1263,38 +1440,44 @@ angular.module('leaflet-directive').service('leafletIterators', ["$log", "leafle var length = arguments.length; if (length < 2 || obj === null) return obj; for (var index = 1; index < length; index++) { - var source = arguments[index], - keys = keysFunc(source), - l = keys.length; + 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, _assign = null; + 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), length = keys.length; + 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, _matches = null; + var _matcher; + var _matches = null; _matcher = _matches = function(attrs) { attrs = _extendOwn({}, attrs); return function(obj) { @@ -1302,7 +1485,6 @@ angular.module('leaflet-directive').service('leafletIterators', ["$log", "leafle }; }; - // 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. @@ -1313,49 +1495,56 @@ angular.module('leaflet-directive').service('leafletIterators', ["$log", "leafle return _property(value); }; - var _every, _all = null; + var _every; + var _all = null; _every = _all = function(obj, predicate, context) { predicate = cb(predicate, context); - var keys = !_isArrayLike(obj) && _keys(obj), - length = (keys || obj).length; + 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) { + 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'); + + 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')){ + var _iterate = function(collection, externalCb, internalCb) { + if (_hasErrors(undefined, internalCb, true, 'internalCb')) { return; } - if(!_hasErrors(collection, externalCb)){ - for(var key in collection){ - internalCb(collection[key], key); + + 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){ + var _each = function(collection, cb) { + _iterate(collection, cb, function(val, key) { cb(val, key); }); }; @@ -1364,1470 +1553,1677 @@ angular.module('leaflet-directive').service('leafletIterators', ["$log", "leafle each:_each, forEach: _each, every: _every, - all: _all + all: _all, }; }]); -angular.module("leaflet-directive") -.factory('leafletLayerHelpers', ["$rootScope", "$log", "leafletHelpers", "leafletIterators", function ($rootScope, $log, 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; +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; } - var utfgrid = new L.UtfGrid(params.url, params.pluginOptions); - utfgrid.on('mouseover', function(e) { - $rootScope.$broadcast('leafletDirectiveMap.utfgridMouseover', e); + 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; + }; - utfgrid.on('mouseout', function(e) { - $rootScope.$broadcast('leafletDirectiveMap.utfgridMouseout', e); + 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; - utfgrid.on('click', function(e) { - $rootScope.$broadcast('leafletDirectiveMap.utfgridClick', e); + 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); }); - utfgrid.on('mousemove', function(e) { - $rootScope.$broadcast('leafletDirectiveMap.utfgridMousemove', e); + 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 += '
' + legendData.error.message + '
'; + } else { + if (type === 'arcgis') { + for (var i = 0; i < legendData.layers.length; i++) { + var layer = legendData.layers[i]; + div.innerHTML += '
' + layer.layerName + '
'; + for (var j = 0; j < layer.legend.length; j++) { + var leg = layer.legend[j]; + div.innerHTML += + '
' + + '
' + leg.label + '
'; + } + } + } else if (type === 'image') { + div.innerHTML = ''; + } + } + }; + + 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); + } - return utfgrid; + _updateLegend(div, legendData, type, url); + return div; }; + }; - 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); - } - }, - 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 && 'string' === typeof options.crs) { - /*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)); - }); - 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); - } - }, - 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 _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 += + '
' + + '
' + legend.labels[i] + '
'; + } - 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; - - return L.esri.featureLayer(params.options); - } - }, - 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 (!L.Browser.touch) { + L.DomEvent.disableClickPropagation(div); + L.DomEvent.on(div, 'mousewheel', L.DomEvent.stopPropagation); + } else { + L.DomEvent.on(div, 'click', L.DomEvent.stopPropagation); + } - 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; - } + return div; + }; + }; - 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 { + getOnAddLegend: _getOnAddLegend, + getOnAddArrayLegend: _getOnAddArrayLegend, + updateLegend: _updateLegend, + }; +}); - return layer; - } +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, }, - heat: { - mustHaveUrl: false, - mustHaveData: true, - createLayer: function(params) { - if (!Helpers.HeatLayerPlugin.isLoaded()) { - return; - } - var layer = new L.heatLayer(); + }, + nominatim: { + server: ' http://nominatim.openstreetmap.org/search', + }, + crs: L.CRS.EPSG3857, + tileLayer: '//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + tileLayerOptions: { + attribution: '© OpenStreetMap contributors', + }, + path: { + weight: 10, + opacity: 1, + color: '#0000ff', + }, + center: { + lat: 0, + lng: 0, + zoom: 1, + }, + }; + } - if (isArray(params.data)) { - layer.setLatLngs(params.data); - } + var isDefined = leafletHelpers.isDefined; + var isObject = leafletHelpers.isObject; + var obtainEffectiveMapId = leafletHelpers.obtainEffectiveMapId; + var defaults = {}; - if (isObject(params.options)) { - layer.setOptions(params.options); - } + // 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, + }; - 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); - } - }, + if (isDefined(d.minZoom)) { + mapDefaults.minZoom = d.minZoom; + } - // 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); - } + 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]; } - }; + } - 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; + 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 (Object.keys(layerTypes).indexOf(layerDefinition.type) === -1) { - $log.error('[AngularJS - Leaflet] A layer must have a valid type: ' + Object.keys(layerTypes)); - return false; + if (isObject(userDefaults.crs)) { + newDefaults.crs = userDefaults.crs; + } else if (isDefined(L.CRS[userDefaults.crs])) { + newDefaults.crs = L.CRS[userDefaults.crs]; } - // 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 (isDefined(userDefaults.center)) { + angular.copy(userDefaults.center, newDefaults.center); } - if (layerTypes[layerDefinition.type].mustHaveData && !isDefined(layerDefinition.data)) { - $log.error('[AngularJS - Leaflet] The base layer must have a "data" array attribute'); - return false; + if (isDefined(userDefaults.tileLayerOptions)) { + angular.copy(userDefaults.tileLayerOptions, newDefaults.tileLayerOptions); } - 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 (isDefined(userDefaults.maxZoom)) { + newDefaults.maxZoom = userDefaults.maxZoom; } - 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 (isDefined(userDefaults.minZoom)) { + newDefaults.minZoom = userDefaults.minZoom; } - if (layerTypes[layerDefinition.type].mustHaveKey && !isDefined(layerDefinition.key)) { - $log.error('[AngularJS - Leaflet] The type of layer ' + layerDefinition.type + ' must have key defined'); - return false ; + if (isDefined(userDefaults.zoomAnimation)) { + newDefaults.zoomAnimation = userDefaults.zoomAnimation; } - return true; - } - function createLayer(layerDefinition) { - if (!isValidLayerType(layerDefinition)) { - return; + if (isDefined(userDefaults.fadeAnimation)) { + newDefaults.fadeAnimation = userDefaults.fadeAnimation; } - if (!isString(layerDefinition.name)) { - $log.error('[AngularJS - Leaflet] A base layer must have a name'); - return; + if (isDefined(userDefaults.markerZoomAnimation)) { + newDefaults.markerZoomAnimation = userDefaults.markerZoomAnimation; } - if (!isObject(layerDefinition.layerParams)) { - layerDefinition.layerParams = {}; + + if (isDefined(userDefaults.worldCopyJump)) { + newDefaults.worldCopyJump = userDefaults.worldCopyJump; } - if (!isObject(layerDefinition.layerOptions)) { - layerDefinition.layerOptions = {}; + + if (isDefined(userDefaults.map)) { + newDefaults.map = userDefaults.map; } - // 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]; + if (isDefined(userDefaults.path)) { + newDefaults.path = userDefaults.path; } + } + + var mapId = obtainEffectiveMapId(defaults, scopeId); + defaults[mapId] = newDefaults; + return newDefaults; + }, + }; +}]); - var params = { - url: layerDefinition.url, - data: layerDefinition.data, - options: layerDefinition.layerOptions, - layer: layerDefinition.layer, - type: layerDefinition.layerType, - bounds: layerDefinition.bounds, - key: layerDefinition.key, - apiKey: layerDefinition.apiKey, - pluginOptions: layerDefinition.pluginOptions, - user: layerDefinition.user - }; +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'; + }); - //TODO Add $watch to the layer properties - return layerTypes[layerDefinition.type].createLayer(params); - } + return '[leafletMarker] : \n' + retStr; + }; - return { - createLayer: createLayer - }; -}]); + var _log = function(marker, useConsole) { + var logger = useConsole ? console : $log; + logger.debug(_string(marker)); + }; -angular.module("leaflet-directive").factory('leafletLegendHelpers', function () { - var _updateLegend = function(div, legendData, type, url) { - div.innerHTML = ''; - if(legendData.error) { - div.innerHTML += '
' + legendData.error.message + '
'; - } else { - if (type === 'arcgis') { - for (var i = 0; i < legendData.layers.length; i++) { - var layer = legendData.layers[i]; - div.innerHTML += '
' + layer.layerName + '
'; - for(var j = 0; j < layer.legend.length; j++) { - var leg = layer.legend[j]; - div.innerHTML += - '
' + - '
' + leg.label + '
'; - } - } - } - else if (type === 'image') { - div.innerHTML = ''; - } - } - }; - - 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 += - '
' + - '
' + legend.labels[i] + '
'; - } - 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, - }; -}); + 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.'); + } -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: '© OpenStreetMap contributors' - }, - path: { - weight: 10, - opacity: 1, - color: '#0000ff' - }, - center: { - lat: 0, - lng: 0, - zoom: 1 - } - }; + return new L.AwesomeMarkers.icon(iconData); } - var isDefined = leafletHelpers.isDefined, - isObject = leafletHelpers.isObject, - obtainEffectiveMapId = leafletHelpers.obtainEffectiveMapId, - defaults = {}; + if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'vectorMarker') { + if (!VectorMarkersPlugin.isLoaded()) { + $log.error(errorHeader + ' The VectorMarkers Plugin is not loaded.'); + } - // 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]; - }, + return new L.VectorMarkers.icon(iconData); + } - 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(iconData) && isDefined(iconData.type) && iconData.type === 'makiMarker') { + if (!MakiMarkersPlugin.isLoaded()) { + $log.error(errorHeader + 'The MakiMarkers Plugin is not loaded.'); + } - if (isDefined(d.minZoom)) { - mapDefaults.minZoom = d.minZoom; - } + return new L.MakiMarkers.icon(iconData); + } - if (isDefined(d.zoomAnimation)) { - mapDefaults.zoomAnimation = d.zoomAnimation; - } + if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'extraMarker') { + if (!ExtraMarkersPlugin.isLoaded()) { + $log.error(errorHeader + 'The ExtraMarkers Plugin is not loaded.'); + } - if (isDefined(d.fadeAnimation)) { - mapDefaults.fadeAnimation = d.fadeAnimation; - } + return new L.ExtraMarkers.icon(iconData); + } - if (isDefined(d.markerZoomAnimation)) { - mapDefaults.markerZoomAnimation = d.markerZoomAnimation; - } + if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'div') { + return new L.divIcon(iconData); + } - if (d.map) { - for (var option in d.map) { - mapDefaults[option] = d.map[option]; - } - } + if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'dom') { + if (!DomMarkersPlugin.isLoaded()) { + $log.error(errorHeader + 'The DomMarkers Plugin is not loaded.'); + } - return mapDefaults; - }, + 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); + } - 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); - } + // 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; + } - if (isObject(userDefaults.crs)) { - newDefaults.crs = userDefaults.crs; - } else if (isDefined(L.CRS[userDefaults.crs])) { - newDefaults.crs = L.CRS[userDefaults.crs]; - } + var base64icon = 'data:image/png;base64,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'; + 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], + }); + } - if (isDefined(userDefaults.center)) { - angular.copy(userDefaults.center, newDefaults.center); - } + return new L.Icon(iconData); + }; - if (isDefined(userDefaults.tileLayerOptions)) { - angular.copy(userDefaults.tileLayerOptions, newDefaults.tileLayerOptions); - } + var _resetMarkerGroup = function(groupName) { + if (isDefined(groups[groupName])) { + groups.splice(groupName, 1); + } + }; - if (isDefined(userDefaults.maxZoom)) { - newDefaults.maxZoom = userDefaults.maxZoom; - } + var _resetMarkerGroups = function() { + groups = {}; + }; - if (isDefined(userDefaults.minZoom)) { - newDefaults.minZoom = userDefaults.minZoom; - } + var _deleteMarker = function(marker, map, layers) { + marker.closePopup(); - if (isDefined(userDefaults.zoomAnimation)) { - newDefaults.zoomAnimation = userDefaults.zoomAnimation; - } + // 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(userDefaults.fadeAnimation)) { - newDefaults.fadeAnimation = userDefaults.fadeAnimation; - } + if (isDefined(groups)) { + for (var groupKey in groups) { + if (groups[groupKey].hasLayer(marker)) { + groups[groupKey].removeLayer(marker); + } + } + } - if (isDefined(userDefaults.markerZoomAnimation)) { - newDefaults.markerZoomAnimation = userDefaults.markerZoomAnimation; - } + if (map.hasLayer(marker)) { + map.removeLayer(marker); + } + }; - if (isDefined(userDefaults.worldCopyJump)) { - newDefaults.worldCopyJump = userDefaults.worldCopyJump; - } + 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(); + } + }; - if (isDefined(userDefaults.map)) { - newDefaults.map = userDefaults.map; - } + var compilePopup = function(marker, markerScope) { + $compile(marker._popup._contentNode)(markerScope); + }; - if (isDefined(userDefaults.path)) { - newDefaults.path = userDefaults.path; - } - } + 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); + }); + } - var mapId = obtainEffectiveMapId(defaults, scopeId); - defaults[mapId] = newDefaults; - return newDefaults; - } - }; -}]); + //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; -angular.module("leaflet-directive").service('leafletMarkersHelpers', ["$rootScope", "$timeout", "leafletHelpers", "$log", "$compile", "leafletGeoJsonHelpers", function ($rootScope, $timeout, leafletHelpers, $log, $compile, leafletGeoJsonHelpers) { - var isDefined = leafletHelpers.isDefined, - defaultTo = leafletHelpers.defaultTo, - MarkerClusterPlugin = leafletHelpers.MarkerClusterPlugin, - AwesomeMarkersPlugin = leafletHelpers.AwesomeMarkersPlugin, - MakiMarkersPlugin = leafletHelpers.MakiMarkersPlugin, - ExtraMarkersPlugin = leafletHelpers.ExtraMarkersPlugin, - safeApply = leafletHelpers.safeApply, - Helpers = leafletHelpers, - isString = leafletHelpers.isString, - isNumber = leafletHelpers.isNumber, - isObject = leafletHelpers.isObject, - groups = {}, - geoHlp = leafletGeoJsonHelpers, - 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)); - }; + marker._popup._updateLayout(); + marker._popup._updatePosition(); - 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.'); - } + if (marker._popup.options.autoPan) { + adjustPopupPan(marker, map); + } - return new L.AwesomeMarkers.icon(iconData); - } + //using / returning reflow so jshint doesn't moan + return reflow; + }; - if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'makiMarker') { - if (!MakiMarkersPlugin.isLoaded()) { - $log.error(errorHeader + 'The MakiMarkers Plugin is not loaded.'); - } + 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; - return new L.MakiMarkers.icon(iconData); - } + if (compileMessage) { + if (!isDefined(marker._popup) || !isDefined(marker._popup._contentNode)) { + $log.error(errorHeader + 'Popup is invalid or does not have any content.'); + return false; + } - 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); - } + compilePopup(marker, markerScope); + updatePopup(marker, markerData, map); + } + }; - if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'div') { - return new L.divIcon(iconData); - } + 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; - // 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; - } + if (Helpers.LabelPlugin.isLoaded() && isDefined(markerData.label)) { + if (isDefined(markerData.label.options) && markerData.label.options.noHide === true) { + marker.showLabel(); + } - var base64icon = "data:image/png;base64,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"; - 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 (compileMessage && isDefined(marker.label)) { + $compile(marker.label._container)(labelScope); + } + } + }; - 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] - }); - } + var _updateMarker = function(markerData, oldMarkerData, marker, name, leafletScope, layers, map) { + if (!isDefined(oldMarkerData)) { + return; + } - return new L.Icon(iconData); - }; + // 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; + } - var _resetMarkerGroup = function (groupName) { - if (isDefined(groups[groupName])) { - groups.splice(groupName, 1); - } - }; + // watch is being initialized if old and new object is the same + var isInitializing = markerData === oldMarkerData; - var _resetMarkerGroups = function () { - groups = {}; - }; + // Update marker rotation + if (isDefined(markerData.iconAngle) && oldMarkerData.iconAngle !== markerData.iconAngle) { + marker.setIconAngle(markerData.iconAngle); + } - 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; - } - } - } + // 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(); } - if (isDefined(groups)) { - for (var groupKey in groups) { - if (groups[groupKey].hasLayer(marker)) { - groups[groupKey].removeLayer(marker); - } - } + // Test if it is not on the map and add it + if (!map.hasLayer(marker)) { + map.addLayer(marker); } + } + } - if (map.hasLayer(marker)) { - map.removeLayer(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); + } - var adjustPopupPan = function(marker, map) { - var containerHeight = marker._popup._container.offsetHeight, - layerPos = new L.Point(marker._popup._containerLeft, -containerHeight - marker._popup._containerBottom), - containerPos = map.layerPointToContainerPoint(layerPos); - if (containerPos !== null) { - marker._popup._adjustPan(); - } - }; + 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); + } - var compilePopup = function(marker, markerScope) { - $compile(marker._popup._contentNode)(markerScope); - }; + marker.closePopup(); - 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); - }); - } + // 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); + } - //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; + // 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; + } - marker._popup._updateLayout(); - marker._popup._updatePosition(); + // 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; + } - if (marker._popup.options.autoPan) { - adjustPopupPan(marker, map); - } + // The marker goes to a correct layer group, so first of all we add it + layerGroup.addLayer(marker); - //using / returning reflow so jshint doesn't moan - return reflow; - }; + // 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(); + } + } - 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, - compileMessage = isDefined(markerData.compileMessage) ? markerData.compileMessage : true; + // Update the draggable property + if (markerData.draggable !== true && oldMarkerData.draggable === true && (isDefined(marker.dragging))) { + marker.dragging.disable(); + } - if (compileMessage) { - if (!isDefined(marker._popup) || !isDefined(marker._popup._contentNode)) { - $log.error(errorHeader + 'Popup is invalid or does not have any content.'); - return false; - } + 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(); + } + } + } - compilePopup(marker, markerScope); - updatePopup(marker, markerData, map); + // 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(); + } - var _manageOpenLabel = function (marker, markerData) { - var markerScope = angular.isFunction(markerData.getMessageScope) ? markerData.getMessageScope() : $rootScope, - labelScope = angular.isFunction(markerData.getLabelScope) ? markerData.getLabelScope() : markerScope, - compileMessage = isDefined(markerData.compileMessage) ? markerData.compileMessage : true; + marker.setIcon(createLeafletIcon(markerData.icon)); + if (dragG) { + marker.dragging.enable(); + } - 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); - } + 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(); } - }; + } + } - var _updateMarker = function (markerData, oldMarkerData, marker, name, leafletScope, layers, map) { - if (!isDefined(oldMarkerData)) { - return; - } + // Update the Popup message property + if (!isString(markerData.message) && isString(oldMarkerData.message)) { + marker.closePopup(); + marker.unbindPopup(); + } - // 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; - } + // 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(); + } + } + } - // watch is being initialized if old and new object is the same - var isInitializing = markerData === oldMarkerData; + // 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); + } - // Update marker rotation - if (isDefined(markerData.iconAngle) && oldMarkerData.iconAngle !== markerData.iconAngle) { - marker.setIconAngle(markerData.iconAngle); - } + 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); + } - // 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); - } - } - } + // 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; + } - 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); - } + // 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; + } - 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(); + // zIndexOffset adjustment + if (oldMarkerData.zIndexOffset !== markerData.zIndexOffset) { + marker.setZIndexOffset(markerData.zIndexOffset); + } - // 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); - } + 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]); + } + }; - // 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(); - } - } + return { + resetMarkerGroup: _resetMarkerGroup, - // Update the draggable property - if (markerData.draggable !== true && oldMarkerData.draggable === true && (isDefined(marker.dragging))) { - marker.dragging.disable(); - } + resetMarkerGroups: _resetMarkerGroups, - 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(); - } - } - } + deleteMarker: _deleteMarker, - // 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); - } - } - } + manageOpenPopup: _manageOpenPopup, - 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); - } - } + manageOpenLabel: _manageOpenLabel, - // Update the Popup message property - if (!isString(markerData.message) && isString(oldMarkerData.message)) { - marker.closePopup(); - marker.unbindPopup(); - } + createMarker: function(markerData) { + if (!isDefined(markerData) || !geoHlp.validateCoords(markerData)) { + $log.error(errorHeader + 'The marker definition is not valid.'); + return; + } - // 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(); - } - } - } + var coords = geoHlp.getCoords(markerData); - // 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 (!isDefined(coords)) { + $log.error(errorHeader + 'Unable to get coordinates from markerData.'); + return; + } - 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); - } + 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, + }; - // 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; - } + // 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]; + } + } - // 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; - } + var marker = new L.marker(coords, markerOptions); - // zIndexOffset adjustment - if (oldMarkerData.zIndexOffset !== markerData.zIndexOffset) { - marker.setZIndexOffset(markerData.zIndexOffset); - } + if (!isString(markerData.message)) { + marker.unbindPopup(); + } - 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, + return marker; + }, - resetMarkerGroups: _resetMarkerGroups, + addMarkerToGroup: function(marker, groupName, groupOptions, map) { + if (!isString(groupName)) { + $log.error(errorHeader + 'The marker group you have specified is invalid.'); + return; + } - deleteMarker: _deleteMarker, + if (!MarkerClusterPlugin.isLoaded()) { + $log.error(errorHeader + 'The MarkerCluster plugin is not loaded.'); + return; + } - manageOpenPopup: _manageOpenPopup, + if (!isDefined(groups[groupName])) { + groups[groupName] = new L.MarkerClusterGroup(groupOptions); + map.addLayer(groups[groupName]); + } - manageOpenLabel: _manageOpenLabel, + groups[groupName].addLayer(marker); + }, - createMarker: function (markerData) { - if (!isDefined(markerData) || !geoHlp.validateCoords(markerData)) { - $log.error(errorHeader + 'The marker definition is not valid.'); - return; - } - var coords = geoHlp.getCoords(markerData); + 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 + } + }); + }); - if (!isDefined(coords)) { - $log.error(errorHeader + 'Unable to get coordinates from markerData.'); - return; - } + marker.on('popupclose', function(/* event */) { + safeApply(leafletScope, function() { + markerData.focus = false; + }); + }); - 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]; - } - } + marker.on('add', function(/* event */) { + safeApply(leafletScope, function() { + if ('label' in markerData) + _manageOpenLabel(marker, markerData); + }); + }); + }, - var marker = new L.marker(coords, markerOptions); + updateMarker: _updateMarker, - if (!isString(markerData.message)) { - marker.unbindPopup(); - } + addMarkerWatcher: function(marker, name, leafletScope, layers, map, isDeepWatch) { + var markerWatchPath = Helpers.getObjectArrayPath('markers.' + name); + isDeepWatch = defaultTo(isDeepWatch, true); - return marker; - }, + var clearWatch = leafletScope.$watch(markerWatchPath, function(markerData, oldMarkerData) { + if (!isDefined(markerData)) { + _deleteMarker(marker, map, layers); + clearWatch(); + return; + } - addMarkerToGroup: function (marker, groupName, groupOptions, map) { - if (!isString(groupName)) { - $log.error(errorHeader + 'The marker group you have specified is invalid.'); - return; - } + _updateMarker(markerData, oldMarkerData, marker, name, leafletScope, layers, map); + }, isDeepWatch); + }, - 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); - }, + string: _string, + log: _log, + }; +}]); - 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); - }); - }); - }, +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); + }); + } - updateMarker: _updateMarker, + function _convertToLeafletLatLng(latlng) { + if (isArray(latlng)) { + return new L.LatLng(latlng[0], latlng[1]); + } else { + return new L.LatLng(latlng.lat, latlng.lng); + } + } - addMarkerWatcher: function (marker, name, leafletScope, layers, map, isDeepWatch) { - var markerWatchPath = Helpers.getObjectArrayPath("markers." + name); - isDeepWatch = defaultTo(isDeepWatch, true); + function _convertToLeafletMultiLatLngs(paths) { + return paths.map(function(latlngs) { + return _convertToLeafletLatLngs(latlngs); + }); + } - 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 - }; -}]); + function _getOptions(path, defaults) { + var options = {}; + for (var i = 0; i < availableOptions.length; i++) { + var optionName = availableOptions[i]; -angular.module("leaflet-directive").factory('leafletPathsHelpers', ["$rootScope", "$log", "leafletHelpers", function ($rootScope, $log, leafletHelpers) { - var isDefined = leafletHelpers.isDefined, - isArray = leafletHelpers.isArray, - isNumber = leafletHelpers.isNumber, - 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); - }); + if (isDefined(path[optionName])) { + options[optionName] = path[optionName]; + } else if (isDefined(defaults.path[optionName])) { + options[optionName] = defaults.path[optionName]; + } } - function _convertToLeafletLatLng(latlng) { - if (isArray(latlng)) { - return new L.LatLng(latlng[0], latlng[1]); - } else { - return new L.LatLng(latlng.lat, latlng.lng); - } - } + return options; + } - function _convertToLeafletMultiLatLngs(paths) { - return paths.map(function(latlngs) { - return _convertToLeafletLatLngs(latlngs); - }); + 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]; + } } - function _getOptions(path, defaults) { - var options = {}; - for (var i = 0; i < availableOptions.length; i++) { - var optionName = availableOptions[i]; + path.setStyle(data); + }; - if (isDefined(path[optionName])) { - options[optionName] = path[optionName]; - } else if (isDefined(defaults.path[optionName])) { - options[optionName] = defaults.path[optionName]; - } - } + var _isValidPolyline = function(latlngs) { + if (!isArray(latlngs)) { + return false; + } - return options; + for (var i = 0; i < latlngs.length; i++) { + var point = latlngs[i]; + if (!isValidPoint(point)) { + return false; + } } - 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); - }; + return true; + }; - var _isValidPolyline = function(latlngs) { + 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; + return false; } - for (var i = 0; i < latlngs.length; i++) { - var point = latlngs[i]; - if (!isValidPoint(point)) { - 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; - 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; - } + if (!isArray(latlngs)) { + return false; + } - for (var i in latlngs) { - var polyline = latlngs[i]; - if (!_isValidPolyline(polyline)) { - 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; + 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; + } - if (!isArray(latlngs)) { - return false; - } + for (var i in latlngs) { + var point = latlngs[i]; + if (!isValidPoint(point)) { + return false; + } + } - for (var i in latlngs) { - var polyline = latlngs[i]; - if (!_isValidPolyline(polyline)) { - 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); + } - 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; + _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); + } - if (!isArray(latlngs) || latlngs.length !== 2) { - return false; - } + _updatePathOptions(path, data); + }, + }, + }; - for (var i in latlngs) { - var point = latlngs[i]; - if (!isValidPoint(point)) { - return false; - } - } + var _getPathData = function(path) { + var pathData = {}; + if (path.latlngs) { + pathData.latlngs = path.latlngs; + } - 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); - } - } - }; + if (path.radius) { + pathData.radius = path.radius; + } - var _getPathData = function(path) { - var pathData = {}; - if (path.latlngs) { - pathData.latlngs = path.latlngs; - } + return pathData; + }; - if (path.radius) { - pathData.radius = path.radius; - } + return { + setPathOptions: function(leafletPath, pathType, data) { + if (!isDefined(pathType)) { + pathType = 'polyline'; + } - return pathData; - }; + pathTypes[pathType].setPath(leafletPath, data); + }, - 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); + createPath: function(name, path, defaults) { + if (!isDefined(path.type)) { + path.type = 'polyline'; + } - if (!pathTypes[path.type].isValid(pathData)) { - $log.error("[AngularJS - Leaflet] Invalid data passed to the " + path.type + " path"); - return; - } + var options = _getOptions(path, defaults); + var pathData = _getPathData(path); - return pathTypes[path.type].createPath(options); - } - }; + 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 (){ +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); + 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; - }; + return unWatch; + }; /* @name: maybeWatch @@ -2836,8 +3232,8 @@ angular.module("leaflet-directive") @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); + var _maybeWatch = function(scope, thingToWatchStr, watchOptions, initCb) { + return _maybe(scope, '$watch', thingToWatchStr, watchOptions, initCb); }; /* @@ -2847,1253 +3243,1381 @@ angular.module("leaflet-directive") @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); + var _maybeWatchCollection = function(scope, thingToWatchStr, watchOptions, initCb) { + return _maybe(scope, '$watchCollection', thingToWatchStr, watchOptions, initCb); }; return { maybeWatch: _maybeWatch, - maybeWatchCollection: _maybeWatchCollection + 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'); - } - }); +angular.module('leaflet-directive').factory('nominatimService', ["$q", "$http", "leafletHelpers", "leafletMapDefaults", function($q, $http, leafletHelpers, leafletMapDefaults) { + var isDefined = leafletHelpers.isDefined; - return df.promise; + 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' ], +angular.module('leaflet-directive').directive('bounds', ["$log", "$timeout", "$http", "leafletHelpers", "nominatimService", "leafletBoundsHelpers", function($log, $timeout, $http, leafletHelpers, nominatimService, leafletBoundsHelpers) { - 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); - }; + 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(); + mapController.getMap().then(function(map) { + leafletScope.$on('boundsChanged', function(event) { + var scope = event.currentScope; + var bounds = map.getBounds(); - if (emptyBounds(bounds) || scope.settingBoundsFromScope) { - return; - } - 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; - } - }); + if (emptyBounds(bounds) || scope.settingBoundsFromScope) { + return; + } - var lastNominatimQuery; - leafletScope.$watch('bounds', function (bounds) { - 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; - } + 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 leafletBounds = createLeafletBounds(bounds); - if (leafletBounds && !map.getBounds().equals(leafletBounds)) { - scope.settingBoundsFromScope = true; - map.fitBounds(leafletBounds, bounds.options); - $timeout( function() { - scope.settingBoundsFromScope = false; - }); - } - }, true); + 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 + '.'); }); - } - }; -}]); -angular.module("leaflet-directive").directive('center', - ["$log", "$q", "$location", "$timeout", "leafletMapDefaults", "leafletHelpers", "leafletBoundsHelpers", "leafletEvents", function ($log, $q, $location, $timeout, leafletMapDefaults, leafletHelpers, leafletBoundsHelpers, leafletEvents) { + lastNominatimQuery = bounds.address; + $timeout(function() { + scope.settingBoundsFromScope = false; + }); - var isDefined = leafletHelpers.isDefined, - isNumber = leafletHelpers.isNumber, - isSameCenterOnMap = leafletHelpers.isSameCenterOnMap, - safeApply = leafletHelpers.safeApply, - isValidCenter = leafletHelpers.isValidCenter, - isValidBounds = leafletBoundsHelpers.isValidBounds, - isUndefinedOrEmpty = leafletHelpers.isUndefinedOrEmpty, - errorHeader = leafletHelpers.errorHeader; + 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 shouldInitializeMapWithBounds = function(bounds, center) { +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", + var _leafletCenter; + return { + restrict: 'A', scope: false, replace: false, require: 'leaflet', - controller: function () { - _leafletCenter = $q.defer(); - this.getCenter = function() { - return _leafletCenter.promise; - }; + controller: function() { + _leafletCenter = $q.defer(); + this.getCenter = function() { + return _leafletCenter.promise; + }; }, + link: function(scope, element, attrs, controller) { - var leafletScope = controller.getLeafletScope(), - centerModel = leafletScope.center; - - controller.getMap().then(function(map) { - var defaults = leafletMapDefaults.getDefaults(attrs.id); - - if (attrs.center.search("-") !== -1) { - $log.error(errorHeader + ' The "center" variable can\'t use a "-" on its key name: "' + attrs.center + '".'); - 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.center,{ - 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 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), + }; + } } - var urlCenterHash, 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.center, { - lat: urlCenter.lat, - lng: urlCenter.lng, - zoom: urlCenter.zoom - }); - } - }); + 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("center", function(center) { - //$log.debug("updated center model..."); - // The center from the URL has priority - if (isDefined(urlCenterHash)) { - angular.copy(urlCenterHash, center); - urlCenterHash = undefined; - } + leafletScope.$watch(directiveName, function(center) { + if (leafletScope.settingCenterFromLeaflet) + return; - if (!isValidCenter(center) && center.autoDiscover !== true) { - $log.warn(errorHeader + " invalid 'center'"); - //map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); - return; - } + //$log.debug("updated center model..."); + // The center from the URL has priority + if (isDefined(urlCenterHash)) { + angular.copy(urlCenterHash, center); + urlCenterHash = undefined; + } - 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 (!isValidCenter(center) && center.autoDiscover !== true) { + $log.warn(errorHeader + ' invalid \'center\''); - if (mapReady && isSameCenterOnMap(center, map)) { - //$log.debug("no need to update map again."); - return; - } + //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, + }); + } - //$log.debug("updating map center...", center); - leafletScope.settingCenterFromScope = true; - map.setView([center.lat, center.lng], center.zoom); - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - $timeout(function() { - leafletScope.settingCenterFromScope = false; - //$log.debug("allow center scope updates"); - }); - }, true); + return; + } - map.whenReady(function() { - mapReady = true; - }); + if (mapReady && isSameCenterOnMap(center, map)) { + //$log.debug("no need to update map again."); + return; + } - map.on('moveend', function(/* event */) { - // Resolve the center after the first map position - _leafletCenter.resolve(); - leafletEvents.notifyCenterUrlHashChanged(leafletScope, map, attrs, $location.search()); - //$log.debug("updated center on map..."); - if (isSameCenterOnMap(centerModel, map) || scope.settingCenterFromScope) { - //$log.debug("same center in model, no need to update again."); - return; - } - safeApply(leafletScope, function(scope) { - if (!leafletScope.settingCenterFromScope) { - //$log.debug("updating center model...", map.getCenter(), map.getZoom()); - angular.extend(scope.center,{ - lat: map.getCenter().lat, - lng: map.getCenter().lng, - zoom: map.getZoom(), - autoDiscover: false - }); - } - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - }); + //$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); - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - } else { - map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - } - }); + 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('controls', ["$log", "leafletHelpers", "leafletControlHelpers", function ($log, leafletHelpers, leafletControlHelpers) { - return { - restrict: "A", - scope: false, - replace: false, - require: '?^leaflet', +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; - link: function(scope, element, attrs, controller) { - if(!controller) { - return; + 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); } + }; - var createControl = leafletControlHelpers.createControl; - var isValidControlType = leafletControlHelpers.isValidControlType; - var leafletScope = controller.getLeafletScope(); - var isDefined = leafletHelpers.isDefined; - 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]; - } - } + if (isNested) { + $it.each(leafletGeoJSON, function(lObject) { + _remove(lObject); + }); + + return; + } - for (var newName in newControls) { - var control; + _remove(leafletGeoJSON); + }; - var controlType = isDefined(newControls[newName].type) ? newControls[newName].type : newName; + 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, + }; + } - if (!isValidControlType(controlType)) { - $log.error(errorHeader + ' Invalid control type: ' + controlType + '.'); - return; - } + var lObject = L.geoJson(geojson.data, geojson.options); - if (controlType !== 'custom') { - control = createControl(controlType, newControls[newName]); - } else { - control = newControls[newName]; - } - map.addControl(control); + if (maybeName && hlp.isString(maybeName)) { + leafletGeoJSON[maybeName] = lObject; + } else { + leafletGeoJSON = lObject; + } - leafletControls[newName] = control; - } + 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); }); - } - }; -}]); -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(), - PolylineDecoratorPlugin = leafletHelpers.PolylineDecoratorPlugin, - isDefined = leafletHelpers.isDefined, - 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], - newDecoration = createDecoration(decorationData); - - if (isDefined(newDecoration)) { - leafletDecorations[newName] = newDecoration; - map.addLayer(newDecoration); - setDecorationOptions(newDecoration, decorationData); - } - } - }, true); - }); - } - }; + return; + } + + _addGeojson(model); + }; + + _extendDirectiveControls(attrs.id, 'geojson', _create, _clean); + + _maybeWatch(leafletScope, 'geojson', watchOptions, function(geojson) { + _create(geojson); + }); + }); + }, + }; }]); -angular.module("leaflet-directive").directive('eventBroadcast', ["$log", "$rootScope", "leafletHelpers", "leafletEvents", "leafletIterators", function ($log, $rootScope, leafletHelpers, leafletEvents, leafletIterators) { - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', +angular.module('leaflet-directive').directive('layercontrol', ["$filter", "$log", "leafletData", "leafletHelpers", function($filter, $log, leafletData, leafletHelpers) { - link: function(scope, element, attrs, controller) { - var isObject = leafletHelpers.isObject, - isDefined = leafletHelpers.isDefined, - leafletScope = controller.getLeafletScope(), - eventBroadcast = leafletScope.eventBroadcast, - availableMapEvents = leafletEvents.getAvailableMapEvents(), - addEvents = leafletEvents.addEvents; - - controller.getMap().then(function(map) { - - var mapEvents = [], - 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; - } + 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; + }); + }); + }); - 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); - } - }); - } + e.preventDefault(); + }, - } - // 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); - }); - } - }; -}]); + 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; + } + } -angular.module("leaflet-directive") -.directive('geojson', ["$log", "$rootScope", "leafletData", "leafletHelpers", "leafletWatchHelpers", "leafletDirectiveControlsHelpers", "leafletIterators", "leafletGeoJsonEvents", function ($log, $rootScope, leafletData, leafletHelpers, - leafletWatchHelpers, leafletDirectiveControlsHelpers,leafletIterators, - leafletGeoJsonEvents) { + if (oldLy) { + safeApply($scope, function() { + oldLy.index = ly.index; + ly.index = newIndex; + }); + } + } - var _maybeWatch = leafletWatchHelpers.maybeWatch, - _watchOptions = leafletHelpers.watchOptions, - _extendDirectiveControls = leafletDirectiveControlsHelpers.extend, - hlp = leafletHelpers, - $it = leafletIterators; + e.stopPropagation(); + e.preventDefault(); + }, - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', + initIndex: function(layer, idx) { + var delta = Object.keys($scope.layers.baselayers).length; + layer.index = isDefined(layer.index) ? layer.index : idx + delta + 1; + }, - link: function(scope, element, attrs, controller) { - var isDefined = leafletHelpers.isDefined, - leafletScope = controller.getLeafletScope(), - leafletGeoJSON = {}, - _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(layer, null, feature, - leafletScope, maybeName, - {resetStyleOnMouseout: geojson.resetStyleOnMouseout, - mapId: attrs.id}); - }; - } - return onEachFeature; - }; + initGroup: function(groupName) { + $scope.groupProperties[groupName] = $scope.groupProperties[groupName] ? $scope.groupProperties[groupName] : {}; + }, - var isNested = (hlp.isDefined(attrs.geojsonNested) && - hlp.isTruthy(attrs.geojsonNested)); + 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; + } + } - 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); - }; + $scope.layerProperties[layer.name].opacityControl = !$scope.layerProperties[layer.name].opacityControl; + } - 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 - }; - } + e.stopPropagation(); + e.preventDefault(); + }, - var lObject = L.geoJson(geojson.data, geojson.options); + toggleLegend: function(layer) { + $scope.layerProperties[layer.name].showLegend = !$scope.layerProperties[layer.name].showLegend; + }, - if(maybeName && hlp.isString(maybeName)){ - leafletGeoJSON[maybeName] = lObject; - } - else{ - leafletGeoJSON = lObject; - } + showLegend: function(layer) { + return layer.legend && $scope.layerProperties[layer.name].showLegend; + }, - lObject.addTo(map); + unsafeHTML: function(html) { + return $sce.trustAsHtml(html); + }, - if(!_hasSetLeafletData){//only do this once and play with the same ref forever - _hasSetLeafletData = true; - leafletData.setGeoJSON(leafletGeoJSON, attrs.id); - } - }; + getOpacityIcon: function(layer) { + return layer.visible && $scope.layerProperties[layer.name].opacityControl ? $scope.icons.close : $scope.icons.open; + }, - 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); - }; + getGroupIcon: function(group) { + return group.visible ? $scope.icons.check : $scope.icons.uncheck; + }, - _extendDirectiveControls(attrs.id, 'geojson', _create, _clean); + 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; + } + } - _maybeWatch(leafletScope,'geojson', watchOptions, function(geojson){ - _create(geojson); - }); - }); - } - }; -}]); + if (map.hasLayer(ly)) { + if (ly.setOpacity) { + ly.setOpacity(op / 100); + } -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, - 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; - } + if (ly.getLayers && ly.eachLayer) { + ly.eachLayer(function(lay) { + if (lay.setOpacity) { + lay.setOpacity(op / 100); } + }); } + } }); + }); + }, - 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); + 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; } - }], - template: - '
' + - '

{{ title }}

' + - '
' + - '
{{ baseTitle }}
' + - '
' + - '
";for(var g=0;g
'+h.label+"
"}}else"image"===c&&(a.innerHTML='')},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.labels[d]+"
";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:'© OpenStreetMap 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.MakiMarkersPlugin,l=c.ExtraMarkersPlugin,m=c.safeApply,n=c,o=c.isString,p=c.isNumber,q=c.isObject,r={},s=f,t=c.errorHeader,u=function(a){var b="";return["_icon","_latlng","_leaflet_id","_map","_shadow"].forEach(function(c){b+=c+": "+h(a[c],"undefined")+" \n"}),"[leafletMarker] : \n"+b},v=function(a,b){var c=b?console:d;c.debug(u(a))},w=function(a){if(g(a)&&g(a.type)&&"awesomeMarker"===a.type)return j.isLoaded()||d.error(t+" The AwesomeMarkers Plugin is not loaded."),new L.AwesomeMarkers.icon(a);if(g(a)&&g(a.type)&&"makiMarker"===a.type)return k.isLoaded()||d.error(t+"The MakiMarkers Plugin is not loaded."),new L.MakiMarkers.icon(a);if(g(a)&&g(a.type)&&"extraMarker"===a.type)return l.isLoaded()||d.error(t+"The ExtraMarkers Plugin is not loaded."),new L.ExtraMarkers.icon(a);if(g(a)&&g(a.type)&&"div"===a.type)return new L.divIcon(a);if(g(a)&&g(a.type)&&"icon"===a.type)return a.icon;var b="data:image/png;base64,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",c="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(a)&&g(a.iconUrl)?new L.Icon(a):new L.Icon.Default({iconUrl:b,shadowUrl:c,iconSize:[25,41],iconAnchor:[12,41],popupAnchor:[1,-34],shadowSize:[41,41]})},x=function(a){g(r[a])&&r.splice(a,1)},y=function(){r={}},z=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(r))for(var e in r)r[e].hasLayer(a)&&r[e].removeLayer(a);b.hasLayer(a)&&b.removeLayer(a)},A=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()},B=function(a,b){e(a._popup._contentNode)(b)},C=function(a,c,d){var e=a._popup._contentNode.innerText||a._popup._contentNode.textContent;e.length<1&&b(function(){C(a,c,d)});var f=a._popup._contentNode.offsetWidth;return a._popup._updateLayout(),a._popup._updatePosition(),a._popup.options.autoPan&&A(a,d),f},D=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(t+"Popup is invalid or does not have any content."),!1;B(b,f),C(b,c,e)}},E=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;n.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))},F=function(a,b,c,e,f,h,i){if(g(b)){if(!s.validateCoords(a))return d.warn("There are problems with lat-lng data, please verify your marker model"),void z(c,i,h);var j=a===b;if(g(a.iconAngle)&&b.iconAngle!==a.iconAngle&&c.setIconAngle(a.iconAngle),o(a.layer)||o(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)),(p(a.opacity)||p(parseFloat(a.opacity)))&&a.opacity!==b.opacity&&c.setOpacity(a.opacity),o(a.layer)&&b.layer!==a.layer){if(o(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(t+"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(t+'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())),q(a.icon)||q(b.icon)&&(c.setIcon(w()),c.closePopup(),c.unbindPopup(),o(a.message)&&c.bindPopup(a.message,a.popupOptions)),q(a.icon)&&q(b.icon)&&!angular.equals(a.icon,b.icon)){var l=!1;c.dragging&&(l=c.dragging.enabled()),c.setIcon(w(a.icon)),l&&c.dragging.enable(),c.closePopup(),c.unbindPopup(),o(a.message)&&c.bindPopup(a.message,a.popupOptions)}!o(a.message)&&o(b.message)&&(c.closePopup(),c.unbindPopup()),n.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),E(c,a)):E(c,a):(!("label"in a)||"message"in a.label)&&angular.isFunction(c.unbindLabel)&&c.unbindLabel()),o(a.message)&&!o(b.message)&&c.bindPopup(a.message,a.popupOptions),o(a.message)&&o(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 r=c.getLatLng(),u=o(a.layer)&&n.MarkerClusterPlugin.is(h.overlays[a.layer]);u?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)):r.lat!==a.lat||r.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)):q(a.icon)&&q(b.icon)&&!angular.equals(a.icon,b.icon)&&(h.overlays[a.layer].removeLayer(c),h.overlays[a.layer].addLayer(c)):(r.lat!==a.lat||r.lng!==a.lng)&&c.setLatLng([a.lat,a.lng])}};return{resetMarkerGroup:x,resetMarkerGroups:y,deleteMarker:z,manageOpenPopup:D,manageOpenLabel:E,createMarker:function(a){if(!g(a)||!s.validateCoords(a))return void d.error(t+"The marker definition is not valid.");var b=s.getCoords(a);if(!g(b))return void d.error(t+"Unable to get coordinates from markerData.");var c={icon:w(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 o(a.message)||f.unbindPopup(),f},addMarkerToGroup:function(a,b,c,e){return o(b)?i.isLoaded()?(g(r[b])||(r[b]=new L.MarkerClusterGroup(c),e.addLayer(r[b])),void r[b].addLayer(a)):void d.error(t+"The MarkerCluster plugin is not loaded."):void d.error(t+"The marker group you have specified is invalid.")},listenMarkerEvents:function(a,b,c,d,e){a.on("popupopen",function(){m(c,function(){(g(a._popup)||g(a._popup._contentNode))&&(b.focus=!0,D(a,b,e))})}),a.on("popupclose",function(){m(c,function(){b.focus=!1})}),a.on("add",function(){m(c,function(){"label"in b&&E(a,b)})})},updateMarker:F,addMarkerWatcher:function(a,b,c,d,e,f){var i=n.getObjectArrayPath("markers."+b);f=h(f,!0);var j=c.$watch(i,function(f,h){return g(f)?void F(f,h,a,b,c,d,e):(z(a,e,d),void j())},f)},string:u,log:v}}]),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;d0&&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 b=a.currentScope,c=d.getBounds();if(!o(c)&&!b.settingBoundsFromScope){var e={northEast:{lat:c._northEast.lat,lng:c._northEast.lng},southWest:{lat:c._southWest.lat,lng:c._southWest.lng},options:c.options};angular.equals(b.bounds,e)||(b.bounds=e)}});var f;l.$watch("bounds",function(g){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)})}}}]),angular.module("leaflet-directive").directive("center",["$log","$q","$location","$timeout","leafletMapDefaults","leafletHelpers","leafletBoundsHelpers","leafletEvents",function(a,b,c,d,e,f,g,h){var i,j=f.isDefined,k=f.isNumber,l=f.isSameCenterOnMap,m=f.safeApply,n=f.isValidCenter,o=g.isValidBounds,p=f.isUndefinedOrEmpty,q=f.errorHeader,r=function(a,b){return j(a)&&o(a)&&p(b)};return{restrict:"A",scope:!1,replace:!1,require:"leaflet",controller:function(){i=b.defer(),this.getCenter=function(){return i.promise}},link:function(b,f,o,p){var s=p.getLeafletScope(),t=s.center;p.getMap().then(function(f){var p=e.getDefaults(o.id);if(-1!==o.center.search("-"))return a.error(q+' The "center" variable can\'t use a "-" on its key name: "'+o.center+'".'),void f.setView([p.center.lat,p.center.lng],p.center.zoom);if(r(s.bounds,t))f.fitBounds(g.createLeafletBounds(s.bounds),s.bounds.options),t=f.getCenter(),m(s,function(a){angular.extend(a.center,{lat:f.getCenter().lat,lng:f.getCenter().lng,zoom:f.getZoom(),autoDiscover:!1})}),m(s,function(a){var b=f.getBounds();a.bounds={northEast:{lat:b._northEast.lat,lng:b._northEast.lng},southWest:{lat:b._southWest.lat,lng:b._southWest.lng}}});else{if(!j(t))return a.error(q+' The "center" property is not defined in the main scope'),void f.setView([p.center.lat,p.center.lng],p.center.zoom);j(t.lat)&&j(t.lng)||j(t.autoDiscover)||angular.copy(p.center,t)}var u,v;if("yes"===o.urlHashCenter){var w=function(){var a,b=c.search();if(j(b.c)){var d=b.c.split(":");3===d.length&&(a={lat:parseFloat(d[0]),lng:parseFloat(d[1]),zoom:parseInt(d[2],10)})}return a};u=w(),s.$on("$locationChangeSuccess",function(a){var b=a.currentScope,c=w();j(c)&&!l(c,f)&&angular.extend(b.center,{lat:c.lat,lng:c.lng,zoom:c.zoom})})}s.$watch("center",function(b){return j(u)&&(angular.copy(u,b),u=void 0),n(b)||b.autoDiscover===!0?b.autoDiscover===!0?(k(b.zoom)||f.setView([p.center.lat,p.center.lng],p.center.zoom),void(k(b.zoom)&&b.zoom>p.center.zoom?f.locate({setView:!0,maxZoom:b.zoom}):j(p.maxZoom)?f.locate({setView:!0,maxZoom:p.maxZoom}):f.locate({setView:!0}))):void(v&&l(b,f)||(s.settingCenterFromScope=!0,f.setView([b.lat,b.lng],b.zoom),h.notifyCenterChangedToBounds(s,f),d(function(){s.settingCenterFromScope=!1}))):void a.warn(q+" invalid 'center'")},!0),f.whenReady(function(){v=!0}),f.on("moveend",function(){i.resolve(),h.notifyCenterUrlHashChanged(s,f,o,c.search()),l(t,f)||b.settingCenterFromScope||m(s,function(a){s.settingCenterFromScope||angular.extend(a.center,{lat:f.getCenter().lat,lng:f.getCenter().lng,zoom:f.getZoom(),autoDiscover:!1}),h.notifyCenterChangedToBounds(s,f)})}),t.autoDiscover===!0&&f.on("locationerror",function(){a.warn(q+" The Geolocation API is unauthorized on this page."),n(t)?(f.setView([t.lat,t.lng],t.zoom),h.notifyCenterChangedToBounds(s,f)):(f.setView([p.center.lat,p.center.lng],p.center.zoom),h.notifyCenterChangedToBounds(s,f))})})}}}]),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={},m=b.errorHeader+" [Controls] ";g.getMap().then(function(b){j.$watchCollection("controls",function(c){for(var d in l)k(c[d])||(b.hasControl(l[d])&&b.removeControl(l[d]),delete l[d]);for(var e in c){var f,g=k(c[e].type)?c[e].type:e;if(!i(g))return void a.error(m+" Invalid control type: "+g+".");f="custom"!==g?h(g,c[e]):c[e],b.addControl(f),l[e]=f}})})}}}}]),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","leafletEvents","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(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:'

{{ title }}

{{ baseTitle }}
{{ overlaysTitle }}
Range is not supported in this browser
',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=f.updateLayersControl,o=!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&&(b.addLayer(j.baselayers[f]),e=!0)):delete l.baselayers[f]}!e&&Object.keys(j.baselayers).length>0&&b.addLayer(j.baselayers[Object.keys(l.baselayers)[0]]);for(f in l.overlays){"cartodb"===l.overlays[f].type;var p=m(l.overlays[f]);i(p)?(j.overlays[f]=p,l.overlays[f].visible===!0&&b.addLayer(j.overlays[f])):delete l.overlays[f]}k.$watch("layers.baselayers",function(a,c){if(angular.equals(a,c))return o=n(b,d,o,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]):b.addLayer(j.baselayers[f]);else{var g=m(a[f]);i(g)&&(j.baselayers[f]=g,a[f].top===!0&&b.addLayer(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&&b.addLayer(j.baselayers[Object.keys(j.baselayers)[0]]),o=n(b,d,o,a,l.overlays,j)},!0),k.$watch("layers.overlays",function(a,c){if(angular.equals(a,c))return o=n(b,d,o,l.baselayers,a,j),!0;for(var e in j.overlays)(!i(a[e])||a[e].doRefresh)&&(b.hasLayer(j.overlays[e])&&b.removeLayer(j.overlays[e]),delete j.overlays[e],a[e]&&a[e].doRefresh&&(a[e].doRefresh=!1));for(var f in a){if(!i(j.overlays[f])){var g=m(a[f]);if(!i(g))continue;j.overlays[f]=g,a[f].visible===!0&&b.addLayer(j.overlays[f])}a[f].visible&&!b.hasLayer(j.overlays[f])?b.addLayer(j.overlays[f]):a[f].visible===!1&&b.hasLayer(j.overlays[f])&&b.removeLayer(j.overlays[f]),a[f].visible&&b._loaded&&a[f].data&&"heatmap"===a[f].type&&(j.overlays[f].setData(a[f].data),j.overlays[f].update())}o=n(b,d,o,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){for(var o in b)if(!k[o])if(-1===o.search("-")){var u=n.copy(b[o]),v=n.getObjectDotPath(j?[j,o]:[o]),w=z(f,o,j);if(l(w)){var x=l(x)?c[o]:void 0;q(u,x,w,v,g,e,d)}else{var y=t(u),C=(u?u.layer:void 0)||j;if(!l(y)){a.error(m+" Received invalid data on the marker "+o+".");continue}if(A(y,f,o,j),l(u.message)&&y.bindPopup(u.message,u.popupOptions),l(u.group)){var D=l(u.groupOption)?u.groupOption:null;s(y,u.group,D,d)}if(n.LabelPlugin.isLoaded()&&l(u.label)&&l(u.label.message)&&y.bindLabel(u.label.message,u.label.options),l(u)&&(l(u.layer)||l(j))){var E=B(C,e,u,y,i.individual.doWatch,d);if(!E)continue}else l(u.group)||(d.addLayer(y),i.individual.doWatch||u.focus!==!0||y.openPopup());i.individual.doWatch&&p(y,v,g,e,d,i.individual.isDeep),r(y,u,g,i.individual.doWatch,d),h.bindEvents(y,v,u,g,C)}}else a.error('The marker can\'t use a "-" on his key name: "'+o+'".')},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,e){c(d,e);var f=null;return j?void v.each(d,function(c,j){var k=l(k)?e[j]:void 0;f=F(d[j],k,g[j]),C(c,e,a,b,g,h,i,j,f)}):(f=F(d,e,g),void C(d,e,a,b,g,h,i,void 0,f))};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||a.fitBounds(d)})})}}}]),angular.module("leaflet-directive").directive("paths",["$log","$q","leafletData","leafletMapDefaults","leafletHelpers","leafletPathsHelpers","leafletEvents",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 j in d)m(c[j])||(f.removeLayer(d[j]),delete d[j]);for(var k in c)if(0!==k.search("\\$"))if(-1===k.search("-")){if(!m(d[k])){var l=c[k],p=q(k,c[k],h);if(m(p)&&m(l.message)&&p.bindPopup(l.message,l.popupOptions),e.LabelPlugin.isLoaded()&&m(l.label)&&m(l.label.message)&&p.bindLabel(l.label.message,l.label.options),m(l)&&m(l.layer)){if(!n(l.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[l.layer])){a.error('[AngularJS - Leaflet] A marker can only be added to a layer of type "group"');continue}var t=b.overlays[l.layer];if(!(t instanceof L.LayerGroup||t instanceof L.FeatureGroup)){a.error('[AngularJS - Leaflet] Adding a marker to an overlay needs a overlay of the type "group" or "featureGroup"');continue}d[k]=p,t.addLayer(p),g?i(p,k):s(p,l.type,l)}else m(p)&&(d[k]=p,f.addLayer(p),g?i(p,k):s(p,l.type,l));r(p,k,l,o)}}else a.error('[AngularJS - Leaflet] The path name "'+k+'" 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){var f=e.tileLayerOptions,h=e.tileLayer;return!i(c.url)&&i(d)?void a.removeLayer(d):i(d)?i(c.url)&&i(c.options)&&!angular.equals(c.options,f)?(a.removeLayer(d),f=e.tileLayerOptions,angular.copy(c.options,f),h=c.url,d=L.tileLayer(h,f),d.addTo(a),void b.setTiles(d,g.id)):void(i(c.url)&&d.setUrl(c.url)):(i(c.options)&&angular.copy(c.options,f),i(c.url)&&(h=c.url),d=L.tileLayer(h,f),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,this.lObjectType=b};return j.prototype.getAvailableEvents=function(){return[]},j.prototype.genDispatchEvent=function(a,b,c,d,e,f,g,h){var i=this;return function(j){var k=i.rootBroadcastName+"."+a;i.fire(c,k,b,j,j.target||d,f,e,g,h)}},j.prototype.fire=function(b,c,d,g,h,i,j,k,l){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){var l=[],m="emit",n=this;if(f(e.eventBroadcast))if(g(e.eventBroadcast))if(f(e.eventBroadcast[n.lObjectType]))if(g(e.eventBroadcast[n.lObjectType])){f(e.eventBroadcast[this.lObjectType].logic)&&"emit"!==e.eventBroadcast[n.lObjectType].logic&&"broadcast"!==e.eventBroadcast[n.lObjectType].logic&&c.warn(i+"Available event propagation logic are: 'emit' or 'broadcast'.");var o=!1,p=!1;f(e.eventBroadcast[n.lObjectType].enable)&&h(e.eventBroadcast[n.lObjectType].enable)&&(o=!0),f(e.eventBroadcast[n.lObjectType].disable)&&h(e.eventBroadcast[n.lObjectType].disable)&&(p=!0),o&&p?c.warn(i+"can not enable and disable events at the same time"):o||p?o?e.eventBroadcast[this.lObjectType].enable.forEach(function(a){-1!==l.indexOf(a)?c.warn(i+"This event "+a+" is already enabled"):-1===n.getAvailableEvents().indexOf(a)?c.warn(i+"This event "+a+" does not exist"):l.push(a)}):(l=this.getAvailableEvents(),e.eventBroadcast[n.lObjectType].disable.forEach(function(a){var b=l.indexOf(a);-1===b?c.warn(i+"This event "+a+" does not exist or has been already disabled"):l.splice(b,1)})):c.warn(i+"must enable or disable events")}else c.warn(i+"event-broadcast."+[n.lObjectType]+" must be an object check your model.");else l=this.getAvailableEvents();else c.error(i+"event-broadcast must be an object check your model.");else l=this.getAvailableEvents();return l.forEach(function(c){a.on(c,n.genDispatchEvent(c,m,e,a,b,d,j,k))}),m},j}]).service("leafletEventsHelpers",["leafletEventsHelpersFactory",function(a){return new a}]),angular.module("leaflet-directive").factory("leafletGeoJsonEvents",["$rootScope","$q","$log","leafletHelpers","leafletEventsHelpersFactory","leafletLabelEvents","leafletData",function(a,b,c,d,e,f,g){var h=d.safeApply,i=(d.isDefined,e),j=function(){i.call(this,"leafletDirectiveGeoJson","geojson")};return j.prototype=new i,j.prototype.genDispatchEvent=function(b,c,d,e,f,j,k,l){var m=i.prototype.genDispatchEvent.call(this,b,c,d,e,f,j,k),n=this;return function(c){"mouseout"===b&&(l.resetStyleOnMouseout&&g.getGeoJSON(l.mapId).then(function(a){var b=k?a[k]:a;b.resetStyle(c.target)}),h(d,function(){a.$broadcast(n.rootBroadcastName+".mouseout",c)})),m(c)}},j.prototype.getAvailableEvents=function(){return["click","dblclick","mouseover","mouseout"]},new j}]),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){var i=e.replace("markers.","");return g.prototype.genDispatchEvent.call(this,a,b,c,d,i,f,h)},h.prototype.getAvailableEvents=function(){return["click","dblclick","mousedown","mouseover","mouseout","contextmenu"]},h.prototype.genEvents=function(a,b,c,d,e,g,h){var i=this,j=this.getAvailableEvents(),k=f.getObjectArrayPath("markers."+e);j.forEach(function(a){d.label.on(a,i.genDispatchEvent(a,b,c,d.label,k,g,h))})},h.prototype.bindEvents=function(a,b,c,d,e){},new h}]),angular.module("leaflet-directive").factory("leafletMapEvents",["$rootScope","$q","$log","leafletHelpers","leafletEventsHelpers",function(a,b,c,d,e){var f=(d.safeApply,d.isDefined),g=(d.isObject,d.errorHeader,e.fire),h=function(){return["click","dblclick","mousedown","mouseup","mouseover","mouseout","mousemove","contextmenu","focus","blur","preclick","load","unload","viewreset","movestart","move","moveend","dragstart","drag","dragend","zoomstart","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"]},i=function(a,b,c){return function(d){var e="leafletDirectiveMap."+b;g(a,e,c,d,d.target,a)}},j=function(a){a.$broadcast("boundsChanged")},k=function(a,b,c,d){if(f(c.urlHashCenter)){var e=b.getCenter(),g=e.lat.toFixed(4)+":"+e.lng.toFixed(4)+":"+b.getZoom();f(d.c)&&d.c===g||a.$emit("centerUrlHash",g)}};return{getAvailableMapEvents:h,genDispatchMapEvent:i,notifyCenterChangedToBounds:j,notifyCenterUrlHashChanged:k}}]),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){var j=k.prototype.genDispatchEvent.call(this,b,c,d,e,f,h,i);return function(c){"click"===b?g(d,function(){a.$broadcast("leafletDirectiveMarkersClick",f)}):"dragend"===b&&(g(d,function(){h.lat=e.getLatLng().lat,h.lng=e.getLatLng().lng}),h.message&&h.focus===!0&&e.openPopup()),j(c)}},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){var f=k.prototype.bindEvents.call(this,a,b,c,d,e);i.LabelPlugin.isLoaded()&&h(a.label)&&j.genEvents(b,f,d,a,c,e)},new l}]),angular.module("leaflet-directive").factory("leafletPathEvents",["$rootScope","$q","$log","leafletHelpers","leafletLabelEvents","leafletEventsHelpers",function(a,b,c,d,e,f){var g=(d.safeApply,d.isDefined),h=d.isObject,i=d,j=d.errorHeader,k=e,l=f.fire,m=function(a,b,c,d,e,f,g){return function(h){var i="leafletDirectivePath."+a;l(c,i,b,h,h.target||d,f,e,g)}},n=function(a,b,d,e){var f,l,n=[],p="broadcast";if(g(e.eventBroadcast))if(h(e.eventBroadcast))if(g(e.eventBroadcast.path))if(h(e.eventBroadcast.paths))c.warn(j+"event-broadcast.path must be an object check your model.");else{void 0!==e.eventBroadcast.path.logic&&null!==e.eventBroadcast.path.logic&&("emit"!==e.eventBroadcast.path.logic&&"broadcast"!==e.eventBroadcast.path.logic?c.warn(j+"Available event propagation logic are: 'emit' or 'broadcast'."):"emit"===e.eventBroadcast.path.logic&&(p="emit"));var q=!1,r=!1;if(void 0!==e.eventBroadcast.path.enable&&null!==e.eventBroadcast.path.enable&&"object"==typeof e.eventBroadcast.path.enable&&(q=!0),void 0!==e.eventBroadcast.path.disable&&null!==e.eventBroadcast.path.disable&&"object"==typeof e.eventBroadcast.path.disable&&(r=!0),q&&r)c.warn(j+"can not enable and disable events at the same time");else if(q||r)if(q)for(f=0;f
',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'+b.error.message+"";else if("arcgis"===c)for(var e=0;e'+f.layerName+"";for(var g=0;g
'+h.label+"
"}}else"image"===c&&(a.innerHTML='')},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.labels[d]+"
";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:'© OpenStreetMap 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,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",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;d0&&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:'

{{ title }}

{{ baseTitle }}
{{ overlaysTitle }}
Range is not supported in this browser
',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
', + 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 += '
' + legendData.error.message + '
'; + } else { + if (type === 'arcgis') { + for (var i = 0; i < legendData.layers.length; i++) { + var layer = legendData.layers[i]; + div.innerHTML += '
' + layer.layerName + '
'; + for (var j = 0; j < layer.legend.length; j++) { + var leg = layer.legend[j]; + div.innerHTML += + '
' + + '
' + leg.label + '
'; + } + } + } else if (type === 'image') { + div.innerHTML = ''; + } + } + }; + + 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 += + '
' + + '
' + legend.labels[i] + '
'; + } + + 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: '© OpenStreetMap 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,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'; + 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: + '
' + + '

{{ title }}

' + + '
' + + '
{{ baseTitle }}
' + + '
' + + '' + + '
' + + '
' + + '
' + + '
{{ overlaysTitle }}
' + + '
' + + '
' + + '' + + '' + + '
' + + ' ' + + ' ' + + ' ' + + '' + + '
' + + '
' + + '
' + + '' + + '' + + '' + + '
Range is not supported in this browser
' + + '
' + + '
' + + '
' + + '
' + + '
', + 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)); \ No newline at end of file diff --git a/dist/angular-leaflet-directive_dev_mapped.js b/dist/angular-leaflet-directive_dev_mapped.js deleted file mode 100644 index 7c4d3cba..00000000 --- a/dist/angular-leaflet-directive_dev_mapped.js +++ /dev/null @@ -1,5146 +0,0 @@ -/*! -* angular-leaflet-directive 0.8.6 2015-07-28 -* 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', - function ($q, leafletData, leafletMapDefaults, leafletHelpers, leafletEvents) { - return { - restrict: "EA", - replace: true, - scope: { - center : '=', - defaults : '=', - maxbounds : '=', - bounds : '=', - markers : '=', - legend : '=', - geojson : '=', - paths : '=', - tiles : '=', - layers : '=', - controls : '=', - decorations : '=', - eventBroadcast : '=', - markersWatchOptions : '=', - geojsonWatchOptions : '=' - }, - transclude: true, - template: '
', - controller: 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, - defaults = leafletMapDefaults.setDefaults(scope.defaults, attrs.id), - mapEvents = leafletEvents.getAvailableMapEvents(), - addEvents = leafletEvents.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)) { - 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', function ($log, leafletHelpers) { - - var isArray = leafletHelpers.isArray, - isNumber = leafletHelpers.isNumber, - isFunction = leafletHelpers.isFunction, - 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(), - southWest = lfBounds.getSouthWest(); - - return { - northEast: { - lat: northEast.lat, - lng: northEast.lng - }, - southWest: { - lat: southWest.lat, - lng: southWest.lng - } - }; - } - }; -}); - -angular.module("leaflet-directive").factory('leafletControlHelpers', 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); - } - }, - 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', 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', function ($log, leafletData, leafletHelpers) { - var _isDefined = leafletHelpers.isDefined, - _isString = leafletHelpers.isString, - _isObject = leafletHelpers.isObject, - _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").factory('leafletEvents', - function (leafletMapEvents, leafletMarkerEvents, leafletPathEvents, leafletIterators) { - //NOTE THIS SHOULD BE DEPRECATED infavor of getting a specific events helper - var instance = angular.extend({}, - leafletMapEvents, { - bindMarkerEvents: leafletMarkerEvents.bindEvents, - getAvailableMarkerEvents: leafletMarkerEvents.getAvailableEvents - }, leafletPathEvents); - - var genDispatchMapEvent = instance.genDispatchMapEvent; - - instance.addEvents = function(map, mapEvents, contextName, scope, logic){ - leafletIterators.each(mapEvents, function(eventName) { - var context = {}; - context[contextName] = eventName; - map.on(eventName, genDispatchMapEvent(scope, eventName, logic), context); - }); - }; - - return instance; -}); - -angular.module("leaflet-directive") -.service('leafletGeoJsonHelpers', function (leafletHelpers, leafletIterators) { - var lHlp = leafletHelpers, - 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").factory('leafletHelpers', 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, 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 if (Object.keys(d).length === 0) { - id = "main"; - } 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), - 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); - }; - - return { - 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), - 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; - } - } - }, - - 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; - } - } - }, - 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', function ($log, leafletHelpers) { - - var lHlp = leafletHelpers, - 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], - keys = keysFunc(source), - 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, _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), 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, _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, _all = null; - _every = _all = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !_isArrayLike(obj) && _keys(obj), - 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){ - 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', function ($rootScope, $log, 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); - } - }, - 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 && 'string' === typeof options.crs) { - /*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)); - }); - 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); - } - }, - 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; - - return L.esri.featureLayer(params.options); - } - }, - 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); - } - }, - - // 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, - 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); - } - - return { - createLayer: createLayer - }; -}); - -angular.module("leaflet-directive").factory('leafletLegendHelpers', function () { - var _updateLegend = function(div, legendData, type, url) { - div.innerHTML = ''; - if(legendData.error) { - div.innerHTML += '
' + legendData.error.message + '
'; - } else { - if (type === 'arcgis') { - for (var i = 0; i < legendData.layers.length; i++) { - var layer = legendData.layers[i]; - div.innerHTML += '
' + layer.layerName + '
'; - for(var j = 0; j < layer.legend.length; j++) { - var leg = layer.legend[j]; - div.innerHTML += - '
' + - '
' + leg.label + '
'; - } - } - } - else if (type === 'image') { - div.innerHTML = ''; - } - } - }; - - 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 += - '
' + - '
' + legend.labels[i] + '
'; - } - 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', 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: '© OpenStreetMap contributors' - }, - path: { - weight: 10, - opacity: 1, - color: '#0000ff' - }, - center: { - lat: 0, - lng: 0, - zoom: 1 - } - }; - } - - var isDefined = leafletHelpers.isDefined, - isObject = leafletHelpers.isObject, - obtainEffectiveMapId = leafletHelpers.obtainEffectiveMapId, - 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', function ($rootScope, $timeout, leafletHelpers, $log, $compile, leafletGeoJsonHelpers) { - var isDefined = leafletHelpers.isDefined, - defaultTo = leafletHelpers.defaultTo, - MarkerClusterPlugin = leafletHelpers.MarkerClusterPlugin, - AwesomeMarkersPlugin = leafletHelpers.AwesomeMarkersPlugin, - MakiMarkersPlugin = leafletHelpers.MakiMarkersPlugin, - ExtraMarkersPlugin = leafletHelpers.ExtraMarkersPlugin, - safeApply = leafletHelpers.safeApply, - Helpers = leafletHelpers, - isString = leafletHelpers.isString, - isNumber = leafletHelpers.isNumber, - isObject = leafletHelpers.isObject, - groups = {}, - geoHlp = leafletGeoJsonHelpers, - 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 === '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); - } - - // 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,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"; - 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, - layerPos = new L.Point(marker._popup._containerLeft, -containerHeight - marker._popup._containerBottom), - 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, - 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, - labelScope = angular.isFunction(markerData.getLabelScope) ? markerData.getLabelScope() : markerScope, - 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); - } - } - - // 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', function ($rootScope, $log, leafletHelpers) { - var isDefined = leafletHelpers.isDefined, - isArray = leafletHelpers.isArray, - isNumber = leafletHelpers.isNumber, - 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', 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', 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; - } - 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; - } - }); - - var lastNominatimQuery; - leafletScope.$watch('bounds', function (bounds) { - 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); - }); - } - }; -}); - -angular.module("leaflet-directive").directive('center', - function ($log, $q, $location, $timeout, leafletMapDefaults, leafletHelpers, leafletBoundsHelpers, leafletEvents) { - - var isDefined = leafletHelpers.isDefined, - isNumber = leafletHelpers.isNumber, - isSameCenterOnMap = leafletHelpers.isSameCenterOnMap, - safeApply = leafletHelpers.safeApply, - isValidCenter = leafletHelpers.isValidCenter, - isValidBounds = leafletBoundsHelpers.isValidBounds, - isUndefinedOrEmpty = leafletHelpers.isUndefinedOrEmpty, - 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(), - centerModel = leafletScope.center; - - controller.getMap().then(function(map) { - var defaults = leafletMapDefaults.getDefaults(attrs.id); - - if (attrs.center.search("-") !== -1) { - $log.error(errorHeader + ' The "center" variable can\'t use a "-" on its key name: "' + attrs.center + '".'); - 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.center,{ - 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, 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.center, { - lat: urlCenter.lat, - lng: urlCenter.lng, - zoom: urlCenter.zoom - }); - } - }); - } - - leafletScope.$watch("center", function(center) { - //$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); - leafletEvents.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(); - leafletEvents.notifyCenterUrlHashChanged(leafletScope, map, attrs, $location.search()); - //$log.debug("updated center on map..."); - if (isSameCenterOnMap(centerModel, map) || scope.settingCenterFromScope) { - //$log.debug("same center in model, no need to update again."); - return; - } - safeApply(leafletScope, function(scope) { - if (!leafletScope.settingCenterFromScope) { - //$log.debug("updating center model...", map.getCenter(), map.getZoom()); - angular.extend(scope.center,{ - lat: map.getCenter().lat, - lng: map.getCenter().lng, - zoom: map.getZoom(), - autoDiscover: false - }); - } - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - }); - }); - - 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); - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - } else { - map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - } - }); - } - }); - } - }; -}); - -angular.module("leaflet-directive").directive('controls', 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 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]); - } else { - control = newControls[newName]; - } - map.addControl(control); - - leafletControls[newName] = control; - } - - }); - - }); - } - }; -}); - -angular.module("leaflet-directive").directive("decorations", function($log, leafletHelpers) { - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', - - link: function(scope, element, attrs, controller) { - var leafletScope = controller.getLeafletScope(), - PolylineDecoratorPlugin = leafletHelpers.PolylineDecoratorPlugin, - isDefined = leafletHelpers.isDefined, - 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], - newDecoration = createDecoration(decorationData); - - if (isDefined(newDecoration)) { - leafletDecorations[newName] = newDecoration; - map.addLayer(newDecoration); - setDecorationOptions(newDecoration, decorationData); - } - } - }, true); - }); - } - }; -}); - -angular.module("leaflet-directive").directive('eventBroadcast', function ($log, $rootScope, leafletHelpers, leafletEvents, leafletIterators) { - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', - - link: function(scope, element, attrs, controller) { - var isObject = leafletHelpers.isObject, - isDefined = leafletHelpers.isDefined, - leafletScope = controller.getLeafletScope(), - eventBroadcast = leafletScope.eventBroadcast, - availableMapEvents = leafletEvents.getAvailableMapEvents(), - addEvents = leafletEvents.addEvents; - - controller.getMap().then(function(map) { - - var mapEvents = [], - 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', function ($log, $rootScope, leafletData, leafletHelpers, - leafletWatchHelpers, leafletDirectiveControlsHelpers,leafletIterators, - leafletGeoJsonEvents) { - - var _maybeWatch = leafletWatchHelpers.maybeWatch, - _watchOptions = leafletHelpers.watchOptions, - _extendDirectiveControls = leafletDirectiveControlsHelpers.extend, - hlp = leafletHelpers, - $it = leafletIterators; - - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', - - link: function(scope, element, attrs, controller) { - var isDefined = leafletHelpers.isDefined, - leafletScope = controller.getLeafletScope(), - leafletGeoJSON = {}, - _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(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', 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: function ($scope, $element, $sce) { - $log.debug('[Angular Directive - Layers] layers', $scope, $element); - var safeApply = leafletHelpers.safeApply, - 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: - '
' + - '

{{ title }}

' + - '
' + - '
{{ baseTitle }}
' + - '
' + - '' + - '
' + - '
' + - '
' + - '
{{ overlaysTitle }}
' + - '
' + - '
' + - ''+ - ''+ - '
' + - ' ' + - ' ' + - ' ' + - '' + - '
' + - '
' + - '
' + - '' + - '' + - '' + - '
Range is not supported in this browser
' + - '
' + - '
' + - '
' + - '
' + - '
', - link: function(scope, element, attrs, controller) { - var isDefined = leafletHelpers.isDefined, - leafletScope = controller.getLeafletScope(), - 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', function ($log, $q, leafletData, leafletHelpers, leafletLayerHelpers, leafletControlHelpers) { - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', - controller: function ($scope) { - $scope._leafletLayers = $q.defer(); - this.getLayers = function () { - return $scope._leafletLayers.promise; - }; - }, - link: function(scope, element, attrs, controller){ - var isDefined = leafletHelpers.isDefined, - leafletLayers = {}, - leafletScope = controller.getLeafletScope(), - layers = leafletScope.layers, - createLayer = leafletLayerHelpers.createLayer, - updateLayersControl = leafletControlHelpers.updateLayersControl, - 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) { - map.addLayer(leafletLayers.baselayers[layerName]); - oneVisibleLayer = true; - } - } - - // If there is no visible layer add first to the map - if (!oneVisibleLayer && Object.keys(leafletLayers.baselayers).length > 0) { - map.addLayer(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) { - map.addLayer(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) { - map.addLayer(leafletLayers.baselayers[newName]); - } - } - } else { - if (newBaseLayers[newName].top === true && !map.hasLayer(leafletLayers.baselayers[newName])) { - map.addLayer(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) { - map.addLayer(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])) { - map.removeLayer(leafletLayers.overlays[name]); - } - // 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) { - map.addLayer(leafletLayers.overlays[newName]); - } - } - - // check for the .visible property to hide/show overLayers - if (newOverlayLayers[newName].visible && !map.hasLayer(leafletLayers.overlays[newName])) { - map.addLayer(leafletLayers.overlays[newName]); - } else if (newOverlayLayers[newName].visible === false && map.hasLayer(leafletLayers.overlays[newName])) { - map.removeLayer(leafletLayers.overlays[newName]); - } - - //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', function ($log, $http, leafletHelpers, leafletLegendHelpers) { - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', - - link: function (scope, element, attrs, controller) { - - var isArray = leafletHelpers.isArray, - isDefined = leafletHelpers.isDefined, - isFunction = leafletHelpers.isFunction, - leafletScope = controller.getLeafletScope(), - 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', - function ($log, $rootScope, $q, leafletData, leafletHelpers, leafletMapDefaults, - leafletMarkersHelpers, leafletMarkerEvents, leafletIterators, leafletWatchHelpers, - leafletDirectiveControlsHelpers) { - //less terse vars to helpers - var isDefined = leafletHelpers.isDefined, - errorHeader = leafletHelpers.errorHeader, - Helpers = leafletHelpers, - isString = leafletHelpers.isString, - addMarkerWatcher = leafletMarkersHelpers.addMarkerWatcher, - updateMarker = leafletMarkersHelpers.updateMarker, - listenMarkerEvents = leafletMarkersHelpers.listenMarkerEvents, - addMarkerToGroup = leafletMarkersHelpers.addMarkerToGroup, - createMarker = leafletMarkersHelpers.createMarker, - deleteMarker = leafletMarkersHelpers.deleteMarker, - $it = leafletIterators, - _markersWatchOptions = leafletHelpers.watchOptions, - maybeWatch = leafletWatchHelpers.maybeWatch, - 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(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(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, - equals = false, - oldMarker, - 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], - leafletScope = mapController.getLeafletScope(); - - mapController.getMap().then(function(map) { - var leafletMarkers = {}, 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(markersToAdd, oldModels, map, layers, leafletMarkers, leafletScope, - watchOptions, layerName, skips); - }); - return; - } - skips = _getNewModelsToSkipp(models, oldModels, leafletMarkers); - _addMarkers(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', function ($log, leafletMapDefaults, leafletBoundsHelpers, leafletHelpers) { - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', - - link: function(scope, element, attrs, controller) { - var leafletScope = controller.getLeafletScope(), - isValidBounds = leafletBoundsHelpers.isValidBounds, - 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) { - map.fitBounds(leafletBounds); - } - }); - }); - } - }; -}); - -angular.module("leaflet-directive").directive('paths', function ($log, $q, leafletData, leafletMapDefaults, leafletHelpers, leafletPathsHelpers, leafletEvents) { - return { - restrict: "A", - scope: false, - replace: false, - require: ['leaflet', '?layers'], - - link: function(scope, element, attrs, controller) { - var mapController = controller[0], - isDefined = leafletHelpers.isDefined, - isString = leafletHelpers.isString, - leafletScope = mapController.getLeafletScope(), - paths = leafletScope.paths, - createPath = leafletPathsHelpers.createPath, - bindPathEvents = leafletEvents.bindPathEvents, - setPathOptions = leafletPathsHelpers.setPathOptions; - - mapController.getMap().then(function(map) { - var defaults = leafletMapDefaults.getDefaults(attrs.id), - 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 marker 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 marker 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(newPath, newName, pathData, leafletScope); - } - } - }); - }); - }); - } - }; -}); - -angular.module("leaflet-directive").directive('tiles', function ($log, leafletData, leafletMapDefaults, leafletHelpers) { - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', - - link: function(scope, element, attrs, controller) { - var isDefined = leafletHelpers.isDefined, - leafletScope = controller.getLeafletScope(), - 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) { - 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; - } - - 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) && !angular.equals(tiles.options, tileLayerOptions)) { - map.removeLayer(tileLayerObj); - tileLayerOptions = defaults.tileLayerOptions; - angular.copy(tiles.options, tileLayerOptions); - tileLayerUrl = tiles.url; - 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', function ($rootScope, $q, $log, leafletHelpers) { - var safeApply = leafletHelpers.safeApply, - isDefined = leafletHelpers.isDefined, - isObject = leafletHelpers.isObject, - isArray = leafletHelpers.isArray, - errorHeader = leafletHelpers.errorHeader; - - var EventsHelper = function(rootBroadcastName, lObjectType){ - this.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(eventName, logic, leafletScope, lObject, name, model, layerName, extra) { - var _this = this; - return function (e) { - var broadcastName = _this.rootBroadcastName + '.' + eventName; - _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, extra){ - // 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 (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, 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(eventName, logic, leafletScope, lObject, name, model, layerName, extra)); - }); - return logic; - }; - - return EventsHelper; -}) -.service('leafletEventsHelpers', function(leafletEventsHelpersFactory){ - return new leafletEventsHelpersFactory(); -}); - -angular.module("leaflet-directive") -.factory('leafletGeoJsonEvents', function ($rootScope, $q, $log, leafletHelpers, - leafletEventsHelpersFactory, leafletLabelEvents, leafletData) { - var safeApply = leafletHelpers.safeApply, - isDefined = leafletHelpers.isDefined, - Helpers = leafletHelpers, - lblHelp = leafletLabelEvents, - EventsHelper = leafletEventsHelpersFactory; - - - var GeoJsonEvents = function(){ - EventsHelper.call(this,'leafletDirectiveGeoJson', 'geojson'); - }; - - GeoJsonEvents.prototype = new EventsHelper(); - - - GeoJsonEvents.prototype.genDispatchEvent = function(eventName, logic, leafletScope, lObject, name, model, layerName, extra) { - var base = EventsHelper.prototype.genDispatchEvent.call(this, eventName, logic, leafletScope, lObject, name, model, layerName), - _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', function ($rootScope, $q, $log, leafletHelpers, leafletEventsHelpersFactory) { - var Helpers = leafletHelpers, - EventsHelper = leafletEventsHelpersFactory; - var LabelEvents = function(){ - EventsHelper.call(this,'leafletDirectiveLabel', 'markers'); - }; - LabelEvents.prototype = new EventsHelper(); - - LabelEvents.prototype.genDispatchEvent = function(eventName, logic, leafletScope, lObject, name, model, layerName) { - var markerName = name.replace('markers.', ''); - return EventsHelper.prototype - .genDispatchEvent.call(this, eventName, logic, leafletScope, lObject, markerName, model, layerName); - }; - - LabelEvents.prototype.getAvailableEvents = function(){ - return [ - 'click', - 'dblclick', - 'mousedown', - 'mouseover', - 'mouseout', - 'contextmenu' - ]; - }; - - LabelEvents.prototype.genEvents = function (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( - eventName, logic, leafletScope, lObject.label, scopeWatchName, model, layerName)); - }); - }; - - LabelEvents.prototype.bindEvents = function (lObject, name, model, leafletScope, layerName) {}; - - return new LabelEvents(); -}); - -angular.module("leaflet-directive") -.factory('leafletMapEvents', function ($rootScope, $q, $log, leafletHelpers, leafletEventsHelpers) { - var safeApply = leafletHelpers.safeApply, - isDefined = leafletHelpers.isDefined, - isObject = leafletHelpers.isObject, - Helpers = leafletHelpers, - errorHeader = leafletHelpers.errorHeader, - 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', - '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) { - // (nmccready) We should consider passing mapId as an argument or using it from scope - return function(e) { - // Put together broadcast name - // (nmccready) We should consider passing mapId joining mapId to the broadcastName to keep the event unique. Same should be done for all directives so we know what map it comes from. - // problem with this is it will cause a minor bump and break backwards compat - var broadcastName = 'leafletDirectiveMap.' + eventName; - // 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); - } - }; - - return { - getAvailableMapEvents: _getAvailableMapEvents, - genDispatchMapEvent: _genDispatchMapEvent, - notifyCenterChangedToBounds: _notifyCenterChangedToBounds, - notifyCenterUrlHashChanged: _notifyCenterUrlHashChanged - }; -}); - -angular.module("leaflet-directive") -.factory('leafletMarkerEvents', function ($rootScope, $q, $log, leafletHelpers, leafletEventsHelpersFactory, leafletLabelEvents) { - var safeApply = leafletHelpers.safeApply, - isDefined = leafletHelpers.isDefined, - Helpers = leafletHelpers, - lblHelp = leafletLabelEvents, - EventsHelper = leafletEventsHelpersFactory; - - var MarkerEvents = function(){ - EventsHelper.call(this,'leafletDirectiveMarker', 'markers'); - }; - - MarkerEvents.prototype = new EventsHelper(); - - MarkerEvents.prototype.genDispatchEvent = function(eventName, logic, leafletScope, lObject, name, model, layerName) { - var handle = EventsHelper.prototype - .genDispatchEvent.call(this, 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 (lObject, name, model, leafletScope, layerName) { - var logic = EventsHelper.prototype.bindEvents.call(this,lObject, name, model, leafletScope, layerName); - - if (Helpers.LabelPlugin.isLoaded() && isDefined(lObject.label)) { - lblHelp.genEvents(name, logic, leafletScope, lObject, model, layerName); - } - }; - - return new MarkerEvents(); -}); - -angular.module("leaflet-directive") -.factory('leafletPathEvents', function ($rootScope, $q, $log, leafletHelpers, leafletLabelEvents, leafletEventsHelpers) { - var safeApply = leafletHelpers.safeApply, - isDefined = leafletHelpers.isDefined, - isObject = leafletHelpers.isObject, - Helpers = leafletHelpers, - errorHeader = leafletHelpers.errorHeader, - lblHelp = leafletLabelEvents, - fire = leafletEventsHelpers.fire; - - var _genDispatchPathEvent = function (eventName, logic, leafletScope, lObject, name, model, layerName) { - return function (e) { - var broadcastName = 'leafletDirectivePath.' + eventName; - - fire(leafletScope, broadcastName, logic, e, e.target || lObject, model, name, layerName); - }; - }; - - var _bindPathEvents = function (lObject, name, model, leafletScope) { - var pathEvents = [], - i, - eventName, - 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, 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(eventName, logic, leafletScope, pathEvents, name)); - } - - if (Helpers.LabelPlugin.isLoaded() && isDefined(lObject.label)) { - lblHelp.genEvents(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)); -//# sourceMappingURL=angular-leaflet-directive_dev_mapped.js.map \ No newline at end of file diff --git a/dist/angular-leaflet-directive_dev_mapped.js.map b/dist/angular-leaflet-directive_dev_mapped.js.map deleted file mode 100644 index dfc18f62..00000000 --- a/dist/angular-leaflet-directive_dev_mapped.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../src/directives/leaflet.js","../src/services/leafletBoundsHelpers.js","../src/services/leafletControlHelpers.js","../src/services/leafletData.js","../src/services/leafletDirectiveControlsHelpers.js","../src/services/leafletEvents.js","../src/services/leafletGeoJsonHelpers.js","../src/services/leafletHelpers.js","../src/services/leafletIterators.js","../src/services/leafletLayerHelpers.js","../src/services/leafletLegendHelpers.js","../src/services/leafletMapDefaults.js","../src/services/leafletMarkersHelpers.js","../src/services/leafletPathsHelpers.js","../src/services/leafletWatchHelpers.js","../src/services/nominatim.js","../src/directives/bounds.js","../src/directives/center.js","../src/directives/controls.js","../src/directives/decorations.js","../src/directives/eventBroadcast.js","../src/directives/geojson.js","../src/directives/layercontrol.js","../src/directives/layers.js","../src/directives/legend.js","../src/directives/markers.js","../src/directives/maxbounds.js","../src/directives/paths.js","../src/directives/tiles.js","../src/directives/watchOptions.js","../src/services/events/leafletEventsHelpers.js","../src/services/events/leafletGeoJsonEvents.js","../src/services/events/leafletLabelEvents.js","../src/services/events/leafletMapEvents.js","../src/services/events/leafletMarkerEvents.js","../src/services/events/leafletPathEvents.js"],"names":[],"mappings":"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","file":"angular-leaflet-directive_dev_mapped.js","sourcesContent":["angular.module(\"leaflet-directive\", []).directive('leaflet',\n function ($q, leafletData, leafletMapDefaults, leafletHelpers, leafletEvents) {\n return {\n restrict: \"EA\",\n replace: true,\n scope: {\n center : '=',\n defaults : '=',\n maxbounds : '=',\n bounds : '=',\n markers : '=',\n legend : '=',\n geojson : '=',\n paths : '=',\n tiles : '=',\n layers : '=',\n controls : '=',\n decorations : '=',\n eventBroadcast : '=',\n markersWatchOptions : '=',\n geojsonWatchOptions : '='\n },\n transclude: true,\n template: '
',\n controller: function ($scope) {\n this._leafletMap = $q.defer();\n this.getMap = function () {\n return this._leafletMap.promise;\n };\n\n this.getLeafletScope = function() {\n return $scope;\n };\n },\n\n link: function(scope, element, attrs, ctrl) {\n var isDefined = leafletHelpers.isDefined,\n defaults = leafletMapDefaults.setDefaults(scope.defaults, attrs.id),\n mapEvents = leafletEvents.getAvailableMapEvents(),\n addEvents = leafletEvents.addEvents;\n\n scope.mapId = attrs.id;\n leafletData.setDirectiveControls({}, attrs.id);\n\n // Set width and height utility functions\n function updateWidth() {\n if (isNaN(attrs.width)) {\n element.css('width', attrs.width);\n } else {\n element.css('width', attrs.width + 'px');\n }\n }\n\n function updateHeight() {\n if (isNaN(attrs.height)) {\n element.css('height', attrs.height);\n } else {\n element.css('height', attrs.height + 'px');\n }\n }\n\n // If the width attribute defined update css\n // Then watch if bound property changes and update css\n if (isDefined(attrs.width)) {\n updateWidth();\n\n scope.$watch(\n function () {\n return element[0].getAttribute('width');\n },\n function () {\n updateWidth();\n map.invalidateSize();\n });\n }\n\n // If the height attribute defined update css\n // Then watch if bound property changes and update css\n if (isDefined(attrs.height)) {\n updateHeight();\n\n scope.$watch(\n function () {\n return element[0].getAttribute('height');\n },\n function () {\n updateHeight();\n map.invalidateSize();\n });\n }\n\n // Create the Leaflet Map Object with the options\n var map = new L.Map(element[0], leafletMapDefaults.getMapCreationDefaults(attrs.id));\n ctrl._leafletMap.resolve(map);\n\n if (!isDefined(attrs.center)) {\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n }\n\n // If no layers nor tiles defined, set the default tileLayer\n if (!isDefined(attrs.tiles) && (!isDefined(attrs.layers))) {\n var tileLayerObj = L.tileLayer(defaults.tileLayer, defaults.tileLayerOptions);\n tileLayerObj.addTo(map);\n leafletData.setTiles(tileLayerObj, attrs.id);\n }\n\n // Set zoom control configuration\n if (isDefined(map.zoomControl) &&\n isDefined(defaults.zoomControlPosition)) {\n map.zoomControl.setPosition(defaults.zoomControlPosition);\n }\n\n if (isDefined(map.zoomControl) &&\n defaults.zoomControl===false) {\n map.zoomControl.removeFrom(map);\n }\n\n if (isDefined(map.zoomsliderControl) &&\n isDefined(defaults.zoomsliderControl) &&\n defaults.zoomsliderControl===false) {\n map.zoomsliderControl.removeFrom(map);\n }\n\n\n // if no event-broadcast attribute, all events are broadcasted\n if (!isDefined(attrs.eventBroadcast)) {\n var logic = \"broadcast\";\n addEvents(map, mapEvents, \"eventName\", scope, logic);\n }\n\n // Resolve the map object to the promises\n map.whenReady(function() {\n leafletData.setMap(map, attrs.id);\n });\n\n scope.$on('$destroy', function () {\n leafletMapDefaults.reset();\n map.remove();\n leafletData.unresolveMap(attrs.id);\n });\n\n //Handle request to invalidate the map size\n //Up scope using $scope.$emit('invalidateSize')\n //Down scope using $scope.$broadcast('invalidateSize')\n scope.$on('invalidateSize', function() {\n map.invalidateSize();\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\").factory('leafletBoundsHelpers', function ($log, leafletHelpers) {\n\n var isArray = leafletHelpers.isArray,\n isNumber = leafletHelpers.isNumber,\n isFunction = leafletHelpers.isFunction,\n isDefined = leafletHelpers.isDefined;\n\n function _isValidBounds(bounds) {\n return angular.isDefined(bounds) && angular.isDefined(bounds.southWest) &&\n angular.isDefined(bounds.northEast) && angular.isNumber(bounds.southWest.lat) &&\n angular.isNumber(bounds.southWest.lng) && angular.isNumber(bounds.northEast.lat) &&\n angular.isNumber(bounds.northEast.lng);\n }\n\n return {\n createLeafletBounds: function(bounds) {\n if (_isValidBounds(bounds)) {\n return L.latLngBounds([bounds.southWest.lat, bounds.southWest.lng],\n [bounds.northEast.lat, bounds.northEast.lng ]);\n }\n },\n\n isValidBounds: _isValidBounds,\n\n createBoundsFromArray: function(boundsArray) {\n if (!(isArray(boundsArray) && boundsArray.length === 2 &&\n isArray(boundsArray[0]) && isArray(boundsArray[1]) &&\n boundsArray[0].length === 2 && boundsArray[1].length === 2 &&\n isNumber(boundsArray[0][0]) && isNumber(boundsArray[0][1]) &&\n isNumber(boundsArray[1][0]) && isNumber(boundsArray[1][1]))) {\n $log.error(\"[AngularJS - Leaflet] The bounds array is not valid.\");\n return;\n }\n\n return {\n northEast: {\n lat: boundsArray[0][0],\n lng: boundsArray[0][1]\n },\n southWest: {\n lat: boundsArray[1][0],\n lng: boundsArray[1][1]\n }\n };\n },\n\n createBoundsFromLeaflet: function(lfBounds) {\n if (!(isDefined(lfBounds) && isFunction(lfBounds.getNorthEast) && isFunction(lfBounds.getSouthWest))) {\n $log.error(\"[AngularJS - Leaflet] The leaflet bounds is not valid object.\");\n return;\n }\n\n var northEast = lfBounds.getNorthEast(),\n southWest = lfBounds.getSouthWest();\n\n return {\n northEast: {\n lat: northEast.lat,\n lng: northEast.lng\n },\n southWest: {\n lat: southWest.lat,\n lng: southWest.lng\n }\n };\n }\n };\n});\n","angular.module(\"leaflet-directive\").factory('leafletControlHelpers', function ($rootScope, $log, leafletHelpers, leafletLayerHelpers, leafletMapDefaults) {\n var isDefined = leafletHelpers.isDefined;\n var isObject = leafletHelpers.isObject;\n var createLayer = leafletLayerHelpers.createLayer;\n var _controls = {};\n var errorHeader = leafletHelpers.errorHeader + ' [Controls] ';\n\n var _controlLayersMustBeVisible = function(baselayers, overlays, mapId) {\n var defaults = leafletMapDefaults.getDefaults(mapId);\n if(!defaults.controls.layers.visible) {\n return false;\n }\n\n var atLeastOneControlItemMustBeShown = false;\n\n if (isObject(baselayers)) {\n Object.keys(baselayers).forEach(function(key) {\n var layer = baselayers[key];\n if (!isDefined(layer.layerOptions) || layer.layerOptions.showOnSelector !== false) {\n atLeastOneControlItemMustBeShown = true;\n }\n });\n }\n\n if (isObject(overlays)) {\n Object.keys(overlays).forEach(function(key) {\n var layer = overlays[key];\n if (!isDefined(layer.layerParams) || layer.layerParams.showOnSelector !== false) {\n atLeastOneControlItemMustBeShown = true;\n }\n });\n }\n\n return atLeastOneControlItemMustBeShown;\n };\n\n var _createLayersControl = function(mapId) {\n var defaults = leafletMapDefaults.getDefaults(mapId);\n var controlOptions = {\n collapsed: defaults.controls.layers.collapsed,\n position: defaults.controls.layers.position,\n autoZIndex: false\n };\n\n angular.extend(controlOptions, defaults.controls.layers.options);\n\n var control;\n if(defaults.controls.layers && isDefined(defaults.controls.layers.control)) {\n\t\t\tcontrol = defaults.controls.layers.control.apply(this, [[], [], controlOptions]);\n\t\t} else {\n\t\t\tcontrol = new L.control.layers([], [], controlOptions);\n\t\t}\n\n return control;\n };\n\n var controlTypes = {\n draw: {\n isPluginLoaded: function() {\n if (!angular.isDefined(L.Control.Draw)) {\n $log.error(errorHeader + ' Draw plugin is not loaded.');\n return false;\n }\n return true;\n },\n checkValidParams: function(/* params */) {\n return true;\n },\n createControl: function(params) {\n return new L.Control.Draw(params);\n }\n },\n scale: {\n isPluginLoaded: function() {\n return true;\n },\n checkValidParams: function(/* params */) {\n return true;\n },\n createControl: function(params) {\n return new L.control.scale(params);\n }\n },\n fullscreen: {\n isPluginLoaded: function() {\n if (!angular.isDefined(L.Control.Fullscreen)) {\n $log.error(errorHeader + ' Fullscreen plugin is not loaded.');\n return false;\n }\n return true;\n },\n checkValidParams: function(/* params */) {\n return true;\n },\n createControl: function(params) {\n return new L.Control.Fullscreen(params);\n }\n },\n search: {\n isPluginLoaded: function() {\n if (!angular.isDefined(L.Control.Search)) {\n $log.error(errorHeader + ' Search plugin is not loaded.');\n return false;\n }\n return true;\n },\n checkValidParams: function(/* params */) {\n return true;\n },\n createControl: function(params) {\n return new L.Control.Search(params);\n }\n },\n minimap: {\n isPluginLoaded: function() {\n if (!angular.isDefined(L.Control.MiniMap)) {\n $log.error(errorHeader + ' Minimap plugin is not loaded.');\n return false;\n }\n\n return true;\n },\n checkValidParams: function(params) {\n if(!isDefined(params.layer)) {\n $log.warn(errorHeader +' minimap \"layer\" option should be defined.');\n return false;\n }\n return true;\n },\n createControl: function(params) {\n var layer = createLayer(params.layer);\n\n if (!isDefined(layer)) {\n $log.warn(errorHeader + ' minimap control \"layer\" could not be created.');\n return;\n }\n\n return new L.Control.MiniMap(layer, params);\n }\n }\n };\n\n return {\n layersControlMustBeVisible: _controlLayersMustBeVisible,\n\n isValidControlType: function(type) {\n return Object.keys(controlTypes).indexOf(type) !== -1;\n },\n\n createControl: function (type, params) {\n if (!controlTypes[type].checkValidParams(params)) {\n return;\n }\n\n return controlTypes[type].createControl(params);\n },\n\n updateLayersControl: function(map, mapId, loaded, baselayers, overlays, leafletLayers) {\n var i;\n var _layersControl = _controls[mapId];\n var mustBeLoaded = _controlLayersMustBeVisible(baselayers, overlays, mapId);\n\n if (isDefined(_layersControl) && loaded) {\n for (i in leafletLayers.baselayers) {\n _layersControl.removeLayer(leafletLayers.baselayers[i]);\n }\n for (i in leafletLayers.overlays) {\n _layersControl.removeLayer(leafletLayers.overlays[i]);\n }\n map.removeControl(_layersControl);\n delete _controls[mapId];\n }\n\n if (mustBeLoaded) {\n _layersControl = _createLayersControl(mapId);\n _controls[mapId] = _layersControl;\n for (i in baselayers) {\n var hideOnSelector = isDefined(baselayers[i].layerOptions) &&\n baselayers[i].layerOptions.showOnSelector === false;\n if (!hideOnSelector && isDefined(leafletLayers.baselayers[i])) {\n _layersControl.addBaseLayer(leafletLayers.baselayers[i], baselayers[i].name);\n }\n }\n for (i in overlays) {\n \tvar hideOverlayOnSelector = isDefined(overlays[i].layerParams) &&\n overlays[i].layerParams.showOnSelector === false;\n if (!hideOverlayOnSelector && isDefined(leafletLayers.overlays[i])) {\n _layersControl.addOverlay(leafletLayers.overlays[i], overlays[i].name);\n }\n }\n\n map.addControl(_layersControl);\n }\n return mustBeLoaded;\n }\n };\n});\n","angular.module(\"leaflet-directive\").service('leafletData', function ($log, $q, leafletHelpers) {\n var getDefer = leafletHelpers.getDefer,\n getUnresolvedDefer = leafletHelpers.getUnresolvedDefer,\n setResolvedDefer = leafletHelpers.setResolvedDefer;\n\n var _private = {};\n var self = this;\n\n var upperFirst = function (string) {\n return string.charAt(0).toUpperCase() + string.slice(1);\n };\n\n var _privateItems = [\n 'map',\n 'tiles',\n 'layers',\n 'paths',\n 'markers',\n 'geoJSON',\n 'UTFGrid', //odd ball on naming convention keeping to not break\n 'decorations',\n 'directiveControls'];\n\n //init\n _privateItems.forEach(function(itemName){\n _private[itemName] = {};\n });\n\n this.unresolveMap = function (scopeId) {\n var id = leafletHelpers.obtainEffectiveMapId(_private.map, scopeId);\n _privateItems.forEach(function (itemName) {\n _private[itemName][id] = undefined;\n });\n };\n\n //int repetitive stuff (get and sets)\n _privateItems.forEach(function (itemName) {\n var name = upperFirst(itemName);\n self['set' + name] = function (lObject, scopeId) {\n var defer = getUnresolvedDefer(_private[itemName], scopeId);\n defer.resolve(lObject);\n setResolvedDefer(_private[itemName], scopeId);\n };\n\n self['get' + name] = function (scopeId) {\n var defer = getDefer(_private[itemName], scopeId);\n return defer.promise;\n };\n });\n});\n","angular.module(\"leaflet-directive\")\n.service('leafletDirectiveControlsHelpers', function ($log, leafletData, leafletHelpers) {\n var _isDefined = leafletHelpers.isDefined,\n _isString = leafletHelpers.isString,\n _isObject = leafletHelpers.isObject,\n _mainErrorHeader = leafletHelpers.errorHeader;\n\n var _errorHeader = _mainErrorHeader + '[leafletDirectiveControlsHelpers';\n\n var _extend = function(id, thingToAddName, createFn, cleanFn){\n var _fnHeader = _errorHeader + '.extend] ';\n var extender = {};\n if(!_isDefined(thingToAddName)){\n $log.error(_fnHeader + 'thingToAddName cannot be undefined');\n return;\n }\n\n if(_isString(thingToAddName) && _isDefined(createFn) && _isDefined(cleanFn)){\n extender[thingToAddName] = {\n create: createFn,\n clean: cleanFn\n };\n }\n else if(_isObject(thingToAddName) && !_isDefined(createFn) && !_isDefined(cleanFn)){\n extender = thingToAddName;\n }\n else{\n $log.error(_fnHeader + 'incorrect arguments');\n return;\n }\n\n //add external control to create / destroy markers without a watch\n leafletData.getDirectiveControls().then(function(controls){\n angular.extend(controls, extender);\n leafletData.setDirectiveControls(controls, id);\n });\n };\n\n return {\n extend: _extend\n };\n});\n","angular.module(\"leaflet-directive\").factory('leafletEvents',\n function (leafletMapEvents, leafletMarkerEvents, leafletPathEvents, leafletIterators) {\n //NOTE THIS SHOULD BE DEPRECATED infavor of getting a specific events helper\n var instance = angular.extend({},\n leafletMapEvents, {\n bindMarkerEvents: leafletMarkerEvents.bindEvents,\n getAvailableMarkerEvents: leafletMarkerEvents.getAvailableEvents\n }, leafletPathEvents);\n\n var genDispatchMapEvent = instance.genDispatchMapEvent;\n\n instance.addEvents = function(map, mapEvents, contextName, scope, logic){\n leafletIterators.each(mapEvents, function(eventName) {\n var context = {};\n context[contextName] = eventName;\n map.on(eventName, genDispatchMapEvent(scope, eventName, logic), context);\n });\n };\n\n return instance;\n});\n","angular.module(\"leaflet-directive\")\n.service('leafletGeoJsonHelpers', function (leafletHelpers, leafletIterators) {\n var lHlp = leafletHelpers,\n lIt = leafletIterators;\n var Point = function(lat,lng){\n this.lat = lat;\n this.lng = lng;\n return this;\n };\n\n var _getLat = function(value) {\n if (Array.isArray(value) && value.length === 2) {\n return value[1];\n } else if (lHlp.isDefined(value.type) && value.type === 'Point') {\n return +value.coordinates[1];\n } else {\n return +value.lat;\n }\n };\n\n var _getLng = function(value) {\n if (Array.isArray(value) && value.length === 2) {\n return value[0];\n } else if (lHlp.isDefined(value.type) && value.type === 'Point') {\n return +value.coordinates[0];\n } else {\n return +value.lng;\n }\n };\n\n var _validateCoords = function(coords) {\n if (lHlp.isUndefined(coords)) {\n return false;\n }\n if (lHlp.isArray(coords)) {\n if (coords.length === 2 && lHlp.isNumber(coords[0]) && lHlp.isNumber(coords[1])) {\n return true;\n }\n } else if (lHlp.isDefined(coords.type)) {\n if (\n coords.type === 'Point' && lHlp.isArray(coords.coordinates) &&\n coords.coordinates.length === 2 &&\n lHlp.isNumber(coords.coordinates[0]) &&\n lHlp.isNumber(coords.coordinates[1])) {\n return true;\n }\n }\n\n var ret = lIt.all(['lat', 'lng'], function(pos){\n return lHlp.isDefined(coords[pos]) && lHlp.isNumber(coords[pos]);\n });\n return ret;\n };\n\n var _getCoords = function(value) {\n if (!value || !_validateCoords(value)) {\n return;\n }\n var p = null;\n if (Array.isArray(value) && value.length === 2) {\n p = new Point(value[1], value[0]);\n } else if (lHlp.isDefined(value.type) && value.type === 'Point') {\n p = new Point(value.coordinates[1], value.coordinates[0]);\n } else {\n return value;\n }\n //note angular.merge is avail in angular 1.4.X we might want to fill it here\n return angular.extend(value, p);//tap on lat, lng if it doesnt exist\n };\n\n\n return {\n getLat: _getLat,\n getLng: _getLng,\n validateCoords: _validateCoords,\n getCoords: _getCoords\n };\n });\n","angular.module(\"leaflet-directive\").factory('leafletHelpers', function ($q, $log) {\n var _errorHeader = '[AngularJS - Leaflet] ';\n var _copy = angular.copy;\n var _clone = _copy;\n /*\n For parsing paths to a field in an object\n\n Example:\n var obj = {\n bike:{\n 1: 'hi'\n 2: 'foo'\n }\n };\n _getObjectValue(obj,\"bike.1\") returns 'hi'\n this is getPath in ui-gmap\n */\n var _getObjectValue = function(object, pathStr) {\n var obj;\n if(!object || !angular.isObject(object))\n return;\n //if the key is not a sting then we already have the value\n if ((pathStr === null) || !angular.isString(pathStr)) {\n return pathStr;\n }\n obj = object;\n pathStr.split('.').forEach(function(value) {\n if (obj) {\n obj = obj[value];\n }\n });\n return obj;\n };\n\n /*\n Object Array Notation\n _getObjectArrayPath(\"bike.one.two\")\n returns:\n 'bike[\"one\"][\"two\"]'\n */\n var _getObjectArrayPath = function(pathStr){\n return pathStr.split('.').reduce(function(previous, current) {\n return previous + '[\"'+ current + '\"]';\n });\n };\n\n /* Object Dot Notation\n _getObjectPath([\"bike\",\"one\",\"two\"])\n returns:\n \"bike.one.two\"\n */\n var _getObjectDotPath = function(arrayOfStrings){\n return arrayOfStrings.reduce(function(previous, current) {\n return previous + '.' + current;\n });\n };\n\n function _obtainEffectiveMapId(d, mapId) {\n var id, i;\n if (!angular.isDefined(mapId)) {\n if (Object.keys(d).length === 0) {\n id = \"main\";\n } else if (Object.keys(d).length >= 1) {\n for (i in d) {\n if (d.hasOwnProperty(i)) {\n id = i;\n }\n }\n } else if (Object.keys(d).length === 0) {\n id = \"main\";\n } else {\n $log.error(_errorHeader + \"- You have more than 1 map on the DOM, you must provide the map ID to the leafletData.getXXX call\");\n }\n } else {\n id = mapId;\n }\n\n return id;\n }\n\n function _getUnresolvedDefer(d, mapId) {\n var id = _obtainEffectiveMapId(d, mapId),\n defer;\n\n if (!angular.isDefined(d[id]) || d[id].resolvedDefer === true) {\n defer = $q.defer();\n d[id] = {\n defer: defer,\n resolvedDefer: false\n };\n } else {\n defer = d[id].defer;\n }\n\n return defer;\n }\n\n var _isDefined = function(value) {\n return angular.isDefined(value) && value !== null;\n };\n var _isUndefined = function(value){\n return !_isDefined(value);\n };\n\n return {\n copy:_copy,\n clone:_clone,\n errorHeader: _errorHeader,\n getObjectValue: _getObjectValue,\n getObjectArrayPath:_getObjectArrayPath,\n getObjectDotPath: _getObjectDotPath,\n defaultTo: function(val, _default){\n return _isDefined(val) ? val : _default;\n },\n //mainly for checking attributes of directives lets keep this minimal (on what we accept)\n isTruthy: function(val){\n return val === 'true' || val === true;\n },\n //Determine if a reference is {}\n isEmpty: function(value) {\n return Object.keys(value).length === 0;\n },\n\n //Determine if a reference is undefined or {}\n isUndefinedOrEmpty: function (value) {\n return (angular.isUndefined(value) || value === null) || Object.keys(value).length === 0;\n },\n\n // Determine if a reference is defined\n isDefined: _isDefined,\n isUndefined:_isUndefined,\n isNumber: angular.isNumber,\n isString: angular.isString,\n isArray: angular.isArray,\n isObject: angular.isObject,\n isFunction: angular.isFunction,\n equals: angular.equals,\n\n isValidCenter: function(center) {\n return angular.isDefined(center) && angular.isNumber(center.lat) &&\n angular.isNumber(center.lng) && angular.isNumber(center.zoom);\n },\n\n isValidPoint: function(point) {\n if (!angular.isDefined(point)) {\n return false;\n }\n if (angular.isArray(point)) {\n return point.length === 2 && angular.isNumber(point[0]) && angular.isNumber(point[1]);\n }\n return angular.isNumber(point.lat) && angular.isNumber(point.lng);\n },\n\n isSameCenterOnMap: function(centerModel, map) {\n var mapCenter = map.getCenter();\n var zoom = map.getZoom();\n if (centerModel.lat && centerModel.lng &&\n mapCenter.lat.toFixed(4) === centerModel.lat.toFixed(4) &&\n mapCenter.lng.toFixed(4) === centerModel.lng.toFixed(4) &&\n zoom === centerModel.zoom) {\n return true;\n }\n return false;\n },\n\n safeApply: function($scope, fn) {\n var phase = $scope.$root.$$phase;\n if (phase === '$apply' || phase === '$digest') {\n $scope.$eval(fn);\n } else {\n $scope.$evalAsync(fn);\n }\n },\n\n obtainEffectiveMapId: _obtainEffectiveMapId,\n\n getDefer: function(d, mapId) {\n var id = _obtainEffectiveMapId(d, mapId),\n defer;\n if (!angular.isDefined(d[id]) || d[id].resolvedDefer === false) {\n defer = _getUnresolvedDefer(d, mapId);\n } else {\n defer = d[id].defer;\n }\n return defer;\n },\n\n getUnresolvedDefer: _getUnresolvedDefer,\n\n setResolvedDefer: function(d, mapId) {\n var id = _obtainEffectiveMapId(d, mapId);\n d[id].resolvedDefer = true;\n },\n\n rangeIsSupported: function() {\n var testrange = document.createElement('input');\n testrange.setAttribute('type', 'range');\n return testrange.type === 'range';\n },\n\n FullScreenControlPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.Control.Fullscreen);\n }\n },\n\n MiniMapControlPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.Control.MiniMap);\n }\n },\n\n AwesomeMarkersPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.AwesomeMarkers) && angular.isDefined(L.AwesomeMarkers.Icon);\n },\n is: function(icon) {\n if (this.isLoaded()) {\n return icon instanceof L.AwesomeMarkers.Icon;\n } else {\n return false;\n }\n },\n equal: function (iconA, iconB) {\n if (!this.isLoaded()) {\n return false;\n }\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n },\n\n PolylineDecoratorPlugin: {\n isLoaded: function() {\n if (angular.isDefined(L.PolylineDecorator)) {\n return true;\n } else {\n return false;\n }\n },\n is: function(decoration) {\n if (this.isLoaded()) {\n return decoration instanceof L.PolylineDecorator;\n } else {\n return false;\n }\n },\n equal: function(decorationA, decorationB) {\n if (!this.isLoaded()) {\n return false;\n }\n if (this.is(decorationA)) {\n return angular.equals(decorationA, decorationB);\n } else {\n return false;\n }\n }\n },\n\n MakiMarkersPlugin: {\n isLoaded: function() {\n if (angular.isDefined(L.MakiMarkers) && angular.isDefined(L.MakiMarkers.Icon)) {\n return true;\n } else {\n return false;\n }\n },\n is: function(icon) {\n if (this.isLoaded()) {\n return icon instanceof L.MakiMarkers.Icon;\n } else {\n return false;\n }\n },\n equal: function (iconA, iconB) {\n if (!this.isLoaded()) {\n return false;\n }\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n },\n ExtraMarkersPlugin: {\n isLoaded: function () {\n if (angular.isDefined(L.ExtraMarkers) && angular.isDefined(L.ExtraMarkers.Icon)) {\n return true;\n } else {\n return false;\n }\n },\n is: function (icon) {\n if (this.isLoaded()) {\n return icon instanceof L.ExtraMarkers.Icon;\n } else {\n return false;\n }\n },\n equal: function (iconA, iconB) {\n if (!this.isLoaded()) {\n return false;\n }\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n },\n LabelPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.Label);\n },\n is: function(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.MarkerClusterGroup;\n } else {\n return false;\n }\n }\n },\n MarkerClusterPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.MarkerClusterGroup);\n },\n is: function(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.MarkerClusterGroup;\n } else {\n return false;\n }\n }\n },\n GoogleLayerPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.Google);\n },\n is: function(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.Google;\n } else {\n return false;\n }\n }\n },\n ChinaLayerPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.tileLayer.chinaProvider);\n }\n },\n HeatLayerPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.heatLayer);\n }\n },\n WebGLHeatMapLayerPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.TileLayer.WebGLHeatMap);\n }\n },\n BingLayerPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.BingLayer);\n },\n is: function(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.BingLayer;\n } else {\n return false;\n }\n }\n },\n WFSLayerPlugin: {\n isLoaded: function() {\n return L.GeoJSON.WFS !== undefined;\n },\n is: function(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.GeoJSON.WFS;\n } else {\n return false;\n }\n }\n },\n AGSBaseLayerPlugin: {\n isLoaded: function() {\n return L.esri !== undefined && L.esri.basemapLayer !== undefined;\n },\n is: function (layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.basemapLayer;\n } else {\n return false;\n }\n }\n },\n AGSLayerPlugin: {\n isLoaded: function() {\n return lvector !== undefined && lvector.AGS !== undefined;\n },\n is: function(layer) {\n if (this.isLoaded()) {\n return layer instanceof lvector.AGS;\n } else {\n return false;\n }\n }\n },\n AGSFeatureLayerPlugin: {\n isLoaded: function() {\n return L.esri !== undefined && L.esri.featureLayer !== undefined;\n },\n is: function (layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.featureLayer;\n } else {\n return false;\n }\n }\n },\n AGSTiledMapLayerPlugin: {\n isLoaded: function() {\n return L.esri !== undefined && L.esri.tiledMapLayer !== undefined;\n },\n is: function (layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.tiledMapLayer;\n } else {\n return false;\n }\n }\n },\n AGSDynamicMapLayerPlugin: {\n isLoaded: function () {\n return L.esri !== undefined && L.esri.dynamicMapLayer !== undefined;\n },\n is: function (layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.dynamicMapLayer;\n } else {\n return false;\n }\n }\n },\n AGSImageMapLayerPlugin: {\n isLoaded: function () {\n return L.esri !== undefined && L.esri.imageMapLayer !== undefined;\n },\n is: function (layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.imageMapLayer;\n } else {\n return false;\n }\n }\n },\n AGSClusteredLayerPlugin: {\n isLoaded: function () {\n return L.esri !== undefined && L.esri.clusteredFeatureLayer !== undefined;\n },\n is: function (layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.clusteredFeatureLayer;\n } else {\n return false;\n }\n }\n },\n AGSHeatmapLayerPlugin: {\n isLoaded: function () {\n return L.esri !== undefined && L.esri.heatmapFeatureLayer !== undefined;\n },\n is: function (layer) {\n if (this.isLoaded()) {\n return layer instanceof L.esri.heatmapFeatureLayer;\n } else {\n return false;\n }\n }\n },\n YandexLayerPlugin: {\n isLoaded: function() {\n return angular.isDefined(L.Yandex);\n },\n is: function(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.Yandex;\n } else {\n return false;\n }\n }\n },\n GeoJSONPlugin: {\n isLoaded: function(){\n return angular.isDefined(L.TileLayer.GeoJSON);\n },\n is: function(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.TileLayer.GeoJSON;\n } else {\n return false;\n }\n }\n },\n UTFGridPlugin: {\n isLoaded: function(){\n return angular.isDefined(L.UtfGrid);\n },\n is: function(layer) {\n if (this.isLoaded()) {\n return layer instanceof L.UtfGrid;\n } else {\n $log.error('[AngularJS - Leaflet] No UtfGrid plugin found.');\n return false;\n }\n }\n },\n CartoDB: {\n isLoaded: function(){\n return cartodb;\n },\n is: function(/*layer*/) {\n return true;\n /*\n if (this.isLoaded()) {\n return layer instanceof L.TileLayer.GeoJSON;\n } else {\n return false;\n }*/\n }\n },\n Leaflet: {\n DivIcon: {\n is: function(icon) {\n return icon instanceof L.DivIcon;\n },\n equal: function(iconA, iconB) {\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n },\n Icon: {\n is: function(icon) {\n return icon instanceof L.Icon;\n },\n equal: function(iconA, iconB) {\n if (this.is(iconA)) {\n return angular.equals(iconA, iconB);\n } else {\n return false;\n }\n }\n }\n },\n /*\n watchOptions - object to set deep nested watches and turn off watches all together\n (rely on control / functional updates)\n watchOptions - Object\n doWatch:boolean\n isDeep:boolean (sets $watch(function,isDeep))\n individual\n doWatch:boolean\n isDeep:boolean\n */\n //legacy defaults\n watchOptions: {\n doWatch:true,\n isDeep: true,\n individual:{\n doWatch:true,\n isDeep: true\n }\n }\n };\n});\n","angular.module('leaflet-directive').service('leafletIterators', function ($log, leafletHelpers) {\n\n var lHlp = leafletHelpers,\n errorHeader = leafletHelpers.errorHeader + 'leafletIterators: ';\n\n //BEGIN COPY from underscore\n var _keys = Object.keys;\n var _isFunction = lHlp.isFunction;\n var _isObject = lHlp.isObject;\n\n // Helper for collection methods to determine whether a collection\n // should be iterated as an array or as an object\n // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength\n var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;\n\n var _isArrayLike = function(collection) {\n var length = collection !== null && collection.length;\n return lHlp.isNumber(length) && length >= 0 && length <= MAX_ARRAY_INDEX;\n };\n\n // Keep the identity function around for default iteratees.\n var _identity = function(value) {\n return value;\n };\n\n var _property = function(key) {\n return function(obj) {\n return obj === null ? void 0 : obj[key];\n };\n };\n\n // Internal function that returns an efficient (for current engines) version\n // of the passed-in callback, to be repeatedly applied in other Underscore\n // functions.\n var optimizeCb = function(func, context, argCount) {\n if (context === void 0) return func;\n switch (argCount === null ? 3 : argCount) {\n case 1: return function(value) {\n return func.call(context, value);\n };\n case 2: return function(value, other) {\n return func.call(context, value, other);\n };\n case 3: return function(value, index, collection) {\n return func.call(context, value, index, collection);\n };\n case 4: return function(accumulator, value, index, collection) {\n return func.call(context, accumulator, value, index, collection);\n };\n }\n return function() {\n return func.apply(context, arguments);\n };\n };\n\n // An internal function for creating assigner functions.\n var createAssigner = function(keysFunc, undefinedOnly) {\n return function(obj) {\n var length = arguments.length;\n if (length < 2 || obj === null) return obj;\n for (var index = 1; index < length; index++) {\n var source = arguments[index],\n keys = keysFunc(source),\n l = keys.length;\n for (var i = 0; i < l; i++) {\n var key = keys[i];\n if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];\n }\n }\n return obj;\n };\n };\n\n // Assigns a given object with all the own properties in the passed-in object(s)\n // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)\n var _extendOwn, _assign = null;\n _extendOwn = _assign = createAssigner(_keys);\n\n // Returns whether an object has a given set of `key:value` pairs.\n var _isMatch = function(object, attrs) {\n var keys = _keys(attrs), length = keys.length;\n if (object === null) return !length;\n var obj = Object(object);\n for (var i = 0; i < length; i++) {\n var key = keys[i];\n if (attrs[key] !== obj[key] || !(key in obj)) return false;\n }\n return true;\n };\n\n // Returns a predicate for checking whether an object has a given set of\n // `key:value` pairs.\n var _matcher, _matches = null;\n _matcher = _matches = function(attrs) {\n attrs = _extendOwn({}, attrs);\n return function(obj) {\n return _isMatch(obj, attrs);\n };\n };\n\n\n // A mostly-internal function to generate callbacks that can be applied\n // to each element in a collection, returning the desired result — either\n // identity, an arbitrary callback, a property matcher, or a property accessor.\n var cb = function(value, context, argCount) {\n if (value === null) return _identity;\n if (_isFunction(value)) return optimizeCb(value, context, argCount);\n if (_isObject(value)) return _matcher(value);\n return _property(value);\n };\n\n var _every, _all = null;\n _every = _all = function(obj, predicate, context) {\n predicate = cb(predicate, context);\n var keys = !_isArrayLike(obj) && _keys(obj),\n length = (keys || obj).length;\n for (var index = 0; index < length; index++) {\n var currentKey = keys ? keys[index] : index;\n if (!predicate(obj[currentKey], currentKey, obj)) return false;\n }\n return true;\n };\n\n //END COPY fron underscore\n\n var _hasErrors = function(collection, cb, ignoreCollection, cbName){\n if(!ignoreCollection) {\n if (!lHlp.isDefined(collection) || !lHlp.isDefined(cb)) {\n return true;\n }\n }\n if(!lHlp.isFunction(cb)){\n cbName = lHlp.defaultTo(cb,'cb');\n $log.error(errorHeader + cbName + ' is not a function');\n return true;\n }\n return false;\n };\n\n var _iterate = function(collection, externalCb, internalCb){\n if(_hasErrors(undefined, internalCb, true, 'internalCb')){\n return;\n }\n if(!_hasErrors(collection, externalCb)){\n for(var key in collection){\n internalCb(collection[key], key);\n }\n }\n };\n\n //see http://jsperf.com/iterators/3\n //utilizing for in is way faster\n var _each = function(collection, cb){\n _iterate(collection, cb, function(val, key){\n cb(val, key);\n });\n };\n\n return {\n each:_each,\n forEach: _each,\n every: _every,\n all: _all\n };\n});\n","angular.module(\"leaflet-directive\")\n.factory('leafletLayerHelpers', function ($rootScope, $log, leafletHelpers, leafletIterators) {\n var Helpers = leafletHelpers;\n var isString = leafletHelpers.isString;\n var isObject = leafletHelpers.isObject;\n var isArray = leafletHelpers.isArray;\n var isDefined = leafletHelpers.isDefined;\n var errorHeader = leafletHelpers.errorHeader;\n var $it = leafletIterators;\n\n var utfGridCreateLayer = function(params) {\n if (!Helpers.UTFGridPlugin.isLoaded()) {\n $log.error('[AngularJS - Leaflet] The UTFGrid plugin is not loaded.');\n return;\n }\n var utfgrid = new L.UtfGrid(params.url, params.pluginOptions);\n\n utfgrid.on('mouseover', function(e) {\n $rootScope.$broadcast('leafletDirectiveMap.utfgridMouseover', e);\n });\n\n utfgrid.on('mouseout', function(e) {\n $rootScope.$broadcast('leafletDirectiveMap.utfgridMouseout', e);\n });\n\n utfgrid.on('click', function(e) {\n $rootScope.$broadcast('leafletDirectiveMap.utfgridClick', e);\n });\n\n utfgrid.on('mousemove', function(e) {\n $rootScope.$broadcast('leafletDirectiveMap.utfgridMousemove', e);\n });\n\n return utfgrid;\n };\n\n var layerTypes = {\n xyz: {\n mustHaveUrl: true,\n createLayer: function(params) {\n return L.tileLayer(params.url, params.options);\n }\n },\n mapbox: {\n mustHaveKey: true,\n createLayer: function(params) {\n var version = 3;\n if(isDefined(params.options.version) && params.options.version === 4) {\n version = params.options.version;\n }\n var url = version === 3?\n '//{s}.tiles.mapbox.com/v3/' + params.key + '/{z}/{x}/{y}.png':\n '//api.tiles.mapbox.com/v4/' + params.key + '/{z}/{x}/{y}.png?access_token=' + params.apiKey;\n return L.tileLayer(url, params.options);\n }\n },\n geoJSON: {\n mustHaveUrl: true,\n createLayer: function(params) {\n if (!Helpers.GeoJSONPlugin.isLoaded()) {\n return;\n }\n return new L.TileLayer.GeoJSON(params.url, params.pluginOptions, params.options);\n }\n },\n utfGrid: {\n mustHaveUrl: true,\n createLayer: utfGridCreateLayer\n },\n cartodbTiles: {\n mustHaveKey: true,\n createLayer: function(params) {\n var url = '//' + params.user + '.cartodb.com/api/v1/map/' + params.key + '/{z}/{x}/{y}.png';\n return L.tileLayer(url, params.options);\n }\n },\n cartodbUTFGrid: {\n mustHaveKey: true,\n mustHaveLayer : true,\n createLayer: function(params) {\n params.url = '//' + params.user + '.cartodb.com/api/v1/map/' + params.key + '/' + params.layer + '/{z}/{x}/{y}.grid.json';\n return utfGridCreateLayer(params);\n }\n },\n cartodbInteractive: {\n mustHaveKey: true,\n mustHaveLayer : true,\n createLayer: function(params) {\n var tilesURL = '//' + params.user + '.cartodb.com/api/v1/map/' + params.key + '/{z}/{x}/{y}.png';\n var tileLayer = L.tileLayer(tilesURL, params.options);\n params.url = '//' + params.user + '.cartodb.com/api/v1/map/' + params.key + '/' + params.layer + '/{z}/{x}/{y}.grid.json';\n var utfLayer = utfGridCreateLayer(params);\n return L.layerGroup([tileLayer, utfLayer]);\n }\n },\n wms: {\n mustHaveUrl: true,\n createLayer: function(params) {\n return L.tileLayer.wms(params.url, params.options);\n }\n },\n wmts: {\n mustHaveUrl: true,\n createLayer: function(params) {\n return L.tileLayer.wmts(params.url, params.options);\n }\n },\n wfs: {\n mustHaveUrl: true,\n mustHaveLayer : true,\n createLayer: function(params) {\n if (!Helpers.WFSLayerPlugin.isLoaded()) {\n return;\n }\n var options = angular.copy(params.options);\n if(options.crs && 'string' === typeof options.crs) {\n /*jshint -W061 */\n options.crs = eval(options.crs);\n }\n return new L.GeoJSON.WFS(params.url, params.layer, options);\n }\n },\n group: {\n mustHaveUrl: false,\n createLayer: function (params) {\n var lyrs = [];\n $it.each(params.options.layers, function(l){\n lyrs.push(createLayer(l));\n });\n return L.layerGroup(lyrs);\n }\n },\n featureGroup: {\n mustHaveUrl: false,\n createLayer: function () {\n return L.featureGroup();\n }\n },\n google: {\n mustHaveUrl: false,\n createLayer: function(params) {\n var type = params.type || 'SATELLITE';\n if (!Helpers.GoogleLayerPlugin.isLoaded()) {\n return;\n }\n return new L.Google(type, params.options);\n }\n },\n china:{\n mustHaveUrl:false,\n createLayer:function(params){\n var type = params.type || '';\n if(!Helpers.ChinaLayerPlugin.isLoaded()){\n return;\n }\n return L.tileLayer.chinaProvider(type, params.options);\n }\n },\n agsBase: {\n mustHaveLayer : true,\n createLayer: function (params) {\n if (!Helpers.AGSBaseLayerPlugin.isLoaded()) {\n return;\n }\n return L.esri.basemapLayer(params.layer, params.options);\n }\n },\n ags: {\n mustHaveUrl: true,\n createLayer: function(params) {\n if (!Helpers.AGSLayerPlugin.isLoaded()) {\n return;\n }\n\n var options = angular.copy(params.options);\n angular.extend(options, {\n url: params.url\n });\n var layer = new lvector.AGS(options);\n layer.onAdd = function(map) {\n this.setMap(map);\n };\n layer.onRemove = function() {\n this.setMap(null);\n };\n return layer;\n }\n },\n agsFeature: {\n mustHaveUrl: true,\n createLayer: function(params) {\n if (!Helpers.AGSFeatureLayerPlugin.isLoaded()) {\n $log.warn(errorHeader + ' The esri plugin is not loaded.');\n return;\n }\n \n params.options.url = params.url;\n \n return L.esri.featureLayer(params.options);\n }\n },\n agsTiled: {\n mustHaveUrl: true,\n createLayer: function(params) {\n if (!Helpers.AGSTiledMapLayerPlugin.isLoaded()) {\n $log.warn(errorHeader + ' The esri plugin is not loaded.');\n return;\n }\n \n params.options.url = params.url;\n \n return L.esri.tiledMapLayer(params.options);\n }\n },\n agsDynamic: {\n mustHaveUrl: true,\n createLayer: function(params) {\n if (!Helpers.AGSDynamicMapLayerPlugin.isLoaded()) {\n $log.warn(errorHeader + ' The esri plugin is not loaded.');\n return;\n }\n \n params.options.url = params.url;\n \n return L.esri.dynamicMapLayer(params.options);\n }\n },\n agsImage: {\n mustHaveUrl: true,\n createLayer: function(params) {\n if (!Helpers.AGSImageMapLayerPlugin.isLoaded()) {\n $log.warn(errorHeader + ' The esri plugin is not loaded.');\n return;\n }\n params.options.url = params.url;\n \n return L.esri.imageMapLayer(params.options);\n }\n },\n agsClustered: {\n mustHaveUrl: true,\n createLayer: function(params) {\n if (!Helpers.AGSClusteredLayerPlugin.isLoaded()) {\n $log.warn(errorHeader + ' The esri clustered layer plugin is not loaded.');\n return;\n }\n\n if(!Helpers.MarkerClusterPlugin.isLoaded()) {\n $log.warn(errorHeader + ' The markercluster plugin is not loaded.');\n return;\n }\n return L.esri.clusteredFeatureLayer(params.url, params.options);\n }\n },\n agsHeatmap: {\n mustHaveUrl: true,\n createLayer: function(params) {\n if (!Helpers.AGSHeatmapLayerPlugin.isLoaded()) {\n $log.warn(errorHeader + ' The esri heatmap layer plugin is not loaded.');\n return;\n }\n\n if(!Helpers.HeatLayerPlugin.isLoaded()) {\n $log.warn(errorHeader + ' The heatlayer plugin is not loaded.');\n return;\n }\n return L.esri.heatmapFeatureLayer(params.url, params.options);\n }\n },\n markercluster: {\n mustHaveUrl: false,\n createLayer: function(params) {\n if (!Helpers.MarkerClusterPlugin.isLoaded()) {\n $log.warn(errorHeader + ' The markercluster plugin is not loaded.');\n return;\n }\n return new L.MarkerClusterGroup(params.options);\n }\n },\n bing: {\n mustHaveUrl: false,\n createLayer: function(params) {\n if (!Helpers.BingLayerPlugin.isLoaded()) {\n return;\n }\n return new L.BingLayer(params.key, params.options);\n }\n },\n webGLHeatmap: {\n mustHaveUrl: false,\n mustHaveData: true,\n createLayer: function(params) {\n if (!Helpers.WebGLHeatMapLayerPlugin.isLoaded()) {\n return;\n }\n var layer = new L.TileLayer.WebGLHeatMap(params.options);\n if (isDefined(params.data)) {\n layer.setData(params.data);\n }\n\n return layer;\n }\n },\n heat: {\n mustHaveUrl: false,\n mustHaveData: true,\n createLayer: function(params) {\n if (!Helpers.HeatLayerPlugin.isLoaded()) {\n return;\n }\n var layer = new L.heatLayer();\n\n if (isArray(params.data)) {\n layer.setLatLngs(params.data);\n }\n\n if (isObject(params.options)) {\n layer.setOptions(params.options);\n }\n\n return layer;\n }\n },\n yandex: {\n mustHaveUrl: false,\n createLayer: function(params) {\n var type = params.type || 'map';\n if (!Helpers.YandexLayerPlugin.isLoaded()) {\n return;\n }\n return new L.Yandex(type, params.options);\n }\n },\n imageOverlay: {\n mustHaveUrl: true,\n mustHaveBounds : true,\n createLayer: function(params) {\n return L.imageOverlay(params.url, params.bounds, params.options);\n }\n },\n\n // This \"custom\" type is used to accept every layer that user want to define himself.\n // We can wrap these custom layers like heatmap or yandex, but it means a lot of work/code to wrap the world,\n // so we let user to define their own layer outside the directive,\n // and pass it on \"createLayer\" result for next processes\n custom: {\n createLayer: function (params) {\n if (params.layer instanceof L.Class) {\n return angular.copy(params.layer);\n }\n else {\n $log.error('[AngularJS - Leaflet] A custom layer must be a leaflet Class');\n }\n }\n },\n cartodb: {\n mustHaveUrl: true,\n createLayer: function(params) {\n return cartodb.createLayer(params.map, params.url);\n }\n }\n };\n\n function isValidLayerType(layerDefinition) {\n // Check if the baselayer has a valid type\n if (!isString(layerDefinition.type)) {\n $log.error('[AngularJS - Leaflet] A layer must have a valid type defined.');\n return false;\n }\n\n if (Object.keys(layerTypes).indexOf(layerDefinition.type) === -1) {\n $log.error('[AngularJS - Leaflet] A layer must have a valid type: ' + Object.keys(layerTypes));\n return false;\n }\n\n // Check if the layer must have an URL\n if (layerTypes[layerDefinition.type].mustHaveUrl && !isString(layerDefinition.url)) {\n $log.error('[AngularJS - Leaflet] A base layer must have an url');\n return false;\n }\n\n if (layerTypes[layerDefinition.type].mustHaveData && !isDefined(layerDefinition.data)) {\n $log.error('[AngularJS - Leaflet] The base layer must have a \"data\" array attribute');\n return false;\n }\n\n if(layerTypes[layerDefinition.type].mustHaveLayer && !isDefined(layerDefinition.layer)) {\n $log.error('[AngularJS - Leaflet] The type of layer ' + layerDefinition.type + ' must have an layer defined');\n return false;\n }\n\n if (layerTypes[layerDefinition.type].mustHaveBounds && !isDefined(layerDefinition.bounds)) {\n $log.error('[AngularJS - Leaflet] The type of layer ' + layerDefinition.type + ' must have bounds defined');\n return false ;\n }\n\n if (layerTypes[layerDefinition.type].mustHaveKey && !isDefined(layerDefinition.key)) {\n $log.error('[AngularJS - Leaflet] The type of layer ' + layerDefinition.type + ' must have key defined');\n return false ;\n }\n return true;\n }\n\n function createLayer(layerDefinition) {\n if (!isValidLayerType(layerDefinition)) {\n return;\n }\n\n if (!isString(layerDefinition.name)) {\n $log.error('[AngularJS - Leaflet] A base layer must have a name');\n return;\n }\n if (!isObject(layerDefinition.layerParams)) {\n layerDefinition.layerParams = {};\n }\n if (!isObject(layerDefinition.layerOptions)) {\n layerDefinition.layerOptions = {};\n }\n\n // Mix the layer specific parameters with the general Leaflet options. Although this is an overhead\n // the definition of a base layers is more 'clean' if the two types of parameters are differentiated\n for (var attrname in layerDefinition.layerParams) {\n layerDefinition.layerOptions[attrname] = layerDefinition.layerParams[attrname];\n }\n\n var params = {\n url: layerDefinition.url,\n data: layerDefinition.data,\n options: layerDefinition.layerOptions,\n layer: layerDefinition.layer,\n type: layerDefinition.layerType,\n bounds: layerDefinition.bounds,\n key: layerDefinition.key,\n apiKey: layerDefinition.apiKey,\n pluginOptions: layerDefinition.pluginOptions,\n user: layerDefinition.user\n };\n\n //TODO Add $watch to the layer properties\n return layerTypes[layerDefinition.type].createLayer(params);\n }\n\n return {\n createLayer: createLayer\n };\n});\n","angular.module(\"leaflet-directive\").factory('leafletLegendHelpers', function () {\n\tvar _updateLegend = function(div, legendData, type, url) {\n\t\tdiv.innerHTML = '';\n\t\tif(legendData.error) {\n\t\t\tdiv.innerHTML += '
' + legendData.error.message + '
';\n\t\t} else {\n\t\t\tif (type === 'arcgis') {\n\t\t\t\tfor (var i = 0; i < legendData.layers.length; i++) {\n\t\t\t\t\tvar layer = legendData.layers[i];\n\t\t\t\t\tdiv.innerHTML += '
' + layer.layerName + '
';\n\t\t\t\t\tfor(var j = 0; j < layer.legend.length; j++) {\n\t\t\t\t\t\tvar leg = layer.legend[j];\n\t\t\t\t\t\tdiv.innerHTML +=\n\t\t\t\t\t\t\t'
' +\n\t\t\t\t\t\t\t'
' + leg.label + '
';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (type === 'image') {\n\t\t\t\tdiv.innerHTML = '';\n\t\t\t}\n\t\t}\n\t};\n\n\tvar _getOnAddLegend = function(legendData, legendClass, type, url) {\n\t\treturn function(/*map*/) {\n\t\t\tvar div = L.DomUtil.create('div', legendClass);\n\n\t\t\tif (!L.Browser.touch) {\n\t\t\t\tL.DomEvent.disableClickPropagation(div);\n\t\t\t\tL.DomEvent.on(div, 'mousewheel', L.DomEvent.stopPropagation);\n\t\t\t} else {\n\t\t\t\tL.DomEvent.on(div, 'click', L.DomEvent.stopPropagation);\n\t\t\t}\n\t\t\t_updateLegend(div, legendData, type, url);\n\t\t\treturn div;\n\t\t};\n\t};\n\n\tvar _getOnAddArrayLegend = function(legend, legendClass) {\n\t\treturn function(/*map*/) {\n\t\t\tvar div = L.DomUtil.create('div', legendClass);\n for (var i = 0; i < legend.colors.length; i++) {\n div.innerHTML +=\n '
' +\n '
' + legend.labels[i] + '
';\n }\n if (!L.Browser.touch) {\n\t\t\t\tL.DomEvent.disableClickPropagation(div);\n\t\t\t\tL.DomEvent.on(div, 'mousewheel', L.DomEvent.stopPropagation);\n\t\t\t} else {\n\t\t\t\tL.DomEvent.on(div, 'click', L.DomEvent.stopPropagation);\n\t\t\t}\n return div;\n\t\t};\n\t};\n\n\treturn {\n\t\tgetOnAddLegend: _getOnAddLegend,\n\t\tgetOnAddArrayLegend: _getOnAddArrayLegend,\n\t\tupdateLegend: _updateLegend,\n\t};\n});\n","angular.module(\"leaflet-directive\").factory('leafletMapDefaults', function ($q, leafletHelpers) {\n function _getDefaults() {\n return {\n keyboard: true,\n dragging: true,\n worldCopyJump: false,\n doubleClickZoom: true,\n scrollWheelZoom: true,\n tap: true,\n touchZoom: true,\n zoomControl: true,\n zoomsliderControl: false,\n zoomControlPosition: 'topleft',\n attributionControl: true,\n controls: {\n layers: {\n visible: true,\n position: 'topright',\n collapsed: true\n }\n },\n nominatim: {\n server: ' http://nominatim.openstreetmap.org/search'\n },\n crs: L.CRS.EPSG3857,\n tileLayer: '//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n tileLayerOptions: {\n attribution: '© OpenStreetMap contributors'\n },\n path: {\n weight: 10,\n opacity: 1,\n color: '#0000ff'\n },\n center: {\n lat: 0,\n lng: 0,\n zoom: 1\n }\n };\n }\n\n var isDefined = leafletHelpers.isDefined,\n isObject = leafletHelpers.isObject,\n obtainEffectiveMapId = leafletHelpers.obtainEffectiveMapId,\n defaults = {};\n\n // Get the _defaults dictionary, and override the properties defined by the user\n return {\n reset: function () {\n defaults = {};\n },\n getDefaults: function (scopeId) {\n var mapId = obtainEffectiveMapId(defaults, scopeId);\n return defaults[mapId];\n },\n\n getMapCreationDefaults: function (scopeId) {\n var mapId = obtainEffectiveMapId(defaults, scopeId);\n var d = defaults[mapId];\n\n var mapDefaults = {\n maxZoom: d.maxZoom,\n keyboard: d.keyboard,\n dragging: d.dragging,\n zoomControl: d.zoomControl,\n doubleClickZoom: d.doubleClickZoom,\n scrollWheelZoom: d.scrollWheelZoom,\n tap: d.tap,\n touchZoom: d.touchZoom,\n attributionControl: d.attributionControl,\n worldCopyJump: d.worldCopyJump,\n crs: d.crs\n };\n\n if (isDefined(d.minZoom)) {\n mapDefaults.minZoom = d.minZoom;\n }\n\n if (isDefined(d.zoomAnimation)) {\n mapDefaults.zoomAnimation = d.zoomAnimation;\n }\n\n if (isDefined(d.fadeAnimation)) {\n mapDefaults.fadeAnimation = d.fadeAnimation;\n }\n\n if (isDefined(d.markerZoomAnimation)) {\n mapDefaults.markerZoomAnimation = d.markerZoomAnimation;\n }\n\n if (d.map) {\n for (var option in d.map) {\n mapDefaults[option] = d.map[option];\n }\n }\n\n return mapDefaults;\n },\n\n setDefaults: function (userDefaults, scopeId) {\n var newDefaults = _getDefaults();\n\n if (isDefined(userDefaults)) {\n newDefaults.doubleClickZoom = isDefined(userDefaults.doubleClickZoom) ? userDefaults.doubleClickZoom : newDefaults.doubleClickZoom;\n newDefaults.scrollWheelZoom = isDefined(userDefaults.scrollWheelZoom) ? userDefaults.scrollWheelZoom : newDefaults.doubleClickZoom;\n newDefaults.tap = isDefined(userDefaults.tap) ? userDefaults.tap : newDefaults.tap;\n newDefaults.touchZoom = isDefined(userDefaults.touchZoom) ? userDefaults.touchZoom : newDefaults.doubleClickZoom;\n newDefaults.zoomControl = isDefined(userDefaults.zoomControl) ? userDefaults.zoomControl : newDefaults.zoomControl;\n newDefaults.zoomsliderControl = isDefined(userDefaults.zoomsliderControl) ? userDefaults.zoomsliderControl : newDefaults.zoomsliderControl;\n newDefaults.attributionControl = isDefined(userDefaults.attributionControl) ? userDefaults.attributionControl : newDefaults.attributionControl;\n newDefaults.tileLayer = isDefined(userDefaults.tileLayer) ? userDefaults.tileLayer : newDefaults.tileLayer;\n newDefaults.zoomControlPosition = isDefined(userDefaults.zoomControlPosition) ? userDefaults.zoomControlPosition : newDefaults.zoomControlPosition;\n newDefaults.keyboard = isDefined(userDefaults.keyboard) ? userDefaults.keyboard : newDefaults.keyboard;\n newDefaults.dragging = isDefined(userDefaults.dragging) ? userDefaults.dragging : newDefaults.dragging;\n\n if (isDefined(userDefaults.controls)) {\n angular.extend(newDefaults.controls, userDefaults.controls);\n }\n\n if (isObject(userDefaults.crs)) {\n newDefaults.crs = userDefaults.crs;\n } else if (isDefined(L.CRS[userDefaults.crs])) {\n newDefaults.crs = L.CRS[userDefaults.crs];\n }\n\n if (isDefined(userDefaults.center)) {\n angular.copy(userDefaults.center, newDefaults.center);\n }\n\n if (isDefined(userDefaults.tileLayerOptions)) {\n angular.copy(userDefaults.tileLayerOptions, newDefaults.tileLayerOptions);\n }\n\n if (isDefined(userDefaults.maxZoom)) {\n newDefaults.maxZoom = userDefaults.maxZoom;\n }\n\n if (isDefined(userDefaults.minZoom)) {\n newDefaults.minZoom = userDefaults.minZoom;\n }\n\n if (isDefined(userDefaults.zoomAnimation)) {\n newDefaults.zoomAnimation = userDefaults.zoomAnimation;\n }\n\n if (isDefined(userDefaults.fadeAnimation)) {\n newDefaults.fadeAnimation = userDefaults.fadeAnimation;\n }\n\n if (isDefined(userDefaults.markerZoomAnimation)) {\n newDefaults.markerZoomAnimation = userDefaults.markerZoomAnimation;\n }\n\n if (isDefined(userDefaults.worldCopyJump)) {\n newDefaults.worldCopyJump = userDefaults.worldCopyJump;\n }\n\n if (isDefined(userDefaults.map)) {\n newDefaults.map = userDefaults.map;\n }\n\n if (isDefined(userDefaults.path)) {\n newDefaults.path = userDefaults.path;\n }\n }\n\n var mapId = obtainEffectiveMapId(defaults, scopeId);\n defaults[mapId] = newDefaults;\n return newDefaults;\n }\n };\n});\n","angular.module(\"leaflet-directive\").service('leafletMarkersHelpers', function ($rootScope, $timeout, leafletHelpers, $log, $compile, leafletGeoJsonHelpers) {\n var isDefined = leafletHelpers.isDefined,\n defaultTo = leafletHelpers.defaultTo,\n MarkerClusterPlugin = leafletHelpers.MarkerClusterPlugin,\n AwesomeMarkersPlugin = leafletHelpers.AwesomeMarkersPlugin,\n MakiMarkersPlugin = leafletHelpers.MakiMarkersPlugin,\n ExtraMarkersPlugin = leafletHelpers.ExtraMarkersPlugin,\n safeApply = leafletHelpers.safeApply,\n Helpers = leafletHelpers,\n isString = leafletHelpers.isString,\n isNumber = leafletHelpers.isNumber,\n isObject = leafletHelpers.isObject,\n groups = {},\n geoHlp = leafletGeoJsonHelpers,\n errorHeader = leafletHelpers.errorHeader;\n\n\n var _string = function (marker) {\n //this exists since JSON.stringify barfs on cyclic\n var retStr = '';\n ['_icon', '_latlng', '_leaflet_id', '_map', '_shadow'].forEach(function (prop) {\n retStr += prop + ': ' + defaultTo(marker[prop], 'undefined') + ' \\n';\n });\n return '[leafletMarker] : \\n' + retStr;\n };\n var _log = function (marker, useConsole) {\n var logger = useConsole ? console : $log;\n logger.debug(_string(marker));\n };\n\n var createLeafletIcon = function (iconData) {\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'awesomeMarker') {\n if (!AwesomeMarkersPlugin.isLoaded()) {\n $log.error(errorHeader + ' The AwesomeMarkers Plugin is not loaded.');\n }\n\n return new L.AwesomeMarkers.icon(iconData);\n }\n\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'makiMarker') {\n if (!MakiMarkersPlugin.isLoaded()) {\n $log.error(errorHeader + 'The MakiMarkers Plugin is not loaded.');\n }\n\n return new L.MakiMarkers.icon(iconData);\n }\n\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'extraMarker') {\n if (!ExtraMarkersPlugin.isLoaded()) {\n $log.error(errorHeader + 'The ExtraMarkers Plugin is not loaded.');\n }\n return new L.ExtraMarkers.icon(iconData);\n }\n\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'div') {\n return new L.divIcon(iconData);\n }\n\n // allow for any custom icon to be used... assumes the icon has already been initialized\n if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'icon') {\n return iconData.icon;\n }\n\n var base64icon = \"data:image/png;base64,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\";\n 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=\";\n\n if (!isDefined(iconData) || !isDefined(iconData.iconUrl)) {\n return new L.Icon.Default({\n iconUrl: base64icon,\n shadowUrl: base64shadow,\n iconSize: [25, 41],\n iconAnchor: [12, 41],\n popupAnchor: [1, -34],\n shadowSize: [41, 41]\n });\n }\n\n return new L.Icon(iconData);\n };\n\n var _resetMarkerGroup = function (groupName) {\n if (isDefined(groups[groupName])) {\n groups.splice(groupName, 1);\n }\n };\n\n var _resetMarkerGroups = function () {\n groups = {};\n };\n\n var _deleteMarker = function (marker, map, layers) {\n marker.closePopup();\n // There is no easy way to know if a marker is added to a layer, so we search for it\n // if there are overlays\n if (isDefined(layers) && isDefined(layers.overlays)) {\n for (var key in layers.overlays) {\n if (layers.overlays[key] instanceof L.LayerGroup || layers.overlays[key] instanceof L.FeatureGroup) {\n if (layers.overlays[key].hasLayer(marker)) {\n layers.overlays[key].removeLayer(marker);\n return;\n }\n }\n }\n }\n\n if (isDefined(groups)) {\n for (var groupKey in groups) {\n if (groups[groupKey].hasLayer(marker)) {\n groups[groupKey].removeLayer(marker);\n }\n }\n }\n\n if (map.hasLayer(marker)) {\n map.removeLayer(marker);\n }\n };\n\n var adjustPopupPan = function(marker, map) {\n var containerHeight = marker._popup._container.offsetHeight,\n layerPos = new L.Point(marker._popup._containerLeft, -containerHeight - marker._popup._containerBottom),\n containerPos = map.layerPointToContainerPoint(layerPos);\n if (containerPos !== null) {\n marker._popup._adjustPan();\n }\n };\n\n var compilePopup = function(marker, markerScope) {\n $compile(marker._popup._contentNode)(markerScope);\n };\n\n var updatePopup = function (marker, markerScope, map) {\n //The innerText should be more than 1 once angular has compiled.\n //We need to keep trying until angular has compiled before we _updateLayout and _updatePosition\n //This should take care of any scenario , eg ngincludes, whatever.\n //Is there a better way to check for this?\n var innerText = marker._popup._contentNode.innerText || marker._popup._contentNode.textContent;\n if (innerText.length < 1) {\n $timeout(function () {\n updatePopup(marker, markerScope, map);\n });\n }\n\n //cause a reflow - this is also very important - if we don't do this then the widths are from before $compile\n var reflow = marker._popup._contentNode.offsetWidth;\n\n marker._popup._updateLayout();\n marker._popup._updatePosition();\n\n if (marker._popup.options.autoPan) {\n adjustPopupPan(marker, map);\n }\n\n //using / returning reflow so jshint doesn't moan\n return reflow;\n };\n\n var _manageOpenPopup = function (marker, markerData, map) {\n // The marker may provide a scope returning function used to compile the message\n // default to $rootScope otherwise\n var markerScope = angular.isFunction(markerData.getMessageScope) ? markerData.getMessageScope() : $rootScope,\n compileMessage = isDefined(markerData.compileMessage) ? markerData.compileMessage : true;\n\n if (compileMessage) {\n if (!isDefined(marker._popup) || !isDefined(marker._popup._contentNode)) {\n $log.error(errorHeader + 'Popup is invalid or does not have any content.');\n return false;\n }\n\n compilePopup(marker, markerScope);\n updatePopup(marker, markerData, map);\n }\n };\n\n\n var _manageOpenLabel = function (marker, markerData) {\n var markerScope = angular.isFunction(markerData.getMessageScope) ? markerData.getMessageScope() : $rootScope,\n labelScope = angular.isFunction(markerData.getLabelScope) ? markerData.getLabelScope() : markerScope,\n compileMessage = isDefined(markerData.compileMessage) ? markerData.compileMessage : true;\n\n if (Helpers.LabelPlugin.isLoaded() && isDefined(markerData.label)) {\n if (isDefined(markerData.label.options) && markerData.label.options.noHide === true) {\n marker.showLabel();\n }\n if (compileMessage && isDefined(marker.label)) {\n $compile(marker.label._container)(labelScope);\n }\n }\n };\n\n var _updateMarker = function (markerData, oldMarkerData, marker, name, leafletScope, layers, map) {\n if (!isDefined(oldMarkerData)) {\n return;\n }\n\n // Update the lat-lng property (always present in marker properties)\n if (!geoHlp.validateCoords(markerData)) {\n $log.warn('There are problems with lat-lng data, please verify your marker model');\n _deleteMarker(marker, map, layers);\n return;\n }\n\n // watch is being initialized if old and new object is the same\n var isInitializing = markerData === oldMarkerData;\n\n // Update marker rotation\n if (isDefined(markerData.iconAngle) && oldMarkerData.iconAngle !== markerData.iconAngle) {\n marker.setIconAngle(markerData.iconAngle);\n }\n\n // It is possible that the layer has been removed or the layer marker does not exist\n // Update the layer group if present or move it to the map if not\n if (!isString(markerData.layer)) {\n // There is no layer information, we move the marker to the map if it was in a layer group\n if (isString(oldMarkerData.layer)) {\n // Remove from the layer group that is supposed to be\n if (isDefined(layers.overlays[oldMarkerData.layer]) && layers.overlays[oldMarkerData.layer].hasLayer(marker)) {\n layers.overlays[oldMarkerData.layer].removeLayer(marker);\n marker.closePopup();\n }\n // Test if it is not on the map and add it\n if (!map.hasLayer(marker)) {\n map.addLayer(marker);\n }\n }\n }\n\n if ((isNumber(markerData.opacity) || isNumber(parseFloat(markerData.opacity))) && markerData.opacity !== oldMarkerData.opacity) {\n // There was a different opacity so we update it\n marker.setOpacity(markerData.opacity);\n }\n\n if (isString(markerData.layer) && oldMarkerData.layer !== markerData.layer) {\n // If it was on a layer group we have to remove it\n if (isString(oldMarkerData.layer) && isDefined(layers.overlays[oldMarkerData.layer]) && layers.overlays[oldMarkerData.layer].hasLayer(marker)) {\n layers.overlays[oldMarkerData.layer].removeLayer(marker);\n }\n marker.closePopup();\n\n // Remove it from the map in case the new layer is hidden or there is an error in the new layer\n if (map.hasLayer(marker)) {\n map.removeLayer(marker);\n }\n\n // The markerData.layer is defined so we add the marker to the layer if it is different from the old data\n if (!isDefined(layers.overlays[markerData.layer])) {\n $log.error(errorHeader + 'You must use a name of an existing layer');\n return;\n }\n // Is a group layer?\n var layerGroup = layers.overlays[markerData.layer];\n if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {\n $log.error(errorHeader + 'A marker can only be added to a layer of type \"group\" or \"featureGroup\"');\n return;\n }\n // The marker goes to a correct layer group, so first of all we add it\n layerGroup.addLayer(marker);\n // The marker is automatically added to the map depending on the visibility\n // of the layer, so we only have to open the popup if the marker is in the map\n if (map.hasLayer(marker) && markerData.focus === true) {\n marker.openPopup();\n }\n }\n\n // Update the draggable property\n if (markerData.draggable !== true && oldMarkerData.draggable === true && (isDefined(marker.dragging))) {\n marker.dragging.disable();\n }\n\n if (markerData.draggable === true && oldMarkerData.draggable !== true) {\n // The markerData.draggable property must be true so we update if there wasn't a previous value or it wasn't true\n if (marker.dragging) {\n marker.dragging.enable();\n } else {\n if (L.Handler.MarkerDrag) {\n marker.dragging = new L.Handler.MarkerDrag(marker);\n marker.options.draggable = true;\n marker.dragging.enable();\n }\n }\n }\n\n // Update the icon property\n if (!isObject(markerData.icon)) {\n // If there is no icon property or it's not an object\n if (isObject(oldMarkerData.icon)) {\n // If there was an icon before restore to the default\n marker.setIcon(createLeafletIcon());\n marker.closePopup();\n marker.unbindPopup();\n if (isString(markerData.message)) {\n marker.bindPopup(markerData.message, markerData.popupOptions);\n }\n }\n }\n\n if (isObject(markerData.icon) && isObject(oldMarkerData.icon) && !angular.equals(markerData.icon, oldMarkerData.icon)) {\n var dragG = false;\n if (marker.dragging) {\n dragG = marker.dragging.enabled();\n }\n marker.setIcon(createLeafletIcon(markerData.icon));\n if (dragG) {\n marker.dragging.enable();\n }\n marker.closePopup();\n marker.unbindPopup();\n if (isString(markerData.message)) {\n marker.bindPopup(markerData.message, markerData.popupOptions);\n }\n }\n\n // Update the Popup message property\n if (!isString(markerData.message) && isString(oldMarkerData.message)) {\n marker.closePopup();\n marker.unbindPopup();\n }\n\n // Update the label content or bind a new label if the old one has been removed.\n if (Helpers.LabelPlugin.isLoaded()) {\n if (isDefined(markerData.label) && isDefined(markerData.label.message)) {\n if ('label' in oldMarkerData && 'message' in oldMarkerData.label && !angular.equals(markerData.label.message, oldMarkerData.label.message)) {\n marker.updateLabelContent(markerData.label.message);\n } else if (!angular.isFunction(marker.getLabel) || angular.isFunction(marker.getLabel) && !isDefined(marker.getLabel())) {\n marker.bindLabel(markerData.label.message, markerData.label.options);\n _manageOpenLabel(marker, markerData);\n } else {\n _manageOpenLabel(marker, markerData);\n }\n } else if (!('label' in markerData && !('message' in markerData.label))) {\n if (angular.isFunction(marker.unbindLabel)) {\n marker.unbindLabel();\n }\n }\n }\n\n // There is some text in the popup, so we must show the text or update existing\n if (isString(markerData.message) && !isString(oldMarkerData.message)) {\n // There was no message before so we create it\n marker.bindPopup(markerData.message, markerData.popupOptions);\n }\n\n if (isString(markerData.message) && isString(oldMarkerData.message) && markerData.message !== oldMarkerData.message) {\n // There was a different previous message so we update it\n marker.setPopupContent(markerData.message);\n }\n\n // Update the focus property\n var updatedFocus = false;\n if (markerData.focus !== true && oldMarkerData.focus === true) {\n // If there was a focus property and was true we turn it off\n marker.closePopup();\n updatedFocus = true;\n }\n\n // The markerData.focus property must be true so we update if there wasn't a previous value or it wasn't true\n if (markerData.focus === true && ( !isDefined(oldMarkerData.focus) || oldMarkerData.focus === false) || (isInitializing && markerData.focus === true)) {\n // Reopen the popup when focus is still true\n marker.openPopup();\n updatedFocus = true;\n }\n\n // zIndexOffset adjustment\n if (oldMarkerData.zIndexOffset !== markerData.zIndexOffset) {\n marker.setZIndexOffset(markerData.zIndexOffset);\n }\n\n var markerLatLng = marker.getLatLng();\n var isCluster = (isString(markerData.layer) && Helpers.MarkerClusterPlugin.is(layers.overlays[markerData.layer]));\n // If the marker is in a cluster it has to be removed and added to the layer when the location is changed\n if (isCluster) {\n // The focus has changed even by a user click or programatically\n if (updatedFocus) {\n // We only have to update the location if it was changed programatically, because it was\n // changed by a user drag the marker data has already been updated by the internal event\n // listened by the directive\n if ((markerData.lat !== oldMarkerData.lat) || (markerData.lng !== oldMarkerData.lng)) {\n layers.overlays[markerData.layer].removeLayer(marker);\n marker.setLatLng([markerData.lat, markerData.lng]);\n layers.overlays[markerData.layer].addLayer(marker);\n }\n } else {\n // The marker has possibly moved. It can be moved by a user drag (marker location and data are equal but old\n // data is diferent) or programatically (marker location and data are diferent)\n if ((markerLatLng.lat !== markerData.lat) || (markerLatLng.lng !== markerData.lng)) {\n // The marker was moved by a user drag\n layers.overlays[markerData.layer].removeLayer(marker);\n marker.setLatLng([markerData.lat, markerData.lng]);\n layers.overlays[markerData.layer].addLayer(marker);\n } else if ((markerData.lat !== oldMarkerData.lat) || (markerData.lng !== oldMarkerData.lng)) {\n // The marker was moved programatically\n layers.overlays[markerData.layer].removeLayer(marker);\n marker.setLatLng([markerData.lat, markerData.lng]);\n layers.overlays[markerData.layer].addLayer(marker);\n } else if (isObject(markerData.icon) && isObject(oldMarkerData.icon) && !angular.equals(markerData.icon, oldMarkerData.icon)) {\n layers.overlays[markerData.layer].removeLayer(marker);\n layers.overlays[markerData.layer].addLayer(marker);\n }\n }\n } else if (markerLatLng.lat !== markerData.lat || markerLatLng.lng !== markerData.lng) {\n marker.setLatLng([markerData.lat, markerData.lng]);\n }\n };\n return {\n resetMarkerGroup: _resetMarkerGroup,\n\n resetMarkerGroups: _resetMarkerGroups,\n\n deleteMarker: _deleteMarker,\n\n manageOpenPopup: _manageOpenPopup,\n\n manageOpenLabel: _manageOpenLabel,\n\n createMarker: function (markerData) {\n if (!isDefined(markerData) || !geoHlp.validateCoords(markerData)) {\n $log.error(errorHeader + 'The marker definition is not valid.');\n return;\n }\n var coords = geoHlp.getCoords(markerData);\n\n if (!isDefined(coords)) {\n $log.error(errorHeader + 'Unable to get coordinates from markerData.');\n return;\n }\n\n var markerOptions = {\n icon: createLeafletIcon(markerData.icon),\n title: isDefined(markerData.title) ? markerData.title : '',\n draggable: isDefined(markerData.draggable) ? markerData.draggable : false,\n clickable: isDefined(markerData.clickable) ? markerData.clickable : true,\n riseOnHover: isDefined(markerData.riseOnHover) ? markerData.riseOnHover : false,\n zIndexOffset: isDefined(markerData.zIndexOffset) ? markerData.zIndexOffset : 0,\n iconAngle: isDefined(markerData.iconAngle) ? markerData.iconAngle : 0\n };\n // Add any other options not added above to markerOptions\n for (var markerDatum in markerData) {\n if (markerData.hasOwnProperty(markerDatum) && !markerOptions.hasOwnProperty(markerDatum)) {\n markerOptions[markerDatum] = markerData[markerDatum];\n }\n }\n\n var marker = new L.marker(coords, markerOptions);\n\n if (!isString(markerData.message)) {\n marker.unbindPopup();\n }\n\n return marker;\n },\n\n addMarkerToGroup: function (marker, groupName, groupOptions, map) {\n if (!isString(groupName)) {\n $log.error(errorHeader + 'The marker group you have specified is invalid.');\n return;\n }\n\n if (!MarkerClusterPlugin.isLoaded()) {\n $log.error(errorHeader + \"The MarkerCluster plugin is not loaded.\");\n return;\n }\n if (!isDefined(groups[groupName])) {\n groups[groupName] = new L.MarkerClusterGroup(groupOptions);\n map.addLayer(groups[groupName]);\n }\n groups[groupName].addLayer(marker);\n },\n\n listenMarkerEvents: function (marker, markerData, leafletScope, doWatch, map) {\n marker.on(\"popupopen\", function (/* event */) {\n safeApply(leafletScope, function () {\n if (isDefined(marker._popup) || isDefined(marker._popup._contentNode)) {\n markerData.focus = true;\n _manageOpenPopup(marker, markerData, map);//needed since markerData is now a copy\n }\n });\n });\n marker.on(\"popupclose\", function (/* event */) {\n safeApply(leafletScope, function () {\n markerData.focus = false;\n });\n });\n marker.on(\"add\", function (/* event */) {\n safeApply(leafletScope, function () {\n if ('label' in markerData)\n _manageOpenLabel(marker, markerData);\n });\n });\n },\n\n updateMarker: _updateMarker,\n\n addMarkerWatcher: function (marker, name, leafletScope, layers, map, isDeepWatch) {\n var markerWatchPath = Helpers.getObjectArrayPath(\"markers.\" + name);\n isDeepWatch = defaultTo(isDeepWatch, true);\n\n var clearWatch = leafletScope.$watch(markerWatchPath, function(markerData, oldMarkerData) {\n if (!isDefined(markerData)) {\n _deleteMarker(marker, map, layers);\n clearWatch();\n return;\n }\n _updateMarker(markerData, oldMarkerData, marker, name, leafletScope, layers, map);\n } , isDeepWatch);\n },\n string: _string,\n log: _log\n };\n});\n","angular.module(\"leaflet-directive\").factory('leafletPathsHelpers', function ($rootScope, $log, leafletHelpers) {\n var isDefined = leafletHelpers.isDefined,\n isArray = leafletHelpers.isArray,\n isNumber = leafletHelpers.isNumber,\n isValidPoint = leafletHelpers.isValidPoint;\n var availableOptions = [\n // Path options\n 'stroke', 'weight', 'color', 'opacity',\n 'fill', 'fillColor', 'fillOpacity',\n 'dashArray', 'lineCap', 'lineJoin', 'clickable',\n 'pointerEvents', 'className',\n\n // Polyline options\n 'smoothFactor', 'noClip'\n ];\n function _convertToLeafletLatLngs(latlngs) {\n return latlngs.filter(function(latlng) {\n return isValidPoint(latlng);\n }).map(function (latlng) {\n return _convertToLeafletLatLng(latlng);\n });\n }\n\n function _convertToLeafletLatLng(latlng) {\n if (isArray(latlng)) {\n return new L.LatLng(latlng[0], latlng[1]);\n } else {\n return new L.LatLng(latlng.lat, latlng.lng);\n }\n }\n\n function _convertToLeafletMultiLatLngs(paths) {\n return paths.map(function(latlngs) {\n return _convertToLeafletLatLngs(latlngs);\n });\n }\n\n function _getOptions(path, defaults) {\n var options = {};\n for (var i = 0; i < availableOptions.length; i++) {\n var optionName = availableOptions[i];\n\n if (isDefined(path[optionName])) {\n options[optionName] = path[optionName];\n } else if (isDefined(defaults.path[optionName])) {\n options[optionName] = defaults.path[optionName];\n }\n }\n\n return options;\n }\n\n var _updatePathOptions = function (path, data) {\n var updatedStyle = {};\n for (var i = 0; i < availableOptions.length; i++) {\n var optionName = availableOptions[i];\n if (isDefined(data[optionName])) {\n updatedStyle[optionName] = data[optionName];\n }\n }\n path.setStyle(data);\n };\n\n var _isValidPolyline = function(latlngs) {\n if (!isArray(latlngs)) {\n return false;\n }\n for (var i = 0; i < latlngs.length; i++) {\n var point = latlngs[i];\n if (!isValidPoint(point)) {\n return false;\n }\n }\n return true;\n };\n\n var pathTypes = {\n polyline: {\n isValid: function(pathData) {\n var latlngs = pathData.latlngs;\n return _isValidPolyline(latlngs);\n },\n createPath: function(options) {\n return new L.Polyline([], options);\n },\n setPath: function(path, data) {\n path.setLatLngs(_convertToLeafletLatLngs(data.latlngs));\n _updatePathOptions(path, data);\n return;\n }\n },\n multiPolyline: {\n isValid: function(pathData) {\n var latlngs = pathData.latlngs;\n if (!isArray(latlngs)) {\n return false;\n }\n\n for (var i in latlngs) {\n var polyline = latlngs[i];\n if (!_isValidPolyline(polyline)) {\n return false;\n }\n }\n\n return true;\n },\n createPath: function(options) {\n return new L.multiPolyline([[[0,0],[1,1]]], options);\n },\n setPath: function(path, data) {\n path.setLatLngs(_convertToLeafletMultiLatLngs(data.latlngs));\n _updatePathOptions(path, data);\n return;\n }\n } ,\n polygon: {\n isValid: function(pathData) {\n var latlngs = pathData.latlngs;\n return _isValidPolyline(latlngs);\n },\n createPath: function(options) {\n return new L.Polygon([], options);\n },\n setPath: function(path, data) {\n path.setLatLngs(_convertToLeafletLatLngs(data.latlngs));\n _updatePathOptions(path, data);\n return;\n }\n },\n multiPolygon: {\n isValid: function(pathData) {\n var latlngs = pathData.latlngs;\n\n if (!isArray(latlngs)) {\n return false;\n }\n\n for (var i in latlngs) {\n var polyline = latlngs[i];\n if (!_isValidPolyline(polyline)) {\n return false;\n }\n }\n\n return true;\n },\n createPath: function(options) {\n return new L.MultiPolygon([[[0,0],[1,1],[0,1]]], options);\n },\n setPath: function(path, data) {\n path.setLatLngs(_convertToLeafletMultiLatLngs(data.latlngs));\n _updatePathOptions(path, data);\n return;\n }\n },\n rectangle: {\n isValid: function(pathData) {\n var latlngs = pathData.latlngs;\n\n if (!isArray(latlngs) || latlngs.length !== 2) {\n return false;\n }\n\n for (var i in latlngs) {\n var point = latlngs[i];\n if (!isValidPoint(point)) {\n return false;\n }\n }\n\n return true;\n },\n createPath: function(options) {\n return new L.Rectangle([[0,0],[1,1]], options);\n },\n setPath: function(path, data) {\n path.setBounds(new L.LatLngBounds(_convertToLeafletLatLngs(data.latlngs)));\n _updatePathOptions(path, data);\n }\n },\n circle: {\n isValid: function(pathData) {\n var point= pathData.latlngs;\n return isValidPoint(point) && isNumber(pathData.radius);\n },\n createPath: function(options) {\n return new L.Circle([0,0], 1, options);\n },\n setPath: function(path, data) {\n path.setLatLng(_convertToLeafletLatLng(data.latlngs));\n if (isDefined(data.radius)) {\n path.setRadius(data.radius);\n }\n _updatePathOptions(path, data);\n }\n },\n circleMarker: {\n isValid: function(pathData) {\n var point= pathData.latlngs;\n return isValidPoint(point) && isNumber(pathData.radius);\n },\n createPath: function(options) {\n return new L.CircleMarker([0,0], options);\n },\n setPath: function(path, data) {\n path.setLatLng(_convertToLeafletLatLng(data.latlngs));\n if (isDefined(data.radius)) {\n path.setRadius(data.radius);\n }\n _updatePathOptions(path, data);\n }\n }\n };\n\n var _getPathData = function(path) {\n var pathData = {};\n if (path.latlngs) {\n pathData.latlngs = path.latlngs;\n }\n\n if (path.radius) {\n pathData.radius = path.radius;\n }\n\n return pathData;\n };\n\n return {\n setPathOptions: function(leafletPath, pathType, data) {\n if(!isDefined(pathType)) {\n pathType = \"polyline\";\n }\n pathTypes[pathType].setPath(leafletPath, data);\n },\n createPath: function(name, path, defaults) {\n if(!isDefined(path.type)) {\n path.type = \"polyline\";\n }\n var options = _getOptions(path, defaults);\n var pathData = _getPathData(path);\n\n if (!pathTypes[path.type].isValid(pathData)) {\n $log.error(\"[AngularJS - Leaflet] Invalid data passed to the \" + path.type + \" path\");\n return;\n }\n\n return pathTypes[path.type].createPath(options);\n }\n };\n});\n","angular.module(\"leaflet-directive\")\n.service('leafletWatchHelpers', function (){\n\n var _maybe = function(scope, watchFunctionName, thingToWatchStr, watchOptions, initCb){\n //watchOptions.isDeep is/should be ignored in $watchCollection\n var unWatch = scope[watchFunctionName](thingToWatchStr, function(newValue, oldValue) {\n initCb(newValue, oldValue);\n if(!watchOptions.doWatch)\n unWatch();\n }, watchOptions.isDeep);\n\n return unWatch;\n };\n\n /*\n @name: maybeWatch\n @description: Utility to watch something once or forever.\n @returns unWatch function\n @param watchOptions - see markersWatchOptions and or derrivatives. This object is used\n to set watching to once and its watch depth.\n */\n var _maybeWatch = function(scope, thingToWatchStr, watchOptions, initCb){\n return _maybe(scope, '$watch', thingToWatchStr, watchOptions, initCb);\n };\n\n /*\n @name: _maybeWatchCollection\n @description: Utility to watch something once or forever.\n @returns unWatch function\n @param watchOptions - see markersWatchOptions and or derrivatives. This object is used\n to set watching to once and its watch depth.\n */\n var _maybeWatchCollection = function(scope, thingToWatchStr, watchOptions, initCb){\n return _maybe(scope, '$watchCollection', thingToWatchStr, watchOptions, initCb);\n };\n\n return {\n maybeWatch: _maybeWatch,\n maybeWatchCollection: _maybeWatchCollection\n };\n});\n","angular.module(\"leaflet-directive\").factory('nominatimService', function ($q, $http, leafletHelpers, leafletMapDefaults) {\n var isDefined = leafletHelpers.isDefined;\n\n return {\n query: function(address, mapId) {\n var defaults = leafletMapDefaults.getDefaults(mapId);\n var url = defaults.nominatim.server;\n var df = $q.defer();\n\n $http.get(url, { params: { format: 'json', limit: 1, q: address } }).success(function(data) {\n if (data.length > 0 && isDefined(data[0].boundingbox)) {\n df.resolve(data[0]);\n } else {\n df.reject('[Nominatim] Invalid address');\n }\n });\n\n return df.promise;\n }\n };\n});\n","angular.module(\"leaflet-directive\").directive('bounds', function ($log, $timeout, $http, leafletHelpers, nominatimService, leafletBoundsHelpers) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: [ 'leaflet' ],\n\n link: function(scope, element, attrs, controller) {\n var isDefined = leafletHelpers.isDefined;\n var createLeafletBounds = leafletBoundsHelpers.createLeafletBounds;\n var leafletScope = controller[0].getLeafletScope();\n var mapController = controller[0];\n var errorHeader = leafletHelpers.errorHeader + ' [Bounds] ';\n\n var emptyBounds = function(bounds) {\n return (bounds._southWest.lat === 0 && bounds._southWest.lng === 0 &&\n bounds._northEast.lat === 0 && bounds._northEast.lng === 0);\n };\n\n mapController.getMap().then(function (map) {\n leafletScope.$on('boundsChanged', function (event) {\n var scope = event.currentScope;\n var bounds = map.getBounds();\n\n if (emptyBounds(bounds) || scope.settingBoundsFromScope) {\n return;\n }\n var newScopeBounds = {\n northEast: {\n lat: bounds._northEast.lat,\n lng: bounds._northEast.lng\n },\n southWest: {\n lat: bounds._southWest.lat,\n lng: bounds._southWest.lng\n },\n options: bounds.options\n };\n if (!angular.equals(scope.bounds, newScopeBounds)) {\n scope.bounds = newScopeBounds;\n }\n });\n\n var lastNominatimQuery;\n leafletScope.$watch('bounds', function (bounds) {\n if (isDefined(bounds.address) && bounds.address !== lastNominatimQuery) {\n scope.settingBoundsFromScope = true;\n nominatimService.query(bounds.address, attrs.id).then(function(data) {\n var b = data.boundingbox;\n var newBounds = [ [ b[0], b[2]], [ b[1], b[3]] ];\n map.fitBounds(newBounds);\n }, function(errMsg) {\n $log.error(errorHeader + ' ' + errMsg + '.');\n });\n lastNominatimQuery = bounds.address;\n $timeout( function() {\n scope.settingBoundsFromScope = false;\n });\n return;\n }\n\n var leafletBounds = createLeafletBounds(bounds);\n if (leafletBounds && !map.getBounds().equals(leafletBounds)) {\n scope.settingBoundsFromScope = true;\n map.fitBounds(leafletBounds, bounds.options);\n $timeout( function() {\n scope.settingBoundsFromScope = false;\n });\n }\n }, true);\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\").directive('center',\n function ($log, $q, $location, $timeout, leafletMapDefaults, leafletHelpers, leafletBoundsHelpers, leafletEvents) {\n\n var isDefined = leafletHelpers.isDefined,\n isNumber = leafletHelpers.isNumber,\n isSameCenterOnMap = leafletHelpers.isSameCenterOnMap,\n safeApply = leafletHelpers.safeApply,\n isValidCenter = leafletHelpers.isValidCenter,\n isValidBounds = leafletBoundsHelpers.isValidBounds,\n isUndefinedOrEmpty = leafletHelpers.isUndefinedOrEmpty,\n errorHeader = leafletHelpers.errorHeader;\n\n var shouldInitializeMapWithBounds = function(bounds, center) {\n return isDefined(bounds) && isValidBounds(bounds) && isUndefinedOrEmpty(center);\n };\n\n var _leafletCenter;\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: 'leaflet',\n controller: function () {\n _leafletCenter = $q.defer();\n this.getCenter = function() {\n return _leafletCenter.promise;\n };\n },\n link: function(scope, element, attrs, controller) {\n var leafletScope = controller.getLeafletScope(),\n centerModel = leafletScope.center;\n\n controller.getMap().then(function(map) {\n var defaults = leafletMapDefaults.getDefaults(attrs.id);\n\n if (attrs.center.search(\"-\") !== -1) {\n $log.error(errorHeader + ' The \"center\" variable can\\'t use a \"-\" on its key name: \"' + attrs.center + '\".');\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n return;\n } else if (shouldInitializeMapWithBounds(leafletScope.bounds, centerModel)) {\n map.fitBounds(leafletBoundsHelpers.createLeafletBounds(leafletScope.bounds), leafletScope.bounds.options);\n centerModel = map.getCenter();\n safeApply(leafletScope, function (scope) {\n angular.extend(scope.center,{\n lat: map.getCenter().lat,\n lng: map.getCenter().lng,\n zoom: map.getZoom(),\n autoDiscover: false\n });\n });\n safeApply(leafletScope, function (scope) {\n var mapBounds = map.getBounds();\n scope.bounds = {\n northEast: {\n lat: mapBounds._northEast.lat,\n lng: mapBounds._northEast.lng\n },\n southWest: {\n lat: mapBounds._southWest.lat,\n lng: mapBounds._southWest.lng\n }\n };\n });\n } else if (!isDefined(centerModel)) {\n $log.error(errorHeader + ' The \"center\" property is not defined in the main scope');\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n return;\n } else if (!(isDefined(centerModel.lat) && isDefined(centerModel.lng)) && !isDefined(centerModel.autoDiscover)) {\n angular.copy(defaults.center, centerModel);\n }\n\n var urlCenterHash, mapReady;\n if (attrs.urlHashCenter === \"yes\") {\n var extractCenterFromUrl = function() {\n var search = $location.search();\n var centerParam;\n if (isDefined(search.c)) {\n var cParam = search.c.split(\":\");\n if (cParam.length === 3) {\n centerParam = { lat: parseFloat(cParam[0]), lng: parseFloat(cParam[1]), zoom: parseInt(cParam[2], 10) };\n }\n }\n return centerParam;\n };\n urlCenterHash = extractCenterFromUrl();\n\n leafletScope.$on('$locationChangeSuccess', function(event) {\n var scope = event.currentScope;\n //$log.debug(\"updated location...\");\n var urlCenter = extractCenterFromUrl();\n if (isDefined(urlCenter) && !isSameCenterOnMap(urlCenter, map)) {\n //$log.debug(\"updating center model...\", urlCenter);\n angular.extend(scope.center, {\n lat: urlCenter.lat,\n lng: urlCenter.lng,\n zoom: urlCenter.zoom\n });\n }\n });\n }\n\n leafletScope.$watch(\"center\", function(center) {\n //$log.debug(\"updated center model...\");\n // The center from the URL has priority\n if (isDefined(urlCenterHash)) {\n angular.copy(urlCenterHash, center);\n urlCenterHash = undefined;\n }\n\n if (!isValidCenter(center) && center.autoDiscover !== true) {\n $log.warn(errorHeader + \" invalid 'center'\");\n //map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n return;\n }\n\n if (center.autoDiscover === true) {\n if (!isNumber(center.zoom)) {\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n }\n if (isNumber(center.zoom) && center.zoom > defaults.center.zoom) {\n map.locate({ setView: true, maxZoom: center.zoom });\n } else if (isDefined(defaults.maxZoom)) {\n map.locate({ setView: true, maxZoom: defaults.maxZoom });\n } else {\n map.locate({ setView: true });\n }\n return;\n }\n\n if (mapReady && isSameCenterOnMap(center, map)) {\n //$log.debug(\"no need to update map again.\");\n return;\n }\n\n //$log.debug(\"updating map center...\", center);\n leafletScope.settingCenterFromScope = true;\n map.setView([center.lat, center.lng], center.zoom);\n leafletEvents.notifyCenterChangedToBounds(leafletScope, map);\n $timeout(function() {\n leafletScope.settingCenterFromScope = false;\n //$log.debug(\"allow center scope updates\");\n });\n }, true);\n\n map.whenReady(function() {\n mapReady = true;\n });\n\n map.on('moveend', function(/* event */) {\n // Resolve the center after the first map position\n _leafletCenter.resolve();\n leafletEvents.notifyCenterUrlHashChanged(leafletScope, map, attrs, $location.search());\n //$log.debug(\"updated center on map...\");\n if (isSameCenterOnMap(centerModel, map) || scope.settingCenterFromScope) {\n //$log.debug(\"same center in model, no need to update again.\");\n return;\n }\n safeApply(leafletScope, function(scope) {\n if (!leafletScope.settingCenterFromScope) {\n //$log.debug(\"updating center model...\", map.getCenter(), map.getZoom());\n angular.extend(scope.center,{\n lat: map.getCenter().lat,\n lng: map.getCenter().lng,\n zoom: map.getZoom(),\n autoDiscover: false\n });\n }\n leafletEvents.notifyCenterChangedToBounds(leafletScope, map);\n });\n });\n\n if (centerModel.autoDiscover === true) {\n map.on('locationerror', function() {\n $log.warn(errorHeader + \" The Geolocation API is unauthorized on this page.\");\n if (isValidCenter(centerModel)) {\n map.setView([centerModel.lat, centerModel.lng], centerModel.zoom);\n leafletEvents.notifyCenterChangedToBounds(leafletScope, map);\n } else {\n map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom);\n leafletEvents.notifyCenterChangedToBounds(leafletScope, map);\n }\n });\n }\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\").directive('controls', function ($log, leafletHelpers, leafletControlHelpers) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: '?^leaflet',\n\n link: function(scope, element, attrs, controller) {\n if(!controller) {\n return;\n }\n\n var createControl = leafletControlHelpers.createControl;\n var isValidControlType = leafletControlHelpers.isValidControlType;\n var leafletScope = controller.getLeafletScope();\n var isDefined = leafletHelpers.isDefined;\n var leafletControls = {};\n var errorHeader = leafletHelpers.errorHeader + ' [Controls] ';\n\n controller.getMap().then(function(map) {\n\n leafletScope.$watchCollection('controls', function(newControls) {\n\n // Delete controls from the array\n for (var name in leafletControls) {\n if (!isDefined(newControls[name])) {\n if (map.hasControl(leafletControls[name])) {\n map.removeControl(leafletControls[name]);\n }\n delete leafletControls[name];\n }\n }\n\n for (var newName in newControls) {\n var control;\n\n var controlType = isDefined(newControls[newName].type) ? newControls[newName].type : newName;\n\n if (!isValidControlType(controlType)) {\n $log.error(errorHeader + ' Invalid control type: ' + controlType + '.');\n return;\n }\n\n if (controlType !== 'custom') {\n control = createControl(controlType, newControls[newName]);\n } else {\n control = newControls[newName];\n }\n map.addControl(control);\n\n leafletControls[newName] = control;\n }\n\n });\n\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\").directive(\"decorations\", function($log, leafletHelpers) {\n\treturn {\n\t\trestrict: \"A\",\n\t\tscope: false,\n\t\treplace: false,\n\t\trequire: 'leaflet',\n\n\t\tlink: function(scope, element, attrs, controller) {\n\t\t\tvar leafletScope = controller.getLeafletScope(),\n\t\t\t\tPolylineDecoratorPlugin = leafletHelpers.PolylineDecoratorPlugin,\n\t\t\t\tisDefined = leafletHelpers.isDefined,\n\t\t\t\tleafletDecorations = {};\n\n\t\t\t/* Creates an \"empty\" decoration with a set of coordinates, but no pattern. */\n\t\t\tfunction createDecoration(options) {\n\t\t\t\tif (isDefined(options) && isDefined(options.coordinates)) {\n\t\t\t\t\tif (!PolylineDecoratorPlugin.isLoaded()) {\n\t\t\t\t\t\t$log.error('[AngularJS - Leaflet] The PolylineDecorator Plugin is not loaded.');\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn L.polylineDecorator(options.coordinates);\n\t\t\t}\n\n\t\t\t/* Updates the path and the patterns for the provided decoration, and returns the decoration. */\n\t\t\tfunction setDecorationOptions(decoration, options) {\n\t\t\t\tif (isDefined(decoration) && isDefined(options)) {\n\t\t\t\t\tif (isDefined(options.coordinates) && isDefined(options.patterns)) {\n\t\t\t\t\t\tdecoration.setPaths(options.coordinates);\n\t\t\t\t\t\tdecoration.setPatterns(options.patterns);\n\t\t\t\t\t\treturn decoration;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcontroller.getMap().then(function(map) {\n\t\t\t\tleafletScope.$watch(\"decorations\", function(newDecorations) {\n\t\t\t\t\tfor (var name in leafletDecorations) {\n\t\t\t\t\t\tif (!isDefined(newDecorations[name]) || !angular.equals(newDecorations[name], leafletDecorations)) {\n\t\t\t\t\t\t\tmap.removeLayer(leafletDecorations[name]);\n\t\t\t\t\t\t\tdelete leafletDecorations[name];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (var newName in newDecorations) {\n\t\t\t\t\t\tvar decorationData = newDecorations[newName],\n\t\t\t\t\t\t\tnewDecoration = createDecoration(decorationData);\n\n\t\t\t\t\t\tif (isDefined(newDecoration)) {\n\t\t\t\t\t\t\tleafletDecorations[newName] = newDecoration;\n\t\t\t\t\t\t\tmap.addLayer(newDecoration);\n\t\t\t\t\t\t\tsetDecorationOptions(newDecoration, decorationData);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, true);\n\t\t\t});\n\t\t}\n\t};\n});\n","angular.module(\"leaflet-directive\").directive('eventBroadcast', function ($log, $rootScope, leafletHelpers, leafletEvents, leafletIterators) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: 'leaflet',\n\n link: function(scope, element, attrs, controller) {\n var isObject = leafletHelpers.isObject,\n isDefined = leafletHelpers.isDefined,\n leafletScope = controller.getLeafletScope(),\n eventBroadcast = leafletScope.eventBroadcast,\n availableMapEvents = leafletEvents.getAvailableMapEvents(),\n addEvents = leafletEvents.addEvents;\n\n controller.getMap().then(function(map) {\n\n var mapEvents = [],\n logic = \"broadcast\";\n\n // We have a possible valid object\n if (!isDefined(eventBroadcast.map)) {\n // We do not have events enable/disable do we do nothing (all enabled by default)\n mapEvents = availableMapEvents;\n } else if (!isObject(eventBroadcast.map)) {\n // Not a valid object\n $log.warn(\"[AngularJS - Leaflet] event-broadcast.map must be an object check your model.\");\n } else {\n // We have a possible valid map object\n // Event propadation logic\n if (eventBroadcast.map.logic !== \"emit\" && eventBroadcast.map.logic !== \"broadcast\") {\n // This is an error\n $log.warn(\"[AngularJS - Leaflet] Available event propagation logic are: 'emit' or 'broadcast'.\");\n } else {\n logic = eventBroadcast.map.logic;\n }\n\n if (!(isObject(eventBroadcast.map.enable) && eventBroadcast.map.enable.length >= 0)) {\n $log.warn(\"[AngularJS - Leaflet] event-broadcast.map.enable must be an object check your model.\");\n } else {\n // Enable events\n leafletIterators.each(eventBroadcast.map.enable, function(eventName) {\n // Do we have already the event enabled?\n if (mapEvents.indexOf(eventName) === -1 && availableMapEvents.indexOf(eventName) !== -1) {\n mapEvents.push(eventName);\n }\n });\n }\n\n }\n // as long as the map is removed in the root leaflet directive we\n // do not need ot clean up the events as leaflet does it itself\n addEvents(map, mapEvents, \"eventName\", leafletScope, logic);\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\")\n.directive('geojson', function ($log, $rootScope, leafletData, leafletHelpers,\n leafletWatchHelpers, leafletDirectiveControlsHelpers,leafletIterators,\n leafletGeoJsonEvents) {\n\n var _maybeWatch = leafletWatchHelpers.maybeWatch,\n _watchOptions = leafletHelpers.watchOptions,\n _extendDirectiveControls = leafletDirectiveControlsHelpers.extend,\n hlp = leafletHelpers,\n $it = leafletIterators;\n\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: 'leaflet',\n\n link: function(scope, element, attrs, controller) {\n var isDefined = leafletHelpers.isDefined,\n leafletScope = controller.getLeafletScope(),\n leafletGeoJSON = {},\n _hasSetLeafletData = false;\n\n controller.getMap().then(function(map) {\n var watchOptions = leafletScope.geojsonWatchOptions || _watchOptions;\n\n var _hookUpEvents = function(geojson, maybeName){\n var onEachFeature;\n\n if (angular.isFunction(geojson.onEachFeature)) {\n onEachFeature = geojson.onEachFeature;\n } else {\n onEachFeature = function(feature, layer) {\n if (leafletHelpers.LabelPlugin.isLoaded() && isDefined(feature.properties.description)) {\n layer.bindLabel(feature.properties.description);\n }\n\n leafletGeoJsonEvents.bindEvents(layer, null, feature,\n leafletScope, maybeName,\n {resetStyleOnMouseout: geojson.resetStyleOnMouseout,\n mapId: attrs.id});\n };\n }\n return onEachFeature;\n };\n\n var isNested = (hlp.isDefined(attrs.geojsonNested) &&\n hlp.isTruthy(attrs.geojsonNested));\n\n var _clean = function(){\n if(!leafletGeoJSON)\n return;\n var _remove = function(lObject) {\n if (isDefined(lObject) && map.hasLayer(lObject)) {\n map.removeLayer(lObject);\n }\n };\n if(isNested) {\n $it.each(leafletGeoJSON, function(lObject) {\n _remove(lObject);\n });\n return;\n }\n _remove(leafletGeoJSON);\n };\n\n var _addGeojson = function(model, maybeName){\n var geojson = angular.copy(model);\n if (!(isDefined(geojson) && isDefined(geojson.data))) {\n return;\n }\n var onEachFeature = _hookUpEvents(geojson, maybeName);\n\n if (!isDefined(geojson.options)) {\n //right here is why we use a clone / copy (we modify and thus)\n //would kick of a watcher.. we need to be more careful everywhere\n //for stuff like this\n geojson.options = {\n style: geojson.style,\n filter: geojson.filter,\n onEachFeature: onEachFeature,\n pointToLayer: geojson.pointToLayer\n };\n }\n\n var lObject = L.geoJson(geojson.data, geojson.options);\n\n if(maybeName && hlp.isString(maybeName)){\n leafletGeoJSON[maybeName] = lObject;\n }\n else{\n leafletGeoJSON = lObject;\n }\n\n lObject.addTo(map);\n\n if(!_hasSetLeafletData){//only do this once and play with the same ref forever\n _hasSetLeafletData = true;\n leafletData.setGeoJSON(leafletGeoJSON, attrs.id);\n }\n };\n\n var _create = function(model){\n _clean();\n if(isNested) {\n if(!model || !Object.keys(model).length)\n return;\n $it.each(model, function(m, name) {\n //name could be layerName and or groupName\n //for now it is not tied to a layer\n _addGeojson(m,name);\n });\n return;\n }\n _addGeojson(model);\n };\n\n _extendDirectiveControls(attrs.id, 'geojson', _create, _clean);\n\n _maybeWatch(leafletScope,'geojson', watchOptions, function(geojson){\n _create(geojson);\n });\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\").directive('layercontrol', function ($filter, $log, leafletData, leafletHelpers) {\n return {\n restrict: \"E\",\n scope: {\n icons: '=?',\n autoHideOpacity: '=?', // Hide other opacity controls when one is activated.\n showGroups: '=?', // Hide other opacity controls when one is activated.\n title: '@',\n baseTitle: '@',\n overlaysTitle: '@'\n },\n replace: true,\n transclude: false,\n require: '^leaflet',\n controller: function ($scope, $element, $sce) {\n $log.debug('[Angular Directive - Layers] layers', $scope, $element);\n var safeApply = leafletHelpers.safeApply,\n isDefined = leafletHelpers.isDefined;\n angular.extend($scope, {\n baselayer: '',\n oldGroup: '',\n layerProperties: {},\n groupProperties: {},\n rangeIsSupported: leafletHelpers.rangeIsSupported(),\n changeBaseLayer: function(key, e) {\n leafletHelpers.safeApply($scope, function(scp) {\n scp.baselayer = key;\n leafletData.getMap().then(function(map) {\n leafletData.getLayers().then(function(leafletLayers) {\n if(map.hasLayer(leafletLayers.baselayers[key])) {\n return;\n }\n for(var i in scp.layers.baselayers) {\n scp.layers.baselayers[i].icon = scp.icons.unradio;\n if(map.hasLayer(leafletLayers.baselayers[i])) {\n map.removeLayer(leafletLayers.baselayers[i]);\n }\n }\n map.addLayer(leafletLayers.baselayers[key]);\n scp.layers.baselayers[key].icon = $scope.icons.radio;\n });\n });\n });\n e.preventDefault();\n },\n moveLayer: function(ly, newIndex, e) {\n var delta = Object.keys($scope.layers.baselayers).length;\n if(newIndex >= (1+delta) && newIndex <= ($scope.overlaysArray.length+delta)) {\n var oldLy;\n for(var key in $scope.layers.overlays) {\n if($scope.layers.overlays[key].index === newIndex) {\n oldLy = $scope.layers.overlays[key];\n break;\n }\n }\n if(oldLy) {\n safeApply($scope, function() {\n oldLy.index = ly.index;\n ly.index = newIndex;\n });\n }\n }\n e.stopPropagation();\n e.preventDefault();\n },\n initIndex: function(layer, idx) {\n var delta = Object.keys($scope.layers.baselayers).length;\n layer.index = isDefined(layer.index)? layer.index:idx+delta+1;\n },\n initGroup: function(groupName) {\n $scope.groupProperties[groupName] = $scope.groupProperties[groupName]? $scope.groupProperties[groupName]:{};\n },\n toggleOpacity: function(e, layer) {\n if(layer.visible) {\n if($scope.autoHideOpacity && !$scope.layerProperties[layer.name].opacityControl) {\n for(var k in $scope.layerProperties) {\n $scope.layerProperties[k].opacityControl = false;\n }\n }\n $scope.layerProperties[layer.name].opacityControl = !$scope.layerProperties[layer.name].opacityControl;\n }\n e.stopPropagation();\n e.preventDefault();\n },\n toggleLegend: function(layer) {\n $scope.layerProperties[layer.name].showLegend = !$scope.layerProperties[layer.name].showLegend;\n },\n showLegend: function(layer) {\n return layer.legend && $scope.layerProperties[layer.name].showLegend;\n },\n unsafeHTML: function(html) {\n return $sce.trustAsHtml(html);\n },\n getOpacityIcon: function(layer) {\n return layer.visible && $scope.layerProperties[layer.name].opacityControl? $scope.icons.close:$scope.icons.open;\n },\n getGroupIcon: function(group) {\n return group.visible? $scope.icons.check:$scope.icons.uncheck;\n },\n changeOpacity: function(layer) {\n var op = $scope.layerProperties[layer.name].opacity;\n leafletData.getMap().then(function(map) {\n leafletData.getLayers().then(function(leafletLayers) {\n var ly;\n for(var k in $scope.layers.overlays) {\n if($scope.layers.overlays[k] === layer) {\n ly = leafletLayers.overlays[k];\n break;\n }\n }\n\n if(map.hasLayer(ly)) {\n if(ly.setOpacity) {\n ly.setOpacity(op/100);\n }\n if(ly.getLayers && ly.eachLayer) {\n ly.eachLayer(function(lay) {\n if(lay.setOpacity) {\n lay.setOpacity(op/100);\n }\n });\n }\n }\n });\n });\n },\n changeGroupVisibility: function(groupName) {\n if(!isDefined($scope.groupProperties[groupName])) {\n return;\n }\n var visible = $scope.groupProperties[groupName].visible;\n for(var k in $scope.layers.overlays) {\n var layer = $scope.layers.overlays[k];\n if(layer.group === groupName) {\n layer.visible = visible;\n }\n }\n }\n });\n\n var div = $element.get(0);\n if (!L.Browser.touch) {\n L.DomEvent.disableClickPropagation(div);\n L.DomEvent.on(div, 'mousewheel', L.DomEvent.stopPropagation);\n } else {\n L.DomEvent.on(div, 'click', L.DomEvent.stopPropagation);\n }\n },\n template:\n '
' +\n '

{{ title }}

' +\n '
' +\n '
{{ baseTitle }}
' +\n '
' +\n '' +\n '
' +\n '
' +\n '
' +\n '
{{ overlaysTitle }}
' +\n '
' +\n '
' +\n ''+\n ''+\n '
' +\n ' ' +\n ' ' +\n ' ' +\n '' +\n '
' +\n '
' +\n '
' +\n '' +\n '' +\n '' +\n '
Range is not supported in this browser
' +\n '
' +\n '
' +\n '
' +\n '
' +\n '
',\n link: function(scope, element, attrs, controller) {\n var isDefined = leafletHelpers.isDefined,\n leafletScope = controller.getLeafletScope(),\n layers = leafletScope.layers;\n\n scope.$watch('icons', function() {\n var defaultIcons = {\n uncheck: 'fa fa-square-o',\n check: 'fa fa-check-square-o',\n radio: 'fa fa-dot-circle-o',\n unradio: 'fa fa-circle-o',\n up: 'fa fa-angle-up',\n down: 'fa fa-angle-down',\n open: 'fa fa-angle-double-down',\n close: 'fa fa-angle-double-up',\n toggleLegend: 'fa fa-pencil-square-o'\n };\n if(isDefined(scope.icons)) {\n angular.extend(defaultIcons, scope.icons);\n angular.extend(scope.icons, defaultIcons);\n } else {\n scope.icons = defaultIcons;\n }\n });\n\n // Setting layer stack order.\n attrs.order = (isDefined(attrs.order) && (attrs.order === 'normal' || attrs.order === 'reverse'))? attrs.order:'normal';\n scope.order = attrs.order === 'normal';\n scope.orderNumber = attrs.order === 'normal'? -1:1;\n\n scope.layers = layers;\n controller.getMap().then(function(map) {\n leafletScope.$watch('layers.baselayers', function(newBaseLayers) {\n var baselayersArray = {};\n leafletData.getLayers().then(function(leafletLayers) {\n var key;\n for(key in newBaseLayers) {\n var layer = newBaseLayers[key];\n layer.icon = scope.icons[map.hasLayer(leafletLayers.baselayers[key])? 'radio':'unradio'];\n baselayersArray[key] = layer;\n }\n scope.baselayersArray = baselayersArray;\n });\n });\n\n leafletScope.$watch('layers.overlays', function(newOverlayLayers) {\n var overlaysArray = [];\n var groupVisibleCount = {};\n leafletData.getLayers().then(function(leafletLayers) {\n var key;\n for(key in newOverlayLayers) {\n var layer = newOverlayLayers[key];\n layer.icon = scope.icons[(layer.visible? 'check':'uncheck')];\n overlaysArray.push(layer);\n if(!isDefined(scope.layerProperties[layer.name])) {\n scope.layerProperties[layer.name] = {\n opacity: isDefined(layer.layerOptions.opacity)? layer.layerOptions.opacity*100:100,\n opacityControl: false,\n showLegend: true\n };\n }\n if(isDefined(layer.group)) {\n if(!isDefined(scope.groupProperties[layer.group])) {\n scope.groupProperties[layer.group] = {\n visible: false\n };\n }\n groupVisibleCount[layer.group] = isDefined(groupVisibleCount[layer.group])? groupVisibleCount[layer.group]:{\n count: 0,\n visibles: 0\n };\n groupVisibleCount[layer.group].count++;\n if(layer.visible) {\n groupVisibleCount[layer.group].visibles++;\n }\n }\n if(isDefined(layer.index) && leafletLayers.overlays[key].setZIndex) {\n leafletLayers.overlays[key].setZIndex(newOverlayLayers[key].index);\n }\n }\n\n for(key in groupVisibleCount) {\n scope.groupProperties[key].visible = groupVisibleCount[key].visibles === groupVisibleCount[key].count;\n }\n scope.overlaysArray = overlaysArray;\n });\n }, true);\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\").directive('layers', function ($log, $q, leafletData, leafletHelpers, leafletLayerHelpers, leafletControlHelpers) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: 'leaflet',\n controller: function ($scope) {\n $scope._leafletLayers = $q.defer();\n this.getLayers = function () {\n return $scope._leafletLayers.promise;\n };\n },\n link: function(scope, element, attrs, controller){\n var isDefined = leafletHelpers.isDefined,\n leafletLayers = {},\n leafletScope = controller.getLeafletScope(),\n layers = leafletScope.layers,\n createLayer = leafletLayerHelpers.createLayer,\n updateLayersControl = leafletControlHelpers.updateLayersControl,\n isLayersControlVisible = false;\n\n controller.getMap().then(function(map) {\n\n // We have baselayers to add to the map\n scope._leafletLayers.resolve(leafletLayers);\n leafletData.setLayers(leafletLayers, attrs.id);\n\n leafletLayers.baselayers = {};\n leafletLayers.overlays = {};\n\n var mapId = attrs.id;\n\n // Setup all baselayers definitions\n var oneVisibleLayer = false;\n for (var layerName in layers.baselayers) {\n var newBaseLayer = createLayer(layers.baselayers[layerName]);\n if (!isDefined(newBaseLayer)) {\n delete layers.baselayers[layerName];\n continue;\n }\n leafletLayers.baselayers[layerName] = newBaseLayer;\n // Only add the visible layer to the map, layer control manages the addition to the map\n // of layers in its control\n if (layers.baselayers[layerName].top === true) {\n map.addLayer(leafletLayers.baselayers[layerName]);\n oneVisibleLayer = true;\n }\n }\n\n // If there is no visible layer add first to the map\n if (!oneVisibleLayer && Object.keys(leafletLayers.baselayers).length > 0) {\n map.addLayer(leafletLayers.baselayers[Object.keys(layers.baselayers)[0]]);\n }\n\n // Setup the Overlays\n for (layerName in layers.overlays) {\n if(layers.overlays[layerName].type === 'cartodb') {\n\n }\n var newOverlayLayer = createLayer(layers.overlays[layerName]);\n if (!isDefined(newOverlayLayer)) {\n delete layers.overlays[layerName];\n continue;\n }\n leafletLayers.overlays[layerName] = newOverlayLayer;\n // Only add the visible overlays to the map\n if (layers.overlays[layerName].visible === true) {\n map.addLayer(leafletLayers.overlays[layerName]);\n }\n }\n\n // Watch for the base layers\n leafletScope.$watch('layers.baselayers', function(newBaseLayers, oldBaseLayers) {\n if(angular.equals(newBaseLayers, oldBaseLayers)) {\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, newBaseLayers, layers.overlays, leafletLayers);\n return true;\n }\n // Delete layers from the array\n for (var name in leafletLayers.baselayers) {\n if (!isDefined(newBaseLayers[name]) || newBaseLayers[name].doRefresh) {\n // Remove from the map if it's on it\n if (map.hasLayer(leafletLayers.baselayers[name])) {\n map.removeLayer(leafletLayers.baselayers[name]);\n }\n delete leafletLayers.baselayers[name];\n\n if (newBaseLayers[name] && newBaseLayers[name].doRefresh) {\n newBaseLayers[name].doRefresh = false;\n }\n }\n }\n // add new layers\n for (var newName in newBaseLayers) {\n if (!isDefined(leafletLayers.baselayers[newName])) {\n var testBaseLayer = createLayer(newBaseLayers[newName]);\n if (isDefined(testBaseLayer)) {\n leafletLayers.baselayers[newName] = testBaseLayer;\n // Only add the visible layer to the map\n if (newBaseLayers[newName].top === true) {\n map.addLayer(leafletLayers.baselayers[newName]);\n }\n }\n } else {\n if (newBaseLayers[newName].top === true && !map.hasLayer(leafletLayers.baselayers[newName])) {\n map.addLayer(leafletLayers.baselayers[newName]);\n } else if (newBaseLayers[newName].top === false && map.hasLayer(leafletLayers.baselayers[newName])) {\n map.removeLayer(leafletLayers.baselayers[newName]);\n }\n }\n }\n\n //we have layers, so we need to make, at least, one active\n var found = false;\n // search for an active layer\n for (var key in leafletLayers.baselayers) {\n if (map.hasLayer(leafletLayers.baselayers[key])) {\n found = true;\n break;\n }\n }\n // If there is no active layer make one active\n if (!found && Object.keys(leafletLayers.baselayers).length > 0) {\n map.addLayer(leafletLayers.baselayers[Object.keys(leafletLayers.baselayers)[0]]);\n }\n\n // Only show the layers switch selector control if we have more than one baselayer + overlay\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, newBaseLayers, layers.overlays, leafletLayers);\n }, true);\n\n // Watch for the overlay layers\n leafletScope.$watch('layers.overlays', function(newOverlayLayers, oldOverlayLayers) {\n if(angular.equals(newOverlayLayers, oldOverlayLayers)) {\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, layers.baselayers, newOverlayLayers, leafletLayers);\n return true;\n }\n // Delete layers from the array\n for (var name in leafletLayers.overlays) {\n if (!isDefined(newOverlayLayers[name]) || newOverlayLayers[name].doRefresh) {\n // Remove from the map if it's on it\n if (map.hasLayer(leafletLayers.overlays[name])) {\n map.removeLayer(leafletLayers.overlays[name]);\n }\n // TODO: Depending on the layer type we will have to delete what's included on it\n delete leafletLayers.overlays[name];\n\n if (newOverlayLayers[name] && newOverlayLayers[name].doRefresh) {\n newOverlayLayers[name].doRefresh = false;\n }\n }\n }\n\n // add new overlays\n for (var newName in newOverlayLayers) {\n if (!isDefined(leafletLayers.overlays[newName])) {\n var testOverlayLayer = createLayer(newOverlayLayers[newName]);\n if (!isDefined(testOverlayLayer)) {\n // If the layer creation fails, continue to the next overlay\n continue;\n }\n leafletLayers.overlays[newName] = testOverlayLayer;\n if (newOverlayLayers[newName].visible === true) {\n map.addLayer(leafletLayers.overlays[newName]);\n }\n }\n\n // check for the .visible property to hide/show overLayers\n if (newOverlayLayers[newName].visible && !map.hasLayer(leafletLayers.overlays[newName])) {\n map.addLayer(leafletLayers.overlays[newName]);\n } else if (newOverlayLayers[newName].visible === false && map.hasLayer(leafletLayers.overlays[newName])) {\n map.removeLayer(leafletLayers.overlays[newName]);\n }\n\n //refresh heatmap data if present\n if (newOverlayLayers[newName].visible && map._loaded && newOverlayLayers[newName].data && newOverlayLayers[newName].type === \"heatmap\") {\n leafletLayers.overlays[newName].setData(newOverlayLayers[newName].data);\n leafletLayers.overlays[newName].update();\n }\n }\n\n // Only add the layers switch selector control if we have more than one baselayer + overlay\n isLayersControlVisible = updateLayersControl(map, mapId, isLayersControlVisible, layers.baselayers, newOverlayLayers, leafletLayers);\n }, true);\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\").directive('legend', function ($log, $http, leafletHelpers, leafletLegendHelpers) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: 'leaflet',\n\n link: function (scope, element, attrs, controller) {\n\n var isArray = leafletHelpers.isArray,\n isDefined = leafletHelpers.isDefined,\n isFunction = leafletHelpers.isFunction,\n leafletScope = controller.getLeafletScope(),\n legend = leafletScope.legend;\n\n var legendClass;\n var position;\n var leafletLegend;\n var type;\n\n leafletScope.$watch('legend', function (newLegend) {\n\n if (isDefined(newLegend)) {\n\n legendClass = newLegend.legendClass ? newLegend.legendClass : \"legend\";\n\n position = newLegend.position || 'bottomright';\n\n // default to arcgis\n type = newLegend.type || 'arcgis'; \n }\n\n }, true);\n\n controller.getMap().then(function (map) {\n\n leafletScope.$watch('legend', function (newLegend) {\n\n if (!isDefined(newLegend)) {\n\n if (isDefined(leafletLegend)) {\n leafletLegend.removeFrom(map);\n leafletLegend= null;\n }\n\n return;\n }\n\n if (!isDefined(newLegend.url) && (type === 'arcgis') && (!isArray(newLegend.colors) || !isArray(newLegend.labels) || newLegend.colors.length !== newLegend.labels.length)) {\n\n $log.warn(\"[AngularJS - Leaflet] legend.colors and legend.labels must be set.\");\n\n return;\n }\n\n if (isDefined(newLegend.url)) {\n\n $log.info(\"[AngularJS - Leaflet] loading legend service.\");\n\n return;\n }\n\n if (isDefined(leafletLegend)) {\n leafletLegend.removeFrom(map);\n leafletLegend= null;\n }\n\n leafletLegend = L.control({\n position: position\n });\n if (type === 'arcgis') {\n leafletLegend.onAdd = leafletLegendHelpers.getOnAddArrayLegend(newLegend, legendClass);\n }\n leafletLegend.addTo(map);\n\n });\n\n leafletScope.$watch('legend.url', function (newURL) {\n\n if (!isDefined(newURL)) {\n return;\n }\n $http.get(newURL)\n .success(function (legendData) {\n\n if (isDefined(leafletLegend)) {\n\n leafletLegendHelpers.updateLegend(leafletLegend.getContainer(), legendData, type, newURL);\n\n } else {\n\n leafletLegend = L.control({\n position: position\n });\n leafletLegend.onAdd = leafletLegendHelpers.getOnAddLegend(legendData, legendClass, type, newURL);\n leafletLegend.addTo(map);\n }\n\n if (isDefined(legend.loadedData) && isFunction(legend.loadedData)) {\n legend.loadedData();\n }\n })\n .error(function () {\n $log.warn('[AngularJS - Leaflet] legend.url not loaded.');\n });\n });\n\n });\n }\n };\n });\n","angular.module(\"leaflet-directive\").directive('markers',\n function ($log, $rootScope, $q, leafletData, leafletHelpers, leafletMapDefaults,\n leafletMarkersHelpers, leafletMarkerEvents, leafletIterators, leafletWatchHelpers,\n leafletDirectiveControlsHelpers) {\n //less terse vars to helpers\n var isDefined = leafletHelpers.isDefined,\n errorHeader = leafletHelpers.errorHeader,\n Helpers = leafletHelpers,\n isString = leafletHelpers.isString,\n addMarkerWatcher = leafletMarkersHelpers.addMarkerWatcher,\n updateMarker = leafletMarkersHelpers.updateMarker,\n listenMarkerEvents = leafletMarkersHelpers.listenMarkerEvents,\n addMarkerToGroup = leafletMarkersHelpers.addMarkerToGroup,\n createMarker = leafletMarkersHelpers.createMarker,\n deleteMarker = leafletMarkersHelpers.deleteMarker,\n $it = leafletIterators,\n _markersWatchOptions = leafletHelpers.watchOptions,\n maybeWatch = leafletWatchHelpers.maybeWatch,\n extendDirectiveControls = leafletDirectiveControlsHelpers.extend;\n\n var _getLMarker = function(leafletMarkers, name, maybeLayerName){\n if(!Object.keys(leafletMarkers).length) return;\n if(maybeLayerName && isString(maybeLayerName)){\n if(!leafletMarkers[maybeLayerName] || !Object.keys(leafletMarkers[maybeLayerName]).length)\n return;\n return leafletMarkers[maybeLayerName][name];\n }\n return leafletMarkers[name];\n };\n\n var _setLMarker = function(lObject, leafletMarkers, name, maybeLayerName){\n if(maybeLayerName && isString(maybeLayerName)){\n if(!isDefined(leafletMarkers[maybeLayerName]))\n leafletMarkers[maybeLayerName] = {};\n leafletMarkers[maybeLayerName][name] = lObject;\n }\n else\n leafletMarkers[name] = lObject;\n return lObject;\n };\n\n var _maybeAddMarkerToLayer = function(layerName, layers, model, marker, doIndividualWatch, map){\n\n if (!isString(layerName)) {\n $log.error(errorHeader + ' A layername must be a string');\n return false;\n }\n\n if (!isDefined(layers)) {\n $log.error(errorHeader + ' You must add layers to the directive if the markers are going to use this functionality.');\n return false;\n }\n\n if (!isDefined(layers.overlays) || !isDefined(layers.overlays[layerName])) {\n $log.error(errorHeader +' A marker can only be added to a layer of type \"group\"');\n return false;\n }\n var layerGroup = layers.overlays[layerName];\n if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {\n $log.error(errorHeader + ' Adding a marker to an overlay needs a overlay of the type \"group\" or \"featureGroup\"');\n return false;\n }\n\n // The marker goes to a correct layer group, so first of all we add it\n layerGroup.addLayer(marker);\n\n // The marker is automatically added to the map depending on the visibility\n // of the layer, so we only have to open the popup if the marker is in the map\n if (!doIndividualWatch && map.hasLayer(marker) && model.focus === true) {\n marker.openPopup();\n }\n return true;\n };\n //TODO: move to leafletMarkersHelpers??? or make a new class/function file (leafletMarkersHelpers is large already)\n var _addMarkers = function(markersToRender, oldModels, map, layers, leafletMarkers, leafletScope,\n watchOptions, maybeLayerName, skips){\n for (var newName in markersToRender) {\n if(skips[newName])\n continue;\n\n if (newName.search(\"-\") !== -1) {\n $log.error('The marker can\\'t use a \"-\" on his key name: \"' + newName + '\".');\n continue;\n }\n\n var model = Helpers.copy(markersToRender[newName]);\n var pathToMarker = Helpers.getObjectDotPath(maybeLayerName? [maybeLayerName, newName]: [newName]);\n var maybeLMarker = _getLMarker(leafletMarkers,newName, maybeLayerName);\n if (!isDefined(maybeLMarker)) {\n //(nmccready) very important to not have model changes when lObject is changed\n //this might be desirable in some cases but it causes two-way binding to lObject which is not ideal\n //if it is left as the reference then all changes from oldModel vs newModel are ignored\n //see _destroy (where modelDiff becomes meaningless if we do not copy here)\n var marker = createMarker(model);\n var layerName = (model? model.layer : undefined) || maybeLayerName; //original way takes pref\n if (!isDefined(marker)) {\n $log.error(errorHeader + ' Received invalid data on the marker ' + newName + '.');\n continue;\n }\n _setLMarker(marker, leafletMarkers, newName, maybeLayerName);\n\n // Bind message\n if (isDefined(model.message)) {\n marker.bindPopup(model.message, model.popupOptions);\n }\n\n // Add the marker to a cluster group if needed\n if (isDefined(model.group)) {\n var groupOptions = isDefined(model.groupOption) ? model.groupOption : null;\n addMarkerToGroup(marker, model.group, groupOptions, map);\n }\n\n // Show label if defined\n if (Helpers.LabelPlugin.isLoaded() && isDefined(model.label) && isDefined(model.label.message)) {\n marker.bindLabel(model.label.message, model.label.options);\n }\n\n // Check if the marker should be added to a layer\n if (isDefined(model) && (isDefined(model.layer) || isDefined(maybeLayerName))){\n\n var pass = _maybeAddMarkerToLayer(layerName, layers, model, marker,\n watchOptions.individual.doWatch, map);\n if(!pass)\n continue; //something went wrong move on in the loop\n } else if (!isDefined(model.group)) {\n // We do not have a layer attr, so the marker goes to the map layer\n map.addLayer(marker);\n if (!watchOptions.individual.doWatch && model.focus === true) {\n marker.openPopup();\n }\n }\n\n if (watchOptions.individual.doWatch) {\n addMarkerWatcher(marker, pathToMarker, leafletScope, layers, map,\n watchOptions.individual.isDeep);\n }\n\n listenMarkerEvents(marker, model, leafletScope, watchOptions.individual.doWatch, map);\n leafletMarkerEvents.bindEvents(marker, pathToMarker, model, leafletScope, layerName);\n }\n else {\n var oldModel = isDefined(oldModel)? oldModels[newName] : undefined;\n updateMarker(model, oldModel, maybeLMarker, pathToMarker, leafletScope, layers, map);\n }\n }\n };\n var _seeWhatWeAlreadyHave = function(markerModels, oldMarkerModels, lMarkers, isEqual, cb){\n var hasLogged = false,\n equals = false,\n oldMarker,\n newMarker;\n\n var doCheckOldModel = isDefined(oldMarkerModels);\n for (var name in lMarkers) {\n if(!hasLogged) {\n $log.debug(errorHeader + \"[markers] destroy: \");\n hasLogged = true;\n }\n\n if(doCheckOldModel){\n //might want to make the option (in watch options) to disable deep checking\n //ie the options to only check !== (reference check) instead of angular.equals (slow)\n newMarker = markerModels[name];\n oldMarker = oldMarkerModels[name];\n equals = angular.equals(newMarker,oldMarker) && isEqual;\n }\n if (!isDefined(markerModels) ||\n !Object.keys(markerModels).length ||\n !isDefined(markerModels[name]) ||\n !Object.keys(markerModels[name]).length ||\n equals) {\n if(cb && Helpers.isFunction(cb))\n cb(newMarker, oldMarker, name);\n }\n }\n };\n var _destroy = function(markerModels, oldMarkerModels, lMarkers, map, layers){\n _seeWhatWeAlreadyHave(markerModels, oldMarkerModels, lMarkers, false,\n function(newMarker, oldMarker, lMarkerName){\n $log.debug(errorHeader + '[marker] is deleting marker: ' + lMarkerName);\n deleteMarker(lMarkers[lMarkerName], map, layers);\n delete lMarkers[lMarkerName];\n });\n };\n\n var _getNewModelsToSkipp = function(newModels, oldModels, lMarkers){\n var skips = {};\n _seeWhatWeAlreadyHave(newModels, oldModels, lMarkers, true,\n function(newMarker, oldMarker, lMarkerName){\n $log.debug(errorHeader + '[marker] is already rendered, marker: ' + lMarkerName);\n skips[lMarkerName] = newMarker;\n });\n return skips;\n };\n\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: ['leaflet', '?layers'],\n\n link: function(scope, element, attrs, controller) {\n var mapController = controller[0],\n leafletScope = mapController.getLeafletScope();\n\n mapController.getMap().then(function(map) {\n var leafletMarkers = {}, getLayers;\n\n // If the layers attribute is used, we must wait until the layers are created\n if (isDefined(controller[1])) {\n getLayers = controller[1].getLayers;\n } else {\n getLayers = function() {\n var deferred = $q.defer();\n deferred.resolve();\n return deferred.promise;\n };\n }\n\n var watchOptions = leafletScope.markersWatchOptions || _markersWatchOptions;\n\n // backwards compat\n if(isDefined(attrs.watchMarkers))\n watchOptions.doWatch = watchOptions.individual.doWatch =\n (!isDefined(attrs.watchMarkers) || Helpers.isTruthy(attrs.watchMarkers));\n\n var isNested = (isDefined(attrs.markersNested) && Helpers.isTruthy(attrs.markersNested));\n\n getLayers().then(function(layers) {\n var _clean = function(models, oldModels){\n if(isNested) {\n $it.each(models, function(markerToMaybeDel, layerName) {\n var oldModel = isDefined(oldModel)? oldModels[layerName] : undefined;\n _destroy(markerToMaybeDel, oldModel, leafletMarkers[layerName], map, layers);\n });\n return;\n }\n _destroy(models, oldModels, leafletMarkers, map, layers);\n };\n\n var _create = function(models, oldModels){\n _clean(models, oldModels);\n var skips = null;\n if(isNested) {\n $it.each(models, function(markersToAdd, layerName) {\n var oldModel = isDefined(oldModel)? oldModels[layerName] : undefined;\n skips = _getNewModelsToSkipp(models[layerName], oldModel, leafletMarkers[layerName]);\n _addMarkers(markersToAdd, oldModels, map, layers, leafletMarkers, leafletScope,\n watchOptions, layerName, skips);\n });\n return;\n }\n skips = _getNewModelsToSkipp(models, oldModels, leafletMarkers);\n _addMarkers(models, oldModels, map, layers, leafletMarkers, leafletScope,\n watchOptions, undefined, skips);\n };\n extendDirectiveControls(attrs.id, 'markers', _create, _clean);\n leafletData.setMarkers(leafletMarkers, attrs.id);\n\n maybeWatch(leafletScope,'markers', watchOptions, function(newMarkers, oldMarkers){\n _create(newMarkers, oldMarkers);\n });\n });\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\").directive('maxbounds', function ($log, leafletMapDefaults, leafletBoundsHelpers, leafletHelpers) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: 'leaflet',\n\n link: function(scope, element, attrs, controller) {\n var leafletScope = controller.getLeafletScope(),\n isValidBounds = leafletBoundsHelpers.isValidBounds,\n isNumber = leafletHelpers.isNumber;\n\n\n controller.getMap().then(function(map) {\n leafletScope.$watch(\"maxbounds\", function (maxbounds) {\n if (!isValidBounds(maxbounds)) {\n // Unset any previous maxbounds\n map.setMaxBounds();\n return;\n }\n \n var leafletBounds = leafletBoundsHelpers.createLeafletBounds(maxbounds);\n if(isNumber(maxbounds.pad)) {\n leafletBounds = leafletBounds.pad(maxbounds.pad);\n }\n\n map.setMaxBounds(leafletBounds);\n if (!attrs.center) {\n map.fitBounds(leafletBounds);\n }\n });\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\").directive('paths', function ($log, $q, leafletData, leafletMapDefaults, leafletHelpers, leafletPathsHelpers, leafletEvents) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: ['leaflet', '?layers'],\n\n link: function(scope, element, attrs, controller) {\n var mapController = controller[0],\n isDefined = leafletHelpers.isDefined,\n isString = leafletHelpers.isString,\n leafletScope = mapController.getLeafletScope(),\n paths = leafletScope.paths,\n createPath = leafletPathsHelpers.createPath,\n bindPathEvents = leafletEvents.bindPathEvents,\n setPathOptions = leafletPathsHelpers.setPathOptions;\n\n mapController.getMap().then(function(map) {\n var defaults = leafletMapDefaults.getDefaults(attrs.id),\n getLayers;\n\n // If the layers attribute is used, we must wait until the layers are created\n if (isDefined(controller[1])) {\n getLayers = controller[1].getLayers;\n } else {\n getLayers = function() {\n var deferred = $q.defer();\n deferred.resolve();\n return deferred.promise;\n };\n }\n\n if (!isDefined(paths)) {\n return;\n }\n\n getLayers().then(function(layers) {\n\n var leafletPaths = {};\n leafletData.setPaths(leafletPaths, attrs.id);\n\n // Should we watch for every specific marker on the map?\n var shouldWatch = (!isDefined(attrs.watchPaths) || attrs.watchPaths === 'true');\n\n // Function for listening every single path once created\n var watchPathFn = function(leafletPath, name) {\n var clearWatch = leafletScope.$watch(\"paths[\\\"\"+name+\"\\\"]\", function(pathData, old) {\n if (!isDefined(pathData)) {\n if (isDefined(old.layer)) {\n for (var i in layers.overlays) {\n var overlay = layers.overlays[i];\n overlay.removeLayer(leafletPath);\n }\n }\n map.removeLayer(leafletPath);\n clearWatch();\n return;\n }\n setPathOptions(leafletPath, pathData.type, pathData);\n }, true);\n };\n\n leafletScope.$watchCollection(\"paths\", function (newPaths) {\n\n // Delete paths (by name) from the array\n for (var name in leafletPaths) {\n if (!isDefined(newPaths[name])) {\n map.removeLayer(leafletPaths[name]);\n delete leafletPaths[name];\n }\n }\n\n // Create the new paths\n for (var newName in newPaths) {\n if (newName.search('\\\\$') === 0) {\n continue;\n }\n if (newName.search(\"-\") !== -1) {\n $log.error('[AngularJS - Leaflet] The path name \"' + newName + '\" is not valid. It must not include \"-\" and a number.');\n continue;\n }\n\n if (!isDefined(leafletPaths[newName])) {\n var pathData = newPaths[newName];\n var newPath = createPath(newName, newPaths[newName], defaults);\n\n // bind popup if defined\n if (isDefined(newPath) && isDefined(pathData.message)) {\n newPath.bindPopup(pathData.message, pathData.popupOptions);\n }\n\n // Show label if defined\n if (leafletHelpers.LabelPlugin.isLoaded() && isDefined(pathData.label) && isDefined(pathData.label.message)) {\n newPath.bindLabel(pathData.label.message, pathData.label.options);\n }\n\n // Check if the marker should be added to a layer\n if (isDefined(pathData) && isDefined(pathData.layer)) {\n\n if (!isString(pathData.layer)) {\n $log.error('[AngularJS - Leaflet] A layername must be a string');\n continue;\n }\n if (!isDefined(layers)) {\n $log.error('[AngularJS - Leaflet] You must add layers to the directive if the markers are going to use this functionality.');\n continue;\n }\n\n if (!isDefined(layers.overlays) || !isDefined(layers.overlays[pathData.layer])) {\n $log.error('[AngularJS - Leaflet] A marker can only be added to a layer of type \"group\"');\n continue;\n }\n var layerGroup = layers.overlays[pathData.layer];\n if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {\n $log.error('[AngularJS - Leaflet] Adding a marker to an overlay needs a overlay of the type \"group\" or \"featureGroup\"');\n continue;\n }\n\n // Listen for changes on the new path\n leafletPaths[newName] = newPath;\n // The path goes to a correct layer group, so first of all we add it\n layerGroup.addLayer(newPath);\n\n if (shouldWatch) {\n watchPathFn(newPath, newName);\n } else {\n setPathOptions(newPath, pathData.type, pathData);\n }\n } else if (isDefined(newPath)) {\n // Listen for changes on the new path\n leafletPaths[newName] = newPath;\n map.addLayer(newPath);\n\n if (shouldWatch) {\n watchPathFn(newPath, newName);\n } else {\n setPathOptions(newPath, pathData.type, pathData);\n }\n }\n\n bindPathEvents(newPath, newName, pathData, leafletScope);\n }\n }\n });\n });\n });\n }\n };\n});\n","angular.module(\"leaflet-directive\").directive('tiles', function ($log, leafletData, leafletMapDefaults, leafletHelpers) {\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: 'leaflet',\n\n link: function(scope, element, attrs, controller) {\n var isDefined = leafletHelpers.isDefined,\n leafletScope = controller.getLeafletScope(),\n tiles = leafletScope.tiles;\n\n if (!isDefined(tiles) || !isDefined(tiles.url)) {\n $log.warn(\"[AngularJS - Leaflet] The 'tiles' definition doesn't have the 'url' property.\");\n return;\n }\n\n controller.getMap().then(function(map) {\n var defaults = leafletMapDefaults.getDefaults(attrs.id);\n var tileLayerObj;\n leafletScope.$watch(\"tiles\", function(tiles) {\n var tileLayerOptions = defaults.tileLayerOptions;\n var tileLayerUrl = defaults.tileLayer;\n\n // If no valid tiles are in the scope, remove the last layer\n if (!isDefined(tiles.url) && isDefined(tileLayerObj)) {\n map.removeLayer(tileLayerObj);\n return;\n }\n\n // No leafletTiles object defined yet\n if (!isDefined(tileLayerObj)) {\n if (isDefined(tiles.options)) {\n angular.copy(tiles.options, tileLayerOptions);\n }\n\n if (isDefined(tiles.url)) {\n tileLayerUrl = tiles.url;\n }\n\n tileLayerObj = L.tileLayer(tileLayerUrl, tileLayerOptions);\n tileLayerObj.addTo(map);\n leafletData.setTiles(tileLayerObj, attrs.id);\n return;\n }\n\n // If the options of the tilelayer is changed, we need to redraw the layer\n if (isDefined(tiles.url) && isDefined(tiles.options) && !angular.equals(tiles.options, tileLayerOptions)) {\n map.removeLayer(tileLayerObj);\n tileLayerOptions = defaults.tileLayerOptions;\n angular.copy(tiles.options, tileLayerOptions);\n tileLayerUrl = tiles.url;\n tileLayerObj = L.tileLayer(tileLayerUrl, tileLayerOptions);\n tileLayerObj.addTo(map);\n leafletData.setTiles(tileLayerObj, attrs.id);\n return;\n }\n\n // Only the URL of the layer is changed, update the tiles object\n if (isDefined(tiles.url)) {\n tileLayerObj.setUrl(tiles.url);\n }\n }, true);\n });\n }\n };\n});\n","/*\n Create multiple similar directives for watchOptions to support directiveControl\n instead. (when watches are disabled)\n NgAnnotate does not work here due to the functional creation\n*/\n['markers', 'geojson'].forEach(function(name){\n angular.module(\"leaflet-directive\").directive(name + 'WatchOptions', [\n '$log', '$rootScope', '$q', 'leafletData', 'leafletHelpers',\n function ($log, $rootScope, $q, leafletData, leafletHelpers) {\n\n var isDefined = leafletHelpers.isDefined,\n errorHeader = leafletHelpers.errorHeader,\n isObject = leafletHelpers.isObject,\n _watchOptions = leafletHelpers.watchOptions;\n\n return {\n restrict: \"A\",\n scope: false,\n replace: false,\n require: ['leaflet'],\n\n link: function (scope, element, attrs, controller) {\n var mapController = controller[0],\n leafletScope = mapController.getLeafletScope();\n\n mapController.getMap().then(function () {\n if (isDefined(scope[name + 'WatchOptions'])) {\n if (isObject(scope[name + 'WatchOptions']))\n angular.extend(_watchOptions, scope[name + 'WatchOptions']);\n else\n $log.error(errorHeader + '[' + name + 'WatchOptions] is not an object');\n leafletScope[name + 'WatchOptions'] = _watchOptions;\n }\n });\n }\n };\n }]);\n});\n","angular.module(\"leaflet-directive\")\n.factory('leafletEventsHelpersFactory', function ($rootScope, $q, $log, leafletHelpers) {\n var safeApply = leafletHelpers.safeApply,\n isDefined = leafletHelpers.isDefined,\n isObject = leafletHelpers.isObject,\n isArray = leafletHelpers.isArray,\n errorHeader = leafletHelpers.errorHeader;\n\n var EventsHelper = function(rootBroadcastName, lObjectType){\n this.rootBroadcastName = rootBroadcastName;\n //used to path/key out certain properties based on the type , \"markers\", \"geojson\"\n this.lObjectType = lObjectType;\n };\n\n EventsHelper.prototype.getAvailableEvents = function(){return []};\n\n /*\n argument: name: Note this can be a single string or dot notation\n Example:\n markerModel : {\n m1: { lat:_, lon: _}\n }\n //would yield name of\n name = \"m1\"\n\n If nested:\n markerModel : {\n cars: {\n m1: { lat:_, lon: _}\n }\n }\n //would yield name of\n name = \"cars.m1\"\n */\n EventsHelper.prototype.genDispatchEvent = function(eventName, logic, leafletScope, lObject, name, model, layerName, extra) {\n var _this = this;\n return function (e) {\n var broadcastName = _this.rootBroadcastName + '.' + eventName;\n _this.fire(leafletScope, broadcastName, logic, e, e.target || lObject, model, name, layerName, extra);\n };\n };\n\n EventsHelper.prototype.fire = function(scope, broadcastName, logic, event, lObject, model, modelName, layerName, extra){\n // Safely broadcast the event\n safeApply(scope, function(){\n var toSend = {\n leafletEvent: event,\n leafletObject: lObject,\n modelName: modelName,\n model: model\n };\n if (isDefined(layerName))\n angular.extend(toSend, {layerName: layerName});\n\n if (logic === \"emit\") {\n scope.$emit(broadcastName, toSend);\n } else {\n $rootScope.$broadcast(broadcastName, toSend);\n }\n });\n };\n\n EventsHelper.prototype.bindEvents = function (lObject, name, model, leafletScope, layerName, extra) {\n var events = [];\n var logic = 'emit';\n var _this = this;\n\n if (!isDefined(leafletScope.eventBroadcast)) {\n // Backward compatibility, if no event-broadcast attribute, all events are broadcasted\n events = this.getAvailableEvents();\n } else if (!isObject(leafletScope.eventBroadcast)) {\n // Not a valid object\n $log.error(errorHeader + \"event-broadcast must be an object check your model.\");\n } else {\n // We have a possible valid object\n if (!isDefined(leafletScope.eventBroadcast[_this.lObjectType])) {\n // We do not have events enable/disable do we do nothing (all enabled by default)\n events = this.getAvailableEvents();\n } else if (!isObject(leafletScope.eventBroadcast[_this.lObjectType])) {\n // Not a valid object\n $log.warn(errorHeader + 'event-broadcast.' + [_this.lObjectType] + ' must be an object check your model.');\n } else {\n // We have a possible valid map object\n // Event propadation logic\n if (isDefined(leafletScope.eventBroadcast[this.lObjectType].logic)) {\n // We take care of possible propagation logic\n if (leafletScope.eventBroadcast[_this.lObjectType].logic !== \"emit\" &&\n leafletScope.eventBroadcast[_this.lObjectType].logic !== \"broadcast\")\n $log.warn(errorHeader + \"Available event propagation logic are: 'emit' or 'broadcast'.\");\n }\n // Enable / Disable\n var eventsEnable = false, eventsDisable = false;\n if (isDefined(leafletScope.eventBroadcast[_this.lObjectType].enable) &&\n isArray(leafletScope.eventBroadcast[_this.lObjectType].enable))\n eventsEnable = true;\n if (isDefined(leafletScope.eventBroadcast[_this.lObjectType].disable) &&\n isArray(leafletScope.eventBroadcast[_this.lObjectType].disable))\n eventsDisable = true;\n\n if (eventsEnable && eventsDisable) {\n // Both are active, this is an error\n $log.warn(errorHeader + \"can not enable and disable events at the same time\");\n } else if (!eventsEnable && !eventsDisable) {\n // Both are inactive, this is an error\n $log.warn(errorHeader + \"must enable or disable events\");\n } else {\n // At this point the object is OK, lets enable or disable events\n if (eventsEnable) {\n // Enable events\n leafletScope.eventBroadcast[this.lObjectType].enable.forEach(function(eventName){\n // Do we have already the event enabled?\n if (events.indexOf(eventName) !== -1) {\n // Repeated event, this is an error\n $log.warn(errorHeader + \"This event \" + eventName + \" is already enabled\");\n } else {\n // Does the event exists?\n if (_this.getAvailableEvents().indexOf(eventName) === -1) {\n // The event does not exists, this is an error\n $log.warn(errorHeader + \"This event \" + eventName + \" does not exist\");\n } else {\n // All ok enable the event\n events.push(eventName);\n }\n }\n });\n } else {\n // Disable events\n events = this.getAvailableEvents();\n leafletScope.eventBroadcast[_this.lObjectType].disable.forEach(function(eventName) {\n var index = events.indexOf(eventName);\n if (index === -1) {\n // The event does not exist\n $log.warn(errorHeader + \"This event \" + eventName + \" does not exist or has been already disabled\");\n\n } else {\n events.splice(index, 1);\n }\n });\n }\n }\n }\n }\n\n events.forEach(function(eventName){\n lObject.on(eventName,_this.genDispatchEvent(eventName, logic, leafletScope, lObject, name, model, layerName, extra));\n });\n return logic;\n };\n\n return EventsHelper;\n})\n.service('leafletEventsHelpers', function(leafletEventsHelpersFactory){\n return new leafletEventsHelpersFactory();\n});\n","angular.module(\"leaflet-directive\")\n.factory('leafletGeoJsonEvents', function ($rootScope, $q, $log, leafletHelpers,\n leafletEventsHelpersFactory, leafletLabelEvents, leafletData) {\n var safeApply = leafletHelpers.safeApply,\n isDefined = leafletHelpers.isDefined,\n Helpers = leafletHelpers,\n lblHelp = leafletLabelEvents,\n EventsHelper = leafletEventsHelpersFactory;\n\n\n var GeoJsonEvents = function(){\n EventsHelper.call(this,'leafletDirectiveGeoJson', 'geojson');\n };\n\n GeoJsonEvents.prototype = new EventsHelper();\n\n\n GeoJsonEvents.prototype.genDispatchEvent = function(eventName, logic, leafletScope, lObject, name, model, layerName, extra) {\n var base = EventsHelper.prototype.genDispatchEvent.call(this, eventName, logic, leafletScope, lObject, name, model, layerName),\n _this = this;\n\n return function(e){\n if (eventName === 'mouseout') {\n if (extra.resetStyleOnMouseout) {\n leafletData.getGeoJSON(extra.mapId)\n .then(function(leafletGeoJSON){\n //this is broken on nested needs to traverse or user layerName (nested)\n var lobj = layerName? leafletGeoJSON[layerName]: leafletGeoJSON;\n lobj.resetStyle(e.target);\n });\n\n }\n safeApply(leafletScope, function() {\n $rootScope.$broadcast(_this.rootBroadcastName + '.mouseout', e);\n });\n }\n base(e); //common\n };\n };\n\n GeoJsonEvents.prototype.getAvailableEvents = function(){ return [\n 'click',\n 'dblclick',\n 'mouseover',\n 'mouseout',\n ];\n };\n\n return new GeoJsonEvents();\n});\n","angular.module(\"leaflet-directive\")\n.factory('leafletLabelEvents', function ($rootScope, $q, $log, leafletHelpers, leafletEventsHelpersFactory) {\n var Helpers = leafletHelpers,\n EventsHelper = leafletEventsHelpersFactory;\n var LabelEvents = function(){\n EventsHelper.call(this,'leafletDirectiveLabel', 'markers');\n };\n LabelEvents.prototype = new EventsHelper();\n\n LabelEvents.prototype.genDispatchEvent = function(eventName, logic, leafletScope, lObject, name, model, layerName) {\n var markerName = name.replace('markers.', '');\n return EventsHelper.prototype\n .genDispatchEvent.call(this, eventName, logic, leafletScope, lObject, markerName, model, layerName);\n };\n\n LabelEvents.prototype.getAvailableEvents = function(){\n return [\n 'click',\n 'dblclick',\n 'mousedown',\n 'mouseover',\n 'mouseout',\n 'contextmenu'\n ];\n };\n\n LabelEvents.prototype.genEvents = function (eventName, logic, leafletScope, lObject, name, model, layerName) {\n var _this = this;\n var labelEvents = this.getAvailableEvents();\n var scopeWatchName = Helpers.getObjectArrayPath(\"markers.\" + name);\n labelEvents.forEach(function(eventName) {\n lObject.label.on(eventName, _this.genDispatchEvent(\n eventName, logic, leafletScope, lObject.label, scopeWatchName, model, layerName));\n });\n };\n\n LabelEvents.prototype.bindEvents = function (lObject, name, model, leafletScope, layerName) {};\n\n return new LabelEvents();\n});\n","angular.module(\"leaflet-directive\")\n.factory('leafletMapEvents', function ($rootScope, $q, $log, leafletHelpers, leafletEventsHelpers) {\n var safeApply = leafletHelpers.safeApply,\n isDefined = leafletHelpers.isDefined,\n isObject = leafletHelpers.isObject,\n Helpers = leafletHelpers,\n errorHeader = leafletHelpers.errorHeader,\n fire = leafletEventsHelpers.fire;\n\n var _getAvailableMapEvents = function() {\n return [\n 'click',\n 'dblclick',\n 'mousedown',\n 'mouseup',\n 'mouseover',\n 'mouseout',\n 'mousemove',\n 'contextmenu',\n 'focus',\n 'blur',\n 'preclick',\n 'load',\n 'unload',\n 'viewreset',\n 'movestart',\n 'move',\n 'moveend',\n 'dragstart',\n 'drag',\n 'dragend',\n 'zoomstart',\n 'zoomend',\n 'zoomlevelschange',\n 'resize',\n 'autopanstart',\n 'layeradd',\n 'layerremove',\n 'baselayerchange',\n 'overlayadd',\n 'overlayremove',\n 'locationfound',\n 'locationerror',\n 'popupopen',\n 'popupclose',\n 'draw:created',\n 'draw:edited',\n 'draw:deleted',\n 'draw:drawstart',\n 'draw:drawstop',\n 'draw:editstart',\n 'draw:editstop',\n 'draw:deletestart',\n 'draw:deletestop'\n ];\n };\n\n var _genDispatchMapEvent = function(scope, eventName, logic) {\n // (nmccready) We should consider passing mapId as an argument or using it from scope\n return function(e) {\n // Put together broadcast name\n // (nmccready) We should consider passing mapId joining mapId to the broadcastName to keep the event unique. Same should be done for all directives so we know what map it comes from.\n // problem with this is it will cause a minor bump and break backwards compat\n var broadcastName = 'leafletDirectiveMap.' + eventName;\n // Safely broadcast the event\n fire(scope, broadcastName, logic, e, e.target, scope)\n };\n };\n\n var _notifyCenterChangedToBounds = function(scope) {\n scope.$broadcast(\"boundsChanged\");\n };\n\n var _notifyCenterUrlHashChanged = function(scope, map, attrs, search) {\n if (!isDefined(attrs.urlHashCenter)) {\n return;\n }\n var center = map.getCenter();\n var centerUrlHash = (center.lat).toFixed(4) + \":\" + (center.lng).toFixed(4) + \":\" + map.getZoom();\n if (!isDefined(search.c) || search.c !== centerUrlHash) {\n //$log.debug(\"notified new center...\");\n scope.$emit(\"centerUrlHash\", centerUrlHash);\n }\n };\n\n return {\n getAvailableMapEvents: _getAvailableMapEvents,\n genDispatchMapEvent: _genDispatchMapEvent,\n notifyCenterChangedToBounds: _notifyCenterChangedToBounds,\n notifyCenterUrlHashChanged: _notifyCenterUrlHashChanged\n };\n});\n","angular.module(\"leaflet-directive\")\n.factory('leafletMarkerEvents', function ($rootScope, $q, $log, leafletHelpers, leafletEventsHelpersFactory, leafletLabelEvents) {\n var safeApply = leafletHelpers.safeApply,\n isDefined = leafletHelpers.isDefined,\n Helpers = leafletHelpers,\n lblHelp = leafletLabelEvents,\n EventsHelper = leafletEventsHelpersFactory;\n\n var MarkerEvents = function(){\n EventsHelper.call(this,'leafletDirectiveMarker', 'markers');\n };\n\n MarkerEvents.prototype = new EventsHelper();\n\n MarkerEvents.prototype.genDispatchEvent = function(eventName, logic, leafletScope, lObject, name, model, layerName) {\n var handle = EventsHelper.prototype\n .genDispatchEvent.call(this, eventName, logic, leafletScope, lObject, name, model, layerName);\n return function(e){\n // Broadcast old marker click name for backwards compatibility\n if (eventName === \"click\") {\n safeApply(leafletScope, function () {\n $rootScope.$broadcast('leafletDirectiveMarkersClick', name);\n });\n } else if (eventName === 'dragend') {\n safeApply(leafletScope, function () {\n model.lat = lObject.getLatLng().lat;\n model.lng = lObject.getLatLng().lng;\n });\n if (model.message && model.focus === true) {\n lObject.openPopup();\n }\n }\n handle(e); //common\n };\n };\n\n MarkerEvents.prototype.getAvailableEvents = function(){ return [\n 'click',\n 'dblclick',\n 'mousedown',\n 'mouseover',\n 'mouseout',\n 'contextmenu',\n 'dragstart',\n 'drag',\n 'dragend',\n 'move',\n 'remove',\n 'popupopen',\n 'popupclose',\n 'touchend',\n 'touchstart',\n 'touchmove',\n 'touchcancel',\n 'touchleave'\n ];\n };\n\n MarkerEvents.prototype.bindEvents = function (lObject, name, model, leafletScope, layerName) {\n var logic = EventsHelper.prototype.bindEvents.call(this,lObject, name, model, leafletScope, layerName);\n\n if (Helpers.LabelPlugin.isLoaded() && isDefined(lObject.label)) {\n lblHelp.genEvents(name, logic, leafletScope, lObject, model, layerName);\n }\n };\n\n return new MarkerEvents();\n});\n","angular.module(\"leaflet-directive\")\n.factory('leafletPathEvents', function ($rootScope, $q, $log, leafletHelpers, leafletLabelEvents, leafletEventsHelpers) {\n var safeApply = leafletHelpers.safeApply,\n isDefined = leafletHelpers.isDefined,\n isObject = leafletHelpers.isObject,\n Helpers = leafletHelpers,\n errorHeader = leafletHelpers.errorHeader,\n lblHelp = leafletLabelEvents,\n fire = leafletEventsHelpers.fire;\n\n var _genDispatchPathEvent = function (eventName, logic, leafletScope, lObject, name, model, layerName) {\n return function (e) {\n var broadcastName = 'leafletDirectivePath.' + eventName;\n\n fire(leafletScope, broadcastName, logic, e, e.target || lObject, model, name, layerName);\n };\n };\n\n var _bindPathEvents = function (lObject, name, model, leafletScope) {\n var pathEvents = [],\n i,\n eventName,\n logic = \"broadcast\";\n\n if (!isDefined(leafletScope.eventBroadcast)) {\n // Backward compatibility, if no event-broadcast attribute, all events are broadcasted\n pathEvents = _getAvailablePathEvents();\n } else if (!isObject(leafletScope.eventBroadcast)) {\n // Not a valid object\n $log.error(errorHeader + \"event-broadcast must be an object check your model.\");\n } else {\n // We have a possible valid object\n if (!isDefined(leafletScope.eventBroadcast.path)) {\n // We do not have events enable/disable do we do nothing (all enabled by default)\n pathEvents = _getAvailablePathEvents();\n } else if (isObject(leafletScope.eventBroadcast.paths)) {\n // Not a valid object\n $log.warn(errorHeader + \"event-broadcast.path must be an object check your model.\");\n } else {\n // We have a possible valid map object\n // Event propadation logic\n if (leafletScope.eventBroadcast.path.logic !== undefined && leafletScope.eventBroadcast.path.logic !== null) {\n // We take care of possible propagation logic\n if (leafletScope.eventBroadcast.path.logic !== \"emit\" && leafletScope.eventBroadcast.path.logic !== \"broadcast\") {\n // This is an error\n $log.warn(errorHeader + \"Available event propagation logic are: 'emit' or 'broadcast'.\");\n } else if (leafletScope.eventBroadcast.path.logic === \"emit\") {\n logic = \"emit\";\n }\n }\n // Enable / Disable\n var pathEventsEnable = false, pathEventsDisable = false;\n if (leafletScope.eventBroadcast.path.enable !== undefined && leafletScope.eventBroadcast.path.enable !== null) {\n if (typeof leafletScope.eventBroadcast.path.enable === 'object') {\n pathEventsEnable = true;\n }\n }\n if (leafletScope.eventBroadcast.path.disable !== undefined && leafletScope.eventBroadcast.path.disable !== null) {\n if (typeof leafletScope.eventBroadcast.path.disable === 'object') {\n pathEventsDisable = true;\n }\n }\n if (pathEventsEnable && pathEventsDisable) {\n // Both are active, this is an error\n $log.warn(errorHeader + \"can not enable and disable events at the same time\");\n } else if (!pathEventsEnable && !pathEventsDisable) {\n // Both are inactive, this is an error\n $log.warn(errorHeader + \"must enable or disable events\");\n } else {\n // At this point the path object is OK, lets enable or disable events\n if (pathEventsEnable) {\n // Enable events\n for (i = 0; i < leafletScope.eventBroadcast.path.enable.length; i++) {\n eventName = leafletScope.eventBroadcast.path.enable[i];\n // Do we have already the event enabled?\n if (pathEvents.indexOf(eventName) !== -1) {\n // Repeated event, this is an error\n $log.warn(errorHeader + \"This event \" + eventName + \" is already enabled\");\n } else {\n // Does the event exists?\n if (_getAvailablePathEvents().indexOf(eventName) === -1) {\n // The event does not exists, this is an error\n $log.warn(errorHeader + \"This event \" + eventName + \" does not exist\");\n } else {\n // All ok enable the event\n pathEvents.push(eventName);\n }\n }\n }\n } else {\n // Disable events\n pathEvents = _getAvailablePathEvents();\n for (i = 0; i < leafletScope.eventBroadcast.path.disable.length; i++) {\n eventName = leafletScope.eventBroadcast.path.disable[i];\n var index = pathEvents.indexOf(eventName);\n if (index === -1) {\n // The event does not exist\n $log.warn(errorHeader + \"This event \" + eventName + \" does not exist or has been already disabled\");\n\n } else {\n pathEvents.splice(index, 1);\n }\n }\n }\n }\n }\n }\n\n for (i = 0; i < pathEvents.length; i++) {\n eventName = pathEvents[i];\n lObject.on(eventName, _genDispatchPathEvent(eventName, logic, leafletScope, pathEvents, name));\n }\n\n if (Helpers.LabelPlugin.isLoaded() && isDefined(lObject.label)) {\n lblHelp.genEvents(name, logic, leafletScope, lObject, model);\n }\n };\n\n var _getAvailablePathEvents = function () {\n return [\n 'click',\n 'dblclick',\n 'mousedown',\n 'mouseover',\n 'mouseout',\n 'contextmenu',\n 'add',\n 'remove',\n 'popupopen',\n 'popupclose'\n ];\n };\n\n return {\n getAvailablePathEvents: _getAvailablePathEvents,\n bindPathEvents: _bindPathEvents\n };\n});\n"]} \ No newline at end of file diff --git a/dist/architecture/dot/all.dot b/dist/architecture/dot/all.dot deleted file mode 100644 index aa2f0eef..00000000 --- a/dist/architecture/dot/all.dot +++ /dev/null @@ -1,577 +0,0 @@ -digraph dependencies { - node[shape="component",style="filled",colorscheme=paired12] - - node[shape="component"] - - "leaflet-directive"[label="leaflet-directive", color=1] - - - - - - - node[shape="ellipse"] - - - - - - - - - "leafletData"[label="leafletData", color=5] - - "leafletDirectiveControlsHelpers"[label="leafletDirectiveControlsHelpers", color=5] - - "leafletGeoJsonHelpers"[label="leafletGeoJsonHelpers", color=5] - - "leafletIterators"[label="leafletIterators", color=5] - - "leafletMarkersHelpers"[label="leafletMarkersHelpers", color=5] - - "leafletWatchHelpers"[label="leafletWatchHelpers", color=5] - - "leafletEventsHelpers"[label="leafletEventsHelpers", color=5] - - - - "leafletBoundsHelpers"[label="leafletBoundsHelpers", color=6] - - "leafletControlHelpers"[label="leafletControlHelpers", color=6] - - "leafletEvents"[label="leafletEvents", color=6] - - "leafletHelpers"[label="leafletHelpers", color=6] - - "leafletLayerHelpers"[label="leafletLayerHelpers", color=6] - - "leafletLegendHelpers"[label="leafletLegendHelpers", color=6] - - "leafletMapDefaults"[label="leafletMapDefaults", color=6] - - "leafletPathsHelpers"[label="leafletPathsHelpers", color=6] - - "nominatimService"[label="nominatimService", color=6] - - "leafletEventsHelpersFactory"[label="leafletEventsHelpersFactory", color=6] - - "leafletGeoJsonEvents"[label="leafletGeoJsonEvents", color=6] - - "leafletLabelEvents"[label="leafletLabelEvents", color=6] - - "leafletMapEvents"[label="leafletMapEvents", color=6] - - "leafletMarkerEvents"[label="leafletMarkerEvents", color=6] - - "leafletPathEvents"[label="leafletPathEvents", color=6] - - - - node[shape="cds"] - - - - - "leaflet"[label="leaflet", color=3] - - "bounds"[label="bounds", color=3] - - "center"[label="center", color=3] - - "controls"[label="controls", color=3] - - "decorations"[label="decorations", color=3] - - "eventBroadcast"[label="eventBroadcast", color=3] - - "geojson"[label="geojson", color=3] - - "layercontrol"[label="layercontrol", color=3] - - "layers"[label="layers", color=3] - - "legend"[label="legend", color=3] - - "markers"[label="markers", color=3] - - "maxbounds"[label="maxbounds", color=3] - - "paths"[label="paths", color=3] - - "tiles"[label="tiles", color=3] - - "markersWatchOptions"[label="markersWatchOptions", color=3] - - "geojsonWatchOptions"[label="geojsonWatchOptions", color=3] - - - - - - - node[shape="ellipse"] - - - - "leaflet-directive" -> "leaflet" - - "leaflet-directive" -> "bounds" - - "leaflet-directive" -> "center" - - "leaflet-directive" -> "controls" - - "leaflet-directive" -> "decorations" - - "leaflet-directive" -> "eventBroadcast" - - "leaflet-directive" -> "geojson" - - "leaflet-directive" -> "layercontrol" - - "leaflet-directive" -> "layers" - - "leaflet-directive" -> "legend" - - "leaflet-directive" -> "markers" - - "leaflet-directive" -> "maxbounds" - - "leaflet-directive" -> "paths" - - "leaflet-directive" -> "tiles" - - "leaflet-directive" -> "markersWatchOptions" - - "leaflet-directive" -> "geojsonWatchOptions" - - - - - - "leaflet-directive" -> "leafletData" - - "leaflet-directive" -> "leafletDirectiveControlsHelpers" - - "leaflet-directive" -> "leafletGeoJsonHelpers" - - "leaflet-directive" -> "leafletIterators" - - "leaflet-directive" -> "leafletMarkersHelpers" - - "leaflet-directive" -> "leafletWatchHelpers" - - "leaflet-directive" -> "leafletEventsHelpers" - - - - "leaflet-directive" -> "leafletBoundsHelpers" - - "leaflet-directive" -> "leafletControlHelpers" - - "leaflet-directive" -> "leafletEvents" - - "leaflet-directive" -> "leafletHelpers" - - "leaflet-directive" -> "leafletLayerHelpers" - - "leaflet-directive" -> "leafletLegendHelpers" - - "leaflet-directive" -> "leafletMapDefaults" - - "leaflet-directive" -> "leafletPathsHelpers" - - "leaflet-directive" -> "nominatimService" - - "leaflet-directive" -> "leafletEventsHelpersFactory" - - "leaflet-directive" -> "leafletGeoJsonEvents" - - "leaflet-directive" -> "leafletLabelEvents" - - "leaflet-directive" -> "leafletMapEvents" - - "leaflet-directive" -> "leafletMarkerEvents" - - "leaflet-directive" -> "leafletPathEvents" - - - - - - - - - - - - - - - node[shape="ellipse",style="filled", color=8] - - - - - "leafletData"[label="leafletData"] - "leafletData" -> "leaflet" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "leaflet" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leaflet" - - "leafletEvents"[label="leafletEvents"] - "leafletEvents" -> "leaflet" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "bounds" - - "nominatimService"[label="nominatimService"] - "nominatimService" -> "bounds" - - "leafletBoundsHelpers"[label="leafletBoundsHelpers"] - "leafletBoundsHelpers" -> "bounds" - - - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "center" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "center" - - "leafletBoundsHelpers"[label="leafletBoundsHelpers"] - "leafletBoundsHelpers" -> "center" - - "leafletEvents"[label="leafletEvents"] - "leafletEvents" -> "center" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "controls" - - "leafletControlHelpers"[label="leafletControlHelpers"] - "leafletControlHelpers" -> "controls" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "decorations" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "eventBroadcast" - - "leafletEvents"[label="leafletEvents"] - "leafletEvents" -> "eventBroadcast" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "eventBroadcast" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "geojson" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "geojson" - - "leafletWatchHelpers"[label="leafletWatchHelpers"] - "leafletWatchHelpers" -> "geojson" - - "leafletDirectiveControlsHelpers"[label="leafletDirectiveControlsHelpers"] - "leafletDirectiveControlsHelpers" -> "geojson" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "geojson" - - "leafletGeoJsonEvents"[label="leafletGeoJsonEvents"] - "leafletGeoJsonEvents" -> "geojson" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "layercontrol" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "layercontrol" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "layers" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "layers" - - "leafletLayerHelpers"[label="leafletLayerHelpers"] - "leafletLayerHelpers" -> "layers" - - "leafletControlHelpers"[label="leafletControlHelpers"] - "leafletControlHelpers" -> "layers" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "legend" - - "leafletLegendHelpers"[label="leafletLegendHelpers"] - "leafletLegendHelpers" -> "legend" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "markers" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "markers" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "markers" - - "leafletMarkersHelpers"[label="leafletMarkersHelpers"] - "leafletMarkersHelpers" -> "markers" - - "leafletMarkerEvents"[label="leafletMarkerEvents"] - "leafletMarkerEvents" -> "markers" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "markers" - - "leafletWatchHelpers"[label="leafletWatchHelpers"] - "leafletWatchHelpers" -> "markers" - - "leafletDirectiveControlsHelpers"[label="leafletDirectiveControlsHelpers"] - "leafletDirectiveControlsHelpers" -> "markers" - - - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "maxbounds" - - "leafletBoundsHelpers"[label="leafletBoundsHelpers"] - "leafletBoundsHelpers" -> "maxbounds" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "maxbounds" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "paths" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "paths" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "paths" - - "leafletPathsHelpers"[label="leafletPathsHelpers"] - "leafletPathsHelpers" -> "paths" - - "leafletEvents"[label="leafletEvents"] - "leafletEvents" -> "paths" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "tiles" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "tiles" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "tiles" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "markersWatchOptions" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "markersWatchOptions" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "geojsonWatchOptions" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "geojsonWatchOptions" - - - - - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletData" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "leafletDirectiveControlsHelpers" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletDirectiveControlsHelpers" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletGeoJsonHelpers" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "leafletGeoJsonHelpers" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletIterators" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletMarkersHelpers" - - "leafletGeoJsonHelpers"[label="leafletGeoJsonHelpers"] - "leafletGeoJsonHelpers" -> "leafletMarkersHelpers" - - - - - - "leafletEventsHelpersFactory"[label="leafletEventsHelpersFactory"] - "leafletEventsHelpersFactory" -> "leafletEventsHelpers" - - - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletBoundsHelpers" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletControlHelpers" - - "leafletLayerHelpers"[label="leafletLayerHelpers"] - "leafletLayerHelpers" -> "leafletControlHelpers" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "leafletControlHelpers" - - - - "leafletMapEvents"[label="leafletMapEvents"] - "leafletMapEvents" -> "leafletEvents" - - "leafletMarkerEvents"[label="leafletMarkerEvents"] - "leafletMarkerEvents" -> "leafletEvents" - - "leafletPathEvents"[label="leafletPathEvents"] - "leafletPathEvents" -> "leafletEvents" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "leafletEvents" - - - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletLayerHelpers" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "leafletLayerHelpers" - - - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletMapDefaults" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletPathsHelpers" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "nominatimService" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "nominatimService" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletEventsHelpersFactory" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletGeoJsonEvents" - - "leafletEventsHelpersFactory"[label="leafletEventsHelpersFactory"] - "leafletEventsHelpersFactory" -> "leafletGeoJsonEvents" - - "leafletLabelEvents"[label="leafletLabelEvents"] - "leafletLabelEvents" -> "leafletGeoJsonEvents" - - "leafletData"[label="leafletData"] - "leafletData" -> "leafletGeoJsonEvents" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletLabelEvents" - - "leafletEventsHelpersFactory"[label="leafletEventsHelpersFactory"] - "leafletEventsHelpersFactory" -> "leafletLabelEvents" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletMapEvents" - - "leafletEventsHelpers"[label="leafletEventsHelpers"] - "leafletEventsHelpers" -> "leafletMapEvents" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletMarkerEvents" - - "leafletEventsHelpersFactory"[label="leafletEventsHelpersFactory"] - "leafletEventsHelpersFactory" -> "leafletMarkerEvents" - - "leafletLabelEvents"[label="leafletLabelEvents"] - "leafletLabelEvents" -> "leafletMarkerEvents" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletPathEvents" - - "leafletLabelEvents"[label="leafletLabelEvents"] - "leafletLabelEvents" -> "leafletPathEvents" - - "leafletEventsHelpers"[label="leafletEventsHelpers"] - "leafletEventsHelpers" -> "leafletPathEvents" - - - - - - -} diff --git a/dist/architecture/dot/legend.dot b/dist/architecture/dot/legend.dot deleted file mode 100644 index 7f91f5de..00000000 --- a/dist/architecture/dot/legend.dot +++ /dev/null @@ -1,18 +0,0 @@ -digraph dependencies { - node[shape="component",style="filled",colorscheme=paired12] - - - node[shape="component"] - "legend.module"[label="Modules", color=1] - node[shape="ellipse"] - "legend.provider" [label="Providers", color=2] - "legend.controllers"[label="Controllers", color=4] - "legend.services" [label="Services", color=5] - "legend.factories" [label="Factories", color=6] - "legend.injected" [label="Injected Services", color=9] - node[shape="cds"] - "legend.filters" [label="Filters", color=7] - "legend.directives" [label="Directives", color=3] - - -} \ No newline at end of file diff --git a/dist/architecture/dot/modules.dot b/dist/architecture/dot/modules.dot deleted file mode 100644 index da611363..00000000 --- a/dist/architecture/dot/modules.dot +++ /dev/null @@ -1,12 +0,0 @@ -digraph dependencies { - node[shape="ellipse",style="filled",colorscheme=paired12] - - - "leaflet-directive"[label="leaflet-directive", color=1] - - - node[shape="ellipse",style="filled",color=2] - - - -} diff --git a/dist/architecture/dot/modules/leaflet-directive.dot b/dist/architecture/dot/modules/leaflet-directive.dot deleted file mode 100644 index 079a0c0b..00000000 --- a/dist/architecture/dot/modules/leaflet-directive.dot +++ /dev/null @@ -1,515 +0,0 @@ -digraph dependencies { - node[shape="component",style="filled",colorscheme=paired12] - - - node[shape="component"] - "leaflet-directive"[label="leaflet-directive", color=1] - - - - - node[shape="ellipse"] - - - - - - - "leafletData"[label="leafletData", color=5] - "leaflet-directive" -> "leafletData" - - "leafletDirectiveControlsHelpers"[label="leafletDirectiveControlsHelpers", color=5] - "leaflet-directive" -> "leafletDirectiveControlsHelpers" - - "leafletGeoJsonHelpers"[label="leafletGeoJsonHelpers", color=5] - "leaflet-directive" -> "leafletGeoJsonHelpers" - - "leafletIterators"[label="leafletIterators", color=5] - "leaflet-directive" -> "leafletIterators" - - "leafletMarkersHelpers"[label="leafletMarkersHelpers", color=5] - "leaflet-directive" -> "leafletMarkersHelpers" - - "leafletWatchHelpers"[label="leafletWatchHelpers", color=5] - "leaflet-directive" -> "leafletWatchHelpers" - - "leafletEventsHelpers"[label="leafletEventsHelpers", color=5] - "leaflet-directive" -> "leafletEventsHelpers" - - - - "leafletBoundsHelpers"[label="leafletBoundsHelpers", color=6] - "leaflet-directive" -> "leafletBoundsHelpers" - - "leafletControlHelpers"[label="leafletControlHelpers", color=6] - "leaflet-directive" -> "leafletControlHelpers" - - "leafletEvents"[label="leafletEvents", color=6] - "leaflet-directive" -> "leafletEvents" - - "leafletHelpers"[label="leafletHelpers", color=6] - "leaflet-directive" -> "leafletHelpers" - - "leafletLayerHelpers"[label="leafletLayerHelpers", color=6] - "leaflet-directive" -> "leafletLayerHelpers" - - "leafletLegendHelpers"[label="leafletLegendHelpers", color=6] - "leaflet-directive" -> "leafletLegendHelpers" - - "leafletMapDefaults"[label="leafletMapDefaults", color=6] - "leaflet-directive" -> "leafletMapDefaults" - - "leafletPathsHelpers"[label="leafletPathsHelpers", color=6] - "leaflet-directive" -> "leafletPathsHelpers" - - "nominatimService"[label="nominatimService", color=6] - "leaflet-directive" -> "nominatimService" - - "leafletEventsHelpersFactory"[label="leafletEventsHelpersFactory", color=6] - "leaflet-directive" -> "leafletEventsHelpersFactory" - - "leafletGeoJsonEvents"[label="leafletGeoJsonEvents", color=6] - "leaflet-directive" -> "leafletGeoJsonEvents" - - "leafletLabelEvents"[label="leafletLabelEvents", color=6] - "leaflet-directive" -> "leafletLabelEvents" - - "leafletMapEvents"[label="leafletMapEvents", color=6] - "leaflet-directive" -> "leafletMapEvents" - - "leafletMarkerEvents"[label="leafletMarkerEvents", color=6] - "leaflet-directive" -> "leafletMarkerEvents" - - "leafletPathEvents"[label="leafletPathEvents", color=6] - "leaflet-directive" -> "leafletPathEvents" - - - node[shape="cds"] - - - - "leaflet"[label="leaflet", color=3] - "leaflet-directive" -> "leaflet" - - "bounds"[label="bounds", color=3] - "leaflet-directive" -> "bounds" - - "center"[label="center", color=3] - "leaflet-directive" -> "center" - - "controls"[label="controls", color=3] - "leaflet-directive" -> "controls" - - "decorations"[label="decorations", color=3] - "leaflet-directive" -> "decorations" - - "eventBroadcast"[label="eventBroadcast", color=3] - "leaflet-directive" -> "eventBroadcast" - - "geojson"[label="geojson", color=3] - "leaflet-directive" -> "geojson" - - "layercontrol"[label="layercontrol", color=3] - "leaflet-directive" -> "layercontrol" - - "layers"[label="layers", color=3] - "leaflet-directive" -> "layers" - - "legend"[label="legend", color=3] - "leaflet-directive" -> "legend" - - "markers"[label="markers", color=3] - "leaflet-directive" -> "markers" - - "maxbounds"[label="maxbounds", color=3] - "leaflet-directive" -> "maxbounds" - - "paths"[label="paths", color=3] - "leaflet-directive" -> "paths" - - "tiles"[label="tiles", color=3] - "leaflet-directive" -> "tiles" - - "markersWatchOptions"[label="markersWatchOptions", color=3] - "leaflet-directive" -> "markersWatchOptions" - - "geojsonWatchOptions"[label="geojsonWatchOptions", color=3] - "leaflet-directive" -> "geojsonWatchOptions" - - - - - - - - - - - node[shape="ellipse",style="filled", color=9] - - - - - "leafletData"[label="leafletData"] - "leafletData" -> "leaflet" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "leaflet" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leaflet" - - "leafletEvents"[label="leafletEvents"] - "leafletEvents" -> "leaflet" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "bounds" - - "nominatimService"[label="nominatimService"] - "nominatimService" -> "bounds" - - "leafletBoundsHelpers"[label="leafletBoundsHelpers"] - "leafletBoundsHelpers" -> "bounds" - - - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "center" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "center" - - "leafletBoundsHelpers"[label="leafletBoundsHelpers"] - "leafletBoundsHelpers" -> "center" - - "leafletEvents"[label="leafletEvents"] - "leafletEvents" -> "center" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "controls" - - "leafletControlHelpers"[label="leafletControlHelpers"] - "leafletControlHelpers" -> "controls" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "decorations" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "eventBroadcast" - - "leafletEvents"[label="leafletEvents"] - "leafletEvents" -> "eventBroadcast" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "eventBroadcast" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "geojson" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "geojson" - - "leafletWatchHelpers"[label="leafletWatchHelpers"] - "leafletWatchHelpers" -> "geojson" - - "leafletDirectiveControlsHelpers"[label="leafletDirectiveControlsHelpers"] - "leafletDirectiveControlsHelpers" -> "geojson" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "geojson" - - "leafletGeoJsonEvents"[label="leafletGeoJsonEvents"] - "leafletGeoJsonEvents" -> "geojson" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "layercontrol" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "layercontrol" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "layers" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "layers" - - "leafletLayerHelpers"[label="leafletLayerHelpers"] - "leafletLayerHelpers" -> "layers" - - "leafletControlHelpers"[label="leafletControlHelpers"] - "leafletControlHelpers" -> "layers" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "legend" - - "leafletLegendHelpers"[label="leafletLegendHelpers"] - "leafletLegendHelpers" -> "legend" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "markers" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "markers" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "markers" - - "leafletMarkersHelpers"[label="leafletMarkersHelpers"] - "leafletMarkersHelpers" -> "markers" - - "leafletMarkerEvents"[label="leafletMarkerEvents"] - "leafletMarkerEvents" -> "markers" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "markers" - - "leafletWatchHelpers"[label="leafletWatchHelpers"] - "leafletWatchHelpers" -> "markers" - - "leafletDirectiveControlsHelpers"[label="leafletDirectiveControlsHelpers"] - "leafletDirectiveControlsHelpers" -> "markers" - - - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "maxbounds" - - "leafletBoundsHelpers"[label="leafletBoundsHelpers"] - "leafletBoundsHelpers" -> "maxbounds" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "maxbounds" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "paths" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "paths" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "paths" - - "leafletPathsHelpers"[label="leafletPathsHelpers"] - "leafletPathsHelpers" -> "paths" - - "leafletEvents"[label="leafletEvents"] - "leafletEvents" -> "paths" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "tiles" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "tiles" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "tiles" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "markersWatchOptions" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "markersWatchOptions" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "geojsonWatchOptions" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "geojsonWatchOptions" - - - - - - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletData" - - - - "leafletData"[label="leafletData"] - "leafletData" -> "leafletDirectiveControlsHelpers" - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletDirectiveControlsHelpers" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletGeoJsonHelpers" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "leafletGeoJsonHelpers" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletIterators" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletMarkersHelpers" - - "leafletGeoJsonHelpers"[label="leafletGeoJsonHelpers"] - "leafletGeoJsonHelpers" -> "leafletMarkersHelpers" - - - - - - "leafletEventsHelpersFactory"[label="leafletEventsHelpersFactory"] - "leafletEventsHelpersFactory" -> "leafletEventsHelpers" - - - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletBoundsHelpers" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletControlHelpers" - - "leafletLayerHelpers"[label="leafletLayerHelpers"] - "leafletLayerHelpers" -> "leafletControlHelpers" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "leafletControlHelpers" - - - - "leafletMapEvents"[label="leafletMapEvents"] - "leafletMapEvents" -> "leafletEvents" - - "leafletMarkerEvents"[label="leafletMarkerEvents"] - "leafletMarkerEvents" -> "leafletEvents" - - "leafletPathEvents"[label="leafletPathEvents"] - "leafletPathEvents" -> "leafletEvents" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "leafletEvents" - - - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletLayerHelpers" - - "leafletIterators"[label="leafletIterators"] - "leafletIterators" -> "leafletLayerHelpers" - - - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletMapDefaults" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletPathsHelpers" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "nominatimService" - - "leafletMapDefaults"[label="leafletMapDefaults"] - "leafletMapDefaults" -> "nominatimService" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletEventsHelpersFactory" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletGeoJsonEvents" - - "leafletEventsHelpersFactory"[label="leafletEventsHelpersFactory"] - "leafletEventsHelpersFactory" -> "leafletGeoJsonEvents" - - "leafletLabelEvents"[label="leafletLabelEvents"] - "leafletLabelEvents" -> "leafletGeoJsonEvents" - - "leafletData"[label="leafletData"] - "leafletData" -> "leafletGeoJsonEvents" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletLabelEvents" - - "leafletEventsHelpersFactory"[label="leafletEventsHelpersFactory"] - "leafletEventsHelpersFactory" -> "leafletLabelEvents" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletMapEvents" - - "leafletEventsHelpers"[label="leafletEventsHelpers"] - "leafletEventsHelpers" -> "leafletMapEvents" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletMarkerEvents" - - "leafletEventsHelpersFactory"[label="leafletEventsHelpersFactory"] - "leafletEventsHelpersFactory" -> "leafletMarkerEvents" - - "leafletLabelEvents"[label="leafletLabelEvents"] - "leafletLabelEvents" -> "leafletMarkerEvents" - - - - "leafletHelpers"[label="leafletHelpers"] - "leafletHelpers" -> "leafletPathEvents" - - "leafletLabelEvents"[label="leafletLabelEvents"] - "leafletLabelEvents" -> "leafletPathEvents" - - "leafletEventsHelpers"[label="leafletEventsHelpers"] - "leafletEventsHelpers" -> "leafletPathEvents" - - - - - - -} diff --git a/dist/architecture/png/all.png b/dist/architecture/png/all.png deleted file mode 100644 index 7746acca..00000000 Binary files a/dist/architecture/png/all.png and /dev/null differ diff --git a/dist/architecture/png/legend.png b/dist/architecture/png/legend.png deleted file mode 100644 index e555687b..00000000 Binary files a/dist/architecture/png/legend.png and /dev/null differ diff --git a/dist/architecture/png/modules.png b/dist/architecture/png/modules.png deleted file mode 100644 index eeff81f2..00000000 Binary files a/dist/architecture/png/modules.png and /dev/null differ diff --git a/dist/architecture/png/modules/leaflet-directive.png b/dist/architecture/png/modules/leaflet-directive.png deleted file mode 100644 index 7746acca..00000000 Binary files a/dist/architecture/png/modules/leaflet-directive.png and /dev/null differ diff --git a/doc/bounds-attribute.md b/doc/bounds-attribute.md index d0e47fb8..6e87d2d9 100644 --- a/doc/bounds-attribute.md +++ b/doc/bounds-attribute.md @@ -4,7 +4,7 @@ This sub-directive needs the **leaflet** main directive, so it is normally used as an attribute of the *leaflet* tag, like this: ``` - + ``` It will map an object _bounds_ of our controller scope with the corresponding object on our leaflet directive isolated scope. It's a bidirectional relationship, so a change in this object on the controller scope object will affect the map bounds, or an interaction on the map which changes the map position will update our _bounds_ values. Let's define the bounds model with an example: diff --git a/doc/center-attribute.md b/doc/center-attribute.md index dba35214..7cef0ed2 100644 --- a/doc/center-attribute.md +++ b/doc/center-attribute.md @@ -4,7 +4,7 @@ This sub-directive needs the **leaflet** main directive, so it is normally used as an attribute of the *leaflet* tag, like this: ``` - + ``` It will map an object _center_ of our controller scope with the corresponding object on our directive isolated scope. It's a bidirectional relationship, so a change in this object on the controller scope will affect the map center position, or an interaction on the map which changes the map center will update our _center_ values. Let's define the center model with an example: @@ -34,7 +34,7 @@ angular.extend($scope, { And after that, in our HTML code we will define our leaflet directive like this: ``` - + ``` And that's all. A full example of using this attribute can be found [here](http://tombatossals.github.io/angular-leaflet-directive/examples/center-example.html). @@ -63,7 +63,7 @@ Center position coded on a hash URL param ------------------------------------------ We can use a special feature of the center attribute which allow us to synchronize the center position of the map with the URL, adding to it a special GET parameter where the center is coded. Then we can persist the map position on the browser URL. ``` - + ``` Adding that attribute will synchronize the center with a GET parameter on the URL of this form `?c=lat:lng:zoom`. Furthermore, whenever the map center is changed a new event `urlCenterHash` will be emitted to the parent scope so you can update your `$location.search` with the new info (if you want). diff --git a/doc/leaflet-directive.md b/doc/leaflet-directive.md index 2a3ff2e9..64ca4017 100644 --- a/doc/leaflet-directive.md +++ b/doc/leaflet-directive.md @@ -4,7 +4,7 @@ Leaflet directive Documentation This directive acts as an intermediary between the AngularJS framework and the Leaflet map management library. It's composed of a main directive **<leaflet>** and attributes (coded as sub-directives) of the main directive. For example, we could add to our HTML code: ``` - + ``` Here we have the main **leaflet** directive, with the attribute **center** and two more attributes (without bi-directional binding) **width** and **height**. diff --git a/examples/0000-viewer.html b/examples/0000-viewer.html index 32e97134..8bdb067c 100644 --- a/examples/0000-viewer.html +++ b/examples/0000-viewer.html @@ -38,7 +38,7 @@ - + diff --git a/examples/0101-basic-center-example.html b/examples/0101-basic-center-example.html index 0d3e7eb2..34668431 100644 --- a/examples/0101-basic-center-example.html +++ b/examples/0101-basic-center-example.html @@ -4,7 +4,7 @@ - + + + + + + + + + +

Center map example

+
    +
  • Latitude
  • +
  • Longitude
  • +
  • Zoom
  • +
+ + diff --git a/examples/0102-basic-center-autodiscover-example.html b/examples/0102-basic-center-autodiscover-example.html index 95c05855..f1ffed0d 100644 --- a/examples/0102-basic-center-autodiscover-example.html +++ b/examples/0102-basic-center-autodiscover-example.html @@ -24,7 +24,7 @@ - +

Center autodiscover example

  • Latitude
  • diff --git a/examples/0103-basic-center-url-hash-example.html b/examples/0103-basic-center-url-hash-example.html index 64dc3279..28f6ee6f 100644 --- a/examples/0103-basic-center-url-hash-example.html +++ b/examples/0103-basic-center-url-hash-example.html @@ -23,7 +23,7 @@ $scope.changeLocation = function(centerHash) { $location.search({ c: centerHash }); - } + }; }]); @@ -35,7 +35,7 @@ - +

    Center map with URL synchronization example

    This demo syncs the map center position with the URL, and vice versa, using the center-url-params property.

      diff --git a/examples/0104-basic-custom-parameters-example.html b/examples/0104-basic-custom-parameters-example.html index f1725909..fccceba6 100644 --- a/examples/0104-basic-custom-parameters-example.html +++ b/examples/0104-basic-custom-parameters-example.html @@ -30,7 +30,7 @@ - +

      Using custom default parameters

      diff --git a/examples/0105-basic-bounds-example.html b/examples/0105-basic-bounds-example.html index 562fcfb7..c59450cb 100644 --- a/examples/0105-basic-bounds-example.html +++ b/examples/0105-basic-bounds-example.html @@ -25,7 +25,7 @@ - +

      Map bounds example

      South west

      diff --git a/examples/0107-basic-tiles-example.html b/examples/0107-basic-tiles-example.html index e1ca3572..6298062b 100644 --- a/examples/0107-basic-tiles-example.html +++ b/examples/0107-basic-tiles-example.html @@ -58,7 +58,7 @@ - +

      Changing tiles example

      Change tiles clicking in the buttons below:

      diff --git a/examples/0108-basic-tiles-zoom-changer-example.html b/examples/0108-basic-tiles-zoom-changer-example.html index bbf5206b..c2275a0a 100644 --- a/examples/0108-basic-tiles-zoom-changer-example.html +++ b/examples/0108-basic-tiles-zoom-changer-example.html @@ -32,7 +32,7 @@ - +

      Dynamic tile changer based on zoom level

      Zoom to level 13 to see how the tiles change:

        diff --git a/examples/0109-basic-center-geoip-example.html b/examples/0109-basic-center-geoip-example.html index 7b0ddfbc..385ff208 100644 --- a/examples/0109-basic-center-geoip-example.html +++ b/examples/0109-basic-center-geoip-example.html @@ -24,9 +24,9 @@ lat: res.latitude, lng: res.longitude, zoom: 10 - } + }; $scope.ip = res.ip; - }) + }); }; $scope.searchIP(""); @@ -41,7 +41,7 @@ - +

        Center by IP (GeoIP) example

        Insert the IP you want to know its location:

        diff --git a/examples/0110-basic-map-without-animations-example.html b/examples/0110-basic-map-without-animations-example.html index bcbdf0bf..b3c90b05 100644 --- a/examples/0110-basic-map-without-animations-example.html +++ b/examples/0110-basic-map-without-animations-example.html @@ -31,7 +31,7 @@ - +

        Map with disabled animations example

        diff --git a/examples/0111-basic-legend-example.html b/examples/0111-basic-legend-example.html index bac7b217..f315475f 100644 --- a/examples/0111-basic-legend-example.html +++ b/examples/0111-basic-legend-example.html @@ -47,7 +47,7 @@ - +

        Legend example

        diff --git a/examples/0112-basic-maxbounds-pad-example.html b/examples/0112-basic-maxbounds-pad-example.html index 265b000c..5ab5c5a7 100644 --- a/examples/0112-basic-maxbounds-pad-example.html +++ b/examples/0112-basic-maxbounds-pad-example.html @@ -55,7 +55,7 @@ - +

        Extend Maxbounds with Pad

        You can extend maxbounds with a pad property. Pad is a percentage by which the latLngBounds will be extended.

        
        diff --git a/examples/0113-basic-geojson-simple-example.html b/examples/0113-basic-geojson-simple-example.html
        index c145920c..636b699e 100644
        --- a/examples/0113-basic-geojson-simple-example.html
        +++ b/examples/0113-basic-geojson-simple-example.html
        @@ -40,7 +40,7 @@
               
           
           
        -     
        +     
              

        Simple GeoJSON example

        diff --git a/examples/0114-basic-geojson-center-example.html b/examples/0114-basic-geojson-center-example.html index 7b15afdc..da49e786 100644 --- a/examples/0114-basic-geojson-center-example.html +++ b/examples/0114-basic-geojson-center-example.html @@ -56,7 +56,7 @@ - +

        Center to GeoJSON example

        diff --git a/examples/0115-basic-events-example.html b/examples/0115-basic-events-example.html index 034c4734..8b0eaad2 100644 --- a/examples/0115-basic-events-example.html +++ b/examples/0115-basic-events-example.html @@ -4,11 +4,11 @@ - + - +

        Events example

        All map events are propagated by default.

          diff --git a/examples/0116-basic-access-leaflet-object-example.html b/examples/0116-basic-access-leaflet-object-example.html index 73754b7b..426fab8c 100644 --- a/examples/0116-basic-access-leaflet-object-example.html +++ b/examples/0116-basic-access-leaflet-object-example.html @@ -32,7 +32,7 @@ - +

          Direct access to the Leaflet Map Object

          diff --git a/examples/0118-basic-double-map-events-example.html b/examples/0118-basic-double-map-events-example.html index 17823aaa..e8b74056 100644 --- a/examples/0118-basic-double-map-events-example.html +++ b/examples/0118-basic-double-map-events-example.html @@ -81,10 +81,10 @@

          Different map events broadcasting

          We can filter which leaflet events we propagate upwars using the event-broadcast directive property, let's see how it works:

          This map propagates all events

          - +

          Event:

          This map propagates the "click" and "dblclick" events

          - +

          Event:

          diff --git a/examples/0119-basic-double-map-access-map-object-example.html b/examples/0119-basic-double-map-access-map-object-example.html index e49a88f9..6ffe1b63 100644 --- a/examples/0119-basic-double-map-access-map-object-example.html +++ b/examples/0119-basic-double-map-access-map-object-example.html @@ -43,10 +43,10 @@
          - +
          - +

          Accesing the map object with two (or more) maps on screen

          diff --git a/examples/0120-basic-double-map-sharing-attributes-example.html b/examples/0120-basic-double-map-sharing-attributes-example.html index 3a51aac6..d65b593e 100644 --- a/examples/0120-basic-double-map-sharing-attributes-example.html +++ b/examples/0120-basic-double-map-sharing-attributes-example.html @@ -58,10 +58,10 @@
          - +
          - +

          Two maps sharing center example

          Drag the center in any of the maps

          diff --git a/examples/0121-basic-double-map-toggle-example.html b/examples/0121-basic-double-map-toggle-example.html index 5e517a36..41eaab46 100644 --- a/examples/0121-basic-double-map-toggle-example.html +++ b/examples/0121-basic-double-map-toggle-example.html @@ -75,8 +75,8 @@ - - + +

          Toggle between two maps on screen

          View javascript console while toggling map

          diff --git a/examples/0122-basic-geojson-update-example.html b/examples/0122-basic-geojson-update-example.html index 195817c8..90477f01 100644 --- a/examples/0122-basic-geojson-update-example.html +++ b/examples/0122-basic-geojson-update-example.html @@ -99,13 +99,13 @@ } } ] - } + }; } }]); - +

          GeoJSON update example

          diff --git a/examples/0123-basic-hide-show-map-example.html b/examples/0123-basic-hide-show-map-example.html index 8ecea4d3..f5d6ef3a 100644 --- a/examples/0123-basic-hide-show-map-example.html +++ b/examples/0123-basic-hide-show-map-example.html @@ -29,7 +29,7 @@ - +

          Hide/Show map example

          Select to show the map

          Center: {{ center }}

          diff --git a/examples/0124-basic-geojson-non-nested-example.html b/examples/0124-basic-geojson-non-nested-example.html index f2fd5952..955e429d 100644 --- a/examples/0124-basic-geojson-non-nested-example.html +++ b/examples/0124-basic-geojson-non-nested-example.html @@ -4,7 +4,7 @@ - + - +

          GeoJSON non nested example

          diff --git a/examples/0125-basic-geojson-nested-example.html b/examples/0125-basic-geojson-nested-example.html index fa8d77fb..39ce50aa 100644 --- a/examples/0125-basic-geojson-nested-example.html +++ b/examples/0125-basic-geojson-nested-example.html @@ -4,7 +4,7 @@ - + - +

          GeoJSON nested example

          diff --git a/examples/0127-basic-tiles-wms-example.html b/examples/0127-basic-tiles-wms-example.html new file mode 100644 index 00000000..b2ae0301 --- /dev/null +++ b/examples/0127-basic-tiles-wms-example.html @@ -0,0 +1,73 @@ + + + + + + + + + + + + +

          Loading WMS tilesDict example

          +

          Change tiles clicking in the buttons below:

          +

          + + + +

          +

          Current TileLayer Url:

          + + diff --git a/examples/0201-layers-simple-example.html b/examples/0201-layers-simple-example.html index f9bafdc0..2aa38e3f 100644 --- a/examples/0201-layers-simple-example.html +++ b/examples/0201-layers-simple-example.html @@ -44,7 +44,7 @@ - +

          Layers simple example

          You can easily add various layers to your map, including a layer selector on the top right, defining layers object.

          diff --git a/examples/0202-layers-overlays-simple-example.html b/examples/0202-layers-overlays-simple-example.html index dd3e4c93..69eee7dc 100644 --- a/examples/0202-layers-overlays-simple-example.html +++ b/examples/0202-layers-overlays-simple-example.html @@ -42,7 +42,7 @@ - +

          Baselayer with overlays

          You can add overlays to a baselayer, which will show a layer selector on the top right corner, defining layers like in this example.

          diff --git a/examples/0203-layers-imageoverlay-example.html b/examples/0203-layers-imageoverlay-example.html index e3c97f89..ed9b2dd4 100644 --- a/examples/0203-layers-imageoverlay-example.html +++ b/examples/0203-layers-imageoverlay-example.html @@ -42,7 +42,7 @@ - +

          Layer with image overlay and maxBounds

          diff --git a/examples/0204-layers-dynamic-addition-example.html b/examples/0204-layers-dynamic-addition-example.html index cd421197..399ee6e7 100644 --- a/examples/0204-layers-dynamic-addition-example.html +++ b/examples/0204-layers-dynamic-addition-example.html @@ -81,7 +81,7 @@ - +

          Dynamic addition/removal of layers

          diff --git a/examples/0205-layers-googlemaps-example.html b/examples/0205-layers-googlemaps-example.html index 6454d785..54daf9cf 100644 --- a/examples/0205-layers-googlemaps-example.html +++ b/examples/0205-layers-googlemaps-example.html @@ -48,7 +48,7 @@ - +

          Google maps example

          Use the Layer Switch Control on the top rigth of the map to select another Google Maps Layer.

          diff --git a/examples/0206-layers-googlemaps-fullsize-example.html b/examples/0206-layers-googlemaps-fullsize-example.html index fb0938c2..235ced65 100644 --- a/examples/0206-layers-googlemaps-fullsize-example.html +++ b/examples/0206-layers-googlemaps-fullsize-example.html @@ -64,7 +64,7 @@
          - +

          Google Maps fullsize example

          Open this example as stand-alone page with the bottom link to see how it fullscreens your monitor

          diff --git a/examples/0207-layers-hide-baselayer-on-selector-example.html b/examples/0207-layers-hide-baselayer-on-selector-example.html index 29fb0820..2bbabafc 100644 --- a/examples/0207-layers-hide-baselayer-on-selector-example.html +++ b/examples/0207-layers-hide-baselayer-on-selector-example.html @@ -45,7 +45,7 @@ - +

          Baselayer hidden on switch selector to show only overlay

          Open the layer switch selector to see it.

          
          diff --git a/examples/0208-layers-esri-dynamic-layer-example.html b/examples/0208-layers-esri-dynamic-layer-example.html
          index 3113a76c..ec2cab0c 100644
          --- a/examples/0208-layers-esri-dynamic-layer-example.html
          +++ b/examples/0208-layers-esri-dynamic-layer-example.html
          @@ -54,7 +54,7 @@
               
           
           
          -    
          +    
               

          Esri ArcGIS Dynamic Map Layer

          Use the Layer Switch Control on the top rigth of the map to select another Esri Layer.

          diff --git a/examples/0209-layers-esri-legend-service-example.html b/examples/0209-layers-esri-legend-service-example.html index 9b7d34b1..95bb8e1e 100644 --- a/examples/0209-layers-esri-legend-service-example.html +++ b/examples/0209-layers-esri-legend-service-example.html @@ -102,7 +102,7 @@ overlays: { usa_pop: { name: "USA 2000-2010 Population Change", - type: "dynamic", + type: "agsDynamic", url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer", visible: true, layerOptions: { @@ -112,7 +112,7 @@ }, usa_social: { name: "USA Social Vulnerability Index", - type: "dynamic", + type: "agsDynamic", url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer", visible: false, layerOptions: { @@ -142,7 +142,7 @@ -

          Esri ArcGIS Legend Service

          Use the button to switch another Esri Legend.

          diff --git a/examples/0210-layers-webgl-heatmap-example.html b/examples/0210-layers-webgl-heatmap-example.html index ebf13247..aae21288 100644 --- a/examples/0210-layers-webgl-heatmap-example.html +++ b/examples/0210-layers-webgl-heatmap-example.html @@ -43,7 +43,7 @@ - +

          HeatMap WebGL overlay example

          You can use the WebGL HeatMap overlay plugin, like this. Please read the heatmap plugin documentation to use it.

          
          diff --git a/examples/0211-layers-layergroup-simple-example.html b/examples/0211-layers-layergroup-simple-example.html
          index f4d43e5f..282a49ff 100644
          --- a/examples/0211-layers-layergroup-simple-example.html
          +++ b/examples/0211-layers-layergroup-simple-example.html
          @@ -70,7 +70,7 @@
               
           
           
          -    
          +    
               

          Layer Groups with nested layer definitions

          You can add layer groups to a map. In this case, a UTF Grid and Tile Layer are grouped. Notice that the layers show as one in the layer selector control.

          You hovered over:

          diff --git a/examples/0212-layers-hide-overlays-on-selector-example.html b/examples/0212-layers-hide-overlays-on-selector-example.html index b44d83e5..c7f135d1 100644 --- a/examples/0212-layers-hide-overlays-on-selector-example.html +++ b/examples/0212-layers-hide-overlays-on-selector-example.html @@ -51,7 +51,7 @@ - +

          Overlay not shown in selector

          diff --git a/examples/0213-layers-bingmaps-example.html b/examples/0213-layers-bingmaps-example.html index 8808dc99..a5c27398 100644 --- a/examples/0213-layers-bingmaps-example.html +++ b/examples/0213-layers-bingmaps-example.html @@ -57,7 +57,7 @@ - +

          Bing maps

          Use the Layer Switch Control on the top rigth of the map to select another Bing Maps Layer.

          diff --git a/examples/0214-layers-utfgrid-example.html b/examples/0214-layers-utfgrid-example.html index 28c299bd..f2378bfc 100644 --- a/examples/0214-layers-utfgrid-example.html +++ b/examples/0214-layers-utfgrid-example.html @@ -53,7 +53,7 @@ - +

          Baselayer with UTFGrid interactivity in Overlay

          Mouse over the map regions to interact with UTFGrid.

          {{interactivity}}

          diff --git a/examples/0216-layers-overlays-markercluster-example.html b/examples/0216-layers-overlays-markercluster-example.html index 7aedb854..df71c4be 100644 --- a/examples/0216-layers-overlays-markercluster-example.html +++ b/examples/0216-layers-overlays-markercluster-example.html @@ -2,9 +2,9 @@ - + - + @@ -106,7 +106,7 @@ - +

          This is a map with overlays and a markercluster

          In this example we use a MarkerCluster overlay to group the markers instead of a LayerGroup. diff --git a/examples/0218-layers-overlays-markers-nested-example.html b/examples/0218-layers-overlays-markers-nested-example.html index aab16e86..c93b6094 100644 --- a/examples/0218-layers-overlays-markers-nested-example.html +++ b/examples/0218-layers-overlays-markers-nested-example.html @@ -3,8 +3,8 @@ - - + + - - +

          Different overlays for paths

          In this example we create two layer groups lines, and shapes. We insert markers in both layers (note that on is initially diff --git a/examples/0220-layers-wms-with-different-projection-example.html b/examples/0220-layers-wms-with-different-projection-example.html index 08d8192b..a005a8d8 100644 --- a/examples/0220-layers-wms-with-different-projection-example.html +++ b/examples/0220-layers-wms-with-different-projection-example.html @@ -54,6 +54,6 @@

          Load a map in non standard projection

          - + diff --git a/examples/0221-layers-heatmap-example.html b/examples/0221-layers-heatmap-example.html index 7b94f4b7..419c6a02 100644 --- a/examples/0221-layers-heatmap-example.html +++ b/examples/0221-layers-heatmap-example.html @@ -59,7 +59,7 @@ - +

          HeatMap example

          This example uses the Leaflet.heat library.

          The example is inspired in this Google Maps Heat example.

          diff --git a/examples/0222-layers-overlays-hide-on-zoomout-example.html b/examples/0222-layers-overlays-hide-on-zoomout-example.html index 782b1a88..ca042363 100644 --- a/examples/0222-layers-overlays-hide-on-zoomout-example.html +++ b/examples/0222-layers-overlays-hide-on-zoomout-example.html @@ -46,7 +46,7 @@ - +

          Baselayer with overlay which is hidden on Zoom less than 4

          zoom: {{center.zoom}} diff --git a/examples/0223-layers-refresh-overlay-every-minute-example.html b/examples/0223-layers-refresh-overlay-every-minute-example.html index 13ce5019..dd135c38 100644 --- a/examples/0223-layers-refresh-overlay-every-minute-example.html +++ b/examples/0223-layers-refresh-overlay-every-minute-example.html @@ -55,7 +55,7 @@ - +

          Refreshable overlays example

          You can refresh the overlay/baselayer state adding a boolean property to the layer:

          diff --git a/examples/0224-layers-esri-base-layer-example.html b/examples/0224-layers-esri-base-layer-example.html
          index 48cb6326..9ce9447e 100644
          --- a/examples/0224-layers-esri-base-layer-example.html
          +++ b/examples/0224-layers-esri-base-layer-example.html
          @@ -86,7 +86,7 @@
               
           
           
          -    
          +    
               

          Esri ArcGIS Basemap Layer

          Use the Layer Switch Control on the top rigth of the map to select another Esri Basemap Layer.

          diff --git a/examples/0225-layers-esri-feature-layer-example.html b/examples/0225-layers-esri-feature-layer-example.html index 349ebcf5..3ebf7ad9 100644 --- a/examples/0225-layers-esri-feature-layer-example.html +++ b/examples/0225-layers-esri-feature-layer-example.html @@ -3,15 +3,24 @@ + - + + + - + + + +

          Esri ArcGIS Feature Layer

          Use the Layer Switch Control on the top rigth of the map to show another Esri Feature Layers.

          diff --git a/examples/0226-layers-esri-tiled-map-layer-example.html b/examples/0226-layers-esri-tiled-map-layer-example.html index 899f96cd..4a38a872 100644 --- a/examples/0226-layers-esri-tiled-map-layer-example.html +++ b/examples/0226-layers-esri-tiled-map-layer-example.html @@ -39,7 +39,7 @@ - +

          Esri ArcGIS Tiled Map Layer

          Use the Layer Switch Control on the top rigth of the map to show another Esri Tiled Map Layers.

          diff --git a/examples/0227-layers-esri-image-layer-example.html b/examples/0227-layers-esri-image-layer-example.html index 8baf6331..c58c7f4e 100644 --- a/examples/0227-layers-esri-image-layer-example.html +++ b/examples/0227-layers-esri-image-layer-example.html @@ -44,7 +44,7 @@ - +

          Esri ArcGIS Image Layer

          Display NAIP imagery from an ArcGIS image service and use the band IDs parameter to show the near infrared band in a diff --git a/examples/0228-layers-esri-clustered-layer-example.html b/examples/0228-layers-esri-clustered-layer-example.html index 5ccac5ed..f27aa6c0 100644 --- a/examples/0228-layers-esri-clustered-layer-example.html +++ b/examples/0228-layers-esri-clustered-layer-example.html @@ -44,7 +44,7 @@ - +

          Esri ArcGIS Clustered Layer

          Visualize dense services as clusters of points with the diff --git a/examples/0229-layers-esri-heatmap-layer-example.html b/examples/0229-layers-esri-heatmap-layer-example.html index 3a4b870c..af792910 100644 --- a/examples/0229-layers-esri-heatmap-layer-example.html +++ b/examples/0229-layers-esri-heatmap-layer-example.html @@ -52,7 +52,7 @@ - +

          Esri ArcGIS Heatmap Layer

          Displaying point data as a heatmap using the L.heat plugin with custom styling of heatmap gradients with the L.heat options. diff --git a/examples/0230-layers-yandex-example.html b/examples/0230-layers-yandex-example.html index 5387b957..5abe1a3d 100644 --- a/examples/0230-layers-yandex-example.html +++ b/examples/0230-layers-yandex-example.html @@ -50,7 +50,7 @@ - +

          Yandex layer example

          Use the Layer Switch Control on the top rigth of the map to select another Yandex Layer.

          diff --git a/examples/0231-layers-overlay-geojson-example.html b/examples/0231-layers-overlay-geojson-example.html index e685062a..cf71a968 100644 --- a/examples/0231-layers-overlay-geojson-example.html +++ b/examples/0231-layers-overlay-geojson-example.html @@ -5,49 +5,62 @@ - - - + + + + + - -

          Yandex layer example

          -

          Use the Layer Switch Control on the top rigth of the map to select another Yandex Layer.

          + +

          GeoJSON Shape Layer and GeoJSON Awesome Marker Layer

          +

          Use the layer control to add a geoJSON shape layer. This is different from a GeoJSON layer, which is a Tile Layer

          +

          The example also includes a geoJSON Awesome Markers layer, which you can use to customise marker icons easily.

          diff --git a/examples/0300-paths-simple-example.html b/examples/0300-paths-simple-example.html index 946a77b0..eb4ff017 100644 --- a/examples/0300-paths-simple-example.html +++ b/examples/0300-paths-simple-example.html @@ -44,7 +44,7 @@ - +

          Paths simple example

          Click on red route (Popup) or hover over green route (Label) to get more information

          diff --git a/examples/0301-paths-types-example.html b/examples/0301-paths-types-example.html index 11c454df..85173bbe 100644 --- a/examples/0301-paths-types-example.html +++ b/examples/0301-paths-types-example.html @@ -99,7 +99,7 @@ - +

          Types of paths

          diff --git a/examples/0302-paths-ajax-load-example.html b/examples/0302-paths-ajax-load-example.html index ee25ac62..5270de9a 100644 --- a/examples/0302-paths-ajax-load-example.html +++ b/examples/0302-paths-ajax-load-example.html @@ -38,7 +38,7 @@ - +

          Load remote paths example

          Click on red route (Popup) or hover over green route (Label) to get more information

          diff --git a/examples/0303-paths-3000-items-example.html b/examples/0303-paths-3000-items-example.html index 12b083af..1b186a72 100644 --- a/examples/0303-paths-3000-items-example.html +++ b/examples/0303-paths-3000-items-example.html @@ -140,7 +140,7 @@ - +

          3000 items in a map performance

          diff --git a/examples/0304-paths-advanced-example.html b/examples/0304-paths-advanced-example.html index 905719b8..f7d65c70 100644 --- a/examples/0304-paths-advanced-example.html +++ b/examples/0304-paths-advanced-example.html @@ -154,7 +154,7 @@ - +

          Advanced Paths Example

          diff --git a/examples/0305-paths-change-in-group-layer-example.html b/examples/0305-paths-change-in-group-layer-example.html index 72012227..1267a2f9 100644 --- a/examples/0305-paths-change-in-group-layer-example.html +++ b/examples/0305-paths-change-in-group-layer-example.html @@ -59,7 +59,7 @@ - +

          Path change in group layer

          diff --git a/examples/0306-paths-decorations-simple-example.html b/examples/0306-paths-decorations-simple-example.html index 94d00b59..0e12d702 100644 --- a/examples/0306-paths-decorations-simple-example.html +++ b/examples/0306-paths-decorations-simple-example.html @@ -4,7 +4,7 @@ - + - +

          Path decoration example

          diff --git a/examples/0307-paths-events-example-with-id.html b/examples/0307-paths-events-example-with-id.html new file mode 100644 index 00000000..ade6ab7e --- /dev/null +++ b/examples/0307-paths-events-example-with-id.html @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + +

          Paths specific events propagation exampl

          +

          Click on path points to trigger an event

          +

          Mouse over:

          +

          You clicked {{clicked}} times

          + + diff --git a/examples/0307-paths-events-example.html b/examples/0307-paths-events-example.html index 425675e6..abb5925e 100644 --- a/examples/0307-paths-events-example.html +++ b/examples/0307-paths-events-example.html @@ -10,8 +10,7 @@ - - + +

          Paths specific events propagation exampl

          Click on path points to trigger an event

          Mouse over:

          diff --git a/examples/0400-controls-custom-layer-control-example.html b/examples/0400-controls-custom-layer-control-example.html index 359f56dc..e241a377 100644 --- a/examples/0400-controls-custom-layer-control-example.html +++ b/examples/0400-controls-custom-layer-control-example.html @@ -102,7 +102,8 @@ layerOptions: { attribution: "© OpenFireMap contributors - © OpenStreetMap contributors", continuousWorld: true - } + }, + group: "Open Fire Map" }; }, existsFireLayer: function() { @@ -119,7 +120,8 @@ layerOptions: { attribution: "© OpenFireMap contributors - © OpenStreetMap contributors", continuousWorld: true - } + }, + group: "Open Fire Map" }; }, existsEmergencyRooms: function() { @@ -140,7 +142,8 @@ opacity: 0.25, attribution: "Hillshade layer by GIScience http://www.osm-wms.de", crs: L.CRS.EPSG900913 - } + }, + group: "Raster" }; }, existsHillshadeLayer: function() { @@ -152,46 +155,46 @@ - + diff --git a/examples/0401-controls-draw-example.html b/examples/0401-controls-draw-example.html index 0b9a601f..d9118eff 100644 --- a/examples/0401-controls-draw-example.html +++ b/examples/0401-controls-draw-example.html @@ -68,7 +68,7 @@ - +

          Draw control example

          Draw a shape and a geoJSON data structure will be shown on the console.log.

          diff --git a/examples/0402-controls-scale-example.html b/examples/0402-controls-scale-example.html index ee6db500..5abd8fd1 100644 --- a/examples/0402-controls-scale-example.html +++ b/examples/0402-controls-scale-example.html @@ -23,7 +23,7 @@ - +

          Scale control example

          diff --git a/examples/0403-controls-fullscreen-example.html b/examples/0403-controls-fullscreen-example.html index 17c8cfde..392fb1e6 100644 --- a/examples/0403-controls-fullscreen-example.html +++ b/examples/0403-controls-fullscreen-example.html @@ -37,7 +37,7 @@ - +

          Fullscreen control example

          Fullscreen control with the Leaflet fullscreen plugin.

          diff --git a/examples/0404-controls-minimap-example.html b/examples/0404-controls-minimap-example.html index 9e3d67ff..85724172 100644 --- a/examples/0404-controls-minimap-example.html +++ b/examples/0404-controls-minimap-example.html @@ -51,7 +51,7 @@ - +

          Minimap control example

          Minimap control with the Leaflet minimap plugin.

          diff --git a/examples/0405-controls-search-example.html b/examples/0405-controls-search-example.html index e7eb8e06..1c99863f 100644 --- a/examples/0405-controls-search-example.html +++ b/examples/0405-controls-search-example.html @@ -103,7 +103,7 @@ - +

          Search control example

          Search for any of the marker names (mouseover to see the name). This is a simple example of use of Leaflet search plugin.

          diff --git a/examples/0406-controls-custom-example.html b/examples/0406-controls-custom-example.html new file mode 100644 index 00000000..fc46ce1e --- /dev/null +++ b/examples/0406-controls-custom-example.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + +

          Fullscreen control example

          +

          Fullscreen control with the Leaflet fullscreen plugin.

          + + diff --git a/examples/0500-markers-simple-example.html b/examples/0500-markers-simple-example.html index 8b0a15a1..aa469eaf 100644 --- a/examples/0500-markers-simple-example.html +++ b/examples/0500-markers-simple-example.html @@ -4,7 +4,7 @@ - + - + - +

          Markers simple example

          Initial marker position (lat/lng): /

          Actual marker position (lat/lng): /

          diff --git a/examples/0501-markers-events-add-example.html b/examples/0501-markers-events-add-example.html index 7aea0925..730d504b 100644 --- a/examples/0501-markers-events-add-example.html +++ b/examples/0501-markers-events-add-example.html @@ -4,7 +4,7 @@ - + - +

          Markers with events example

          Click on the map to add a marker

          diff --git a/examples/0502-markers-add-remove-example.html b/examples/0502-markers-add-remove-example.html index 8881cf7e..81f214ec 100644 --- a/examples/0502-markers-add-remove-example.html +++ b/examples/0502-markers-add-remove-example.html @@ -46,7 +46,7 @@ - +

          Add/remove markers easily example

          diff --git a/examples/0503-markers-icons-example.html b/examples/0503-markers-icons-example.html index d59a7ec8..97e28278 100644 --- a/examples/0503-markers-icons-example.html +++ b/examples/0503-markers-icons-example.html @@ -5,6 +5,7 @@ + @@ -13,6 +14,7 @@ + - + - +

          Marker Popup properties

          Marker position

          Latitude: diff --git a/examples/0505-markers-label-example.html b/examples/0505-markers-label-example.html index 95671e05..265754c4 100644 --- a/examples/0505-markers-label-example.html +++ b/examples/0505-markers-label-example.html @@ -41,7 +41,7 @@ - +

          Marker with label example

          diff --git a/examples/0506-markers-groups-example.html b/examples/0506-markers-groups-example.html index a8112252..3cd1f739 100644 --- a/examples/0506-markers-groups-example.html +++ b/examples/0506-markers-groups-example.html @@ -4,7 +4,7 @@ - + - +

          Changing Icon Rotation

          diff --git a/examples/0507-markers-change-opacity-example.html b/examples/0508-markers-change-opacity-example.html similarity index 93% rename from examples/0507-markers-change-opacity-example.html rename to examples/0508-markers-change-opacity-example.html index a6834d03..1a375e28 100644 --- a/examples/0507-markers-change-opacity-example.html +++ b/examples/0508-markers-change-opacity-example.html @@ -29,7 +29,7 @@ - +

          Change icon opacity

          Move the slider to change the icon opacity.

          diff --git a/examples/0508-markers-clustering-example.html b/examples/0509-markers-clustering-example.html similarity index 97% rename from examples/0508-markers-clustering-example.html rename to examples/0509-markers-clustering-example.html index 4a5c9ee7..5e919345 100644 --- a/examples/0508-markers-clustering-example.html +++ b/examples/0509-markers-clustering-example.html @@ -105,7 +105,7 @@ - +

          Marker clustering example

          You can create a marker-clustering group on the map, defining layers and your markers definition as this example.

          diff --git a/examples/0509-markers-clustering-without-overlays-example.html b/examples/0510-markers-clustering-without-overlays-example.html similarity index 97% rename from examples/0509-markers-clustering-without-overlays-example.html rename to examples/0510-markers-clustering-without-overlays-example.html index 5713251d..d5d21e62 100644 --- a/examples/0509-markers-clustering-without-overlays-example.html +++ b/examples/0510-markers-clustering-without-overlays-example.html @@ -78,7 +78,7 @@ - +

          Marker clustering example without layers

          diff --git a/examples/0510-markers-modal-markercluster-example.html b/examples/0511-markers-modal-markercluster-example.html similarity index 96% rename from examples/0510-markers-modal-markercluster-example.html rename to examples/0511-markers-modal-markercluster-example.html index 7aa144ad..53bd6da6 100644 --- a/examples/0510-markers-modal-markercluster-example.html +++ b/examples/0511-markers-modal-markercluster-example.html @@ -101,7 +101,7 @@

          Markercluster in a SemanticUI modal

          Modal map example
          - +
          Cancel
          diff --git a/examples/0511-markers-clustering-10000-markers-example.html b/examples/0512-markers-clustering-10000-markers-example.html similarity index 95% rename from examples/0511-markers-clustering-10000-markers-example.html rename to examples/0512-markers-clustering-10000-markers-example.html index c24bea09..da9aec47 100644 --- a/examples/0511-markers-clustering-10000-markers-example.html +++ b/examples/0512-markers-clustering-10000-markers-example.html @@ -64,7 +64,7 @@ - +

          Marker clustering example (10000 markers)

          diff --git a/examples/0512-markers-events-example.html b/examples/0513-markers-events-example-with-id.html similarity index 75% rename from examples/0512-markers-events-example.html rename to examples/0513-markers-events-example-with-id.html index b6d1866c..d5a036d1 100644 --- a/examples/0512-markers-events-example.html +++ b/examples/0513-markers-events-example-with-id.html @@ -4,11 +4,11 @@ - + - +

          Marker Events example

          • event caught in listener.
          • diff --git a/examples/0513-markers-events-example.html b/examples/0513-markers-events-example.html new file mode 100644 index 00000000..6522b7e1 --- /dev/null +++ b/examples/0513-markers-events-example.html @@ -0,0 +1,53 @@ + + + + + + + + + + + + +

            Marker Events example

            +
              +
            • event caught in listener.
            • +
            + + diff --git a/examples/0513-markers-delayed-events.html b/examples/0514-markers-delayed-events.html similarity index 95% rename from examples/0513-markers-delayed-events.html rename to examples/0514-markers-delayed-events.html index 2f108533..514adfc4 100644 --- a/examples/0513-markers-delayed-events.html +++ b/examples/0514-markers-delayed-events.html @@ -61,7 +61,7 @@ - +

            Markers delayed events example

            diff --git a/examples/0514-markers-angular-template-example.html b/examples/0515-markers-angular-template-example.html similarity index 94% rename from examples/0514-markers-angular-template-example.html rename to examples/0515-markers-angular-template-example.html index 8443305a..cdf2660a 100644 --- a/examples/0514-markers-angular-template-example.html +++ b/examples/0515-markers-angular-template-example.html @@ -3,7 +3,7 @@ - + + + + + + +
            +
            + {{ selectedCountry.properties.name || 'No country'}} +
            +
            Map center: [ lat: {{ center.lat | number:4 }}, lng: {{ center.lng | number:4 }} ]
            +

            World map flags example

            + + diff --git a/examples/0601-mixed-geojson-events-example.html b/examples/0601-mixed-geojson-events-example.html index 9da5c868..9908aa2f 100644 --- a/examples/0601-mixed-geojson-events-example.html +++ b/examples/0601-mixed-geojson-events-example.html @@ -4,7 +4,7 @@ - + - +
            {{ selectedCountry.properties.name || 'No country'}} diff --git a/examples/0602-mixed-mapbox-tiles-geojson-example.html b/examples/0602-mixed-mapbox-tiles-geojson-example.html index b3bea271..7c6e6a61 100644 --- a/examples/0602-mixed-mapbox-tiles-geojson-example.html +++ b/examples/0602-mixed-mapbox-tiles-geojson-example.html @@ -37,7 +37,7 @@ - +

            Mapbox tiles and Mapbox GeoJSON loading

            
             
            diff --git a/examples/0603-mixed-layers-overlays-geojson-example.html b/examples/0603-mixed-layers-overlays-geojson-example.html
            index 65124a7e..d691b298 100644
            --- a/examples/0603-mixed-layers-overlays-geojson-example.html
            +++ b/examples/0603-mixed-layers-overlays-geojson-example.html
            @@ -1,82 +1,82 @@
             
             
             
            -	
            -	
            -	
            -	
            -	
            -	
            -	
            +    
            +    
            +    
            +    
            +    
            +                    }
            +                }
            +            })
            +        }]);
            +    
             
             
            -		
            -		

            GeoJSON TileLayers

            -

            Data source: Openstreetmap (buildings data)

            + +

            GeoJSON TileLayers

            +

            Data source: Openstreetmap (buildings data)

            diff --git a/examples/0604-mixed-markers-nested-events-example.html b/examples/0604-mixed-markers-nested-events-example.html index 45a6eef8..d79e95ed 100644 --- a/examples/0604-mixed-markers-nested-events-example.html +++ b/examples/0604-mixed-markers-nested-events-example.html @@ -4,79 +4,79 @@ - + - + + + + + + + + + + + + +

            Esri ArcGIS Legend Service

            +

            Use the button to switch another Esri Legend.

            +
            + + + diff --git a/examples/0607-mixed-esri-multilayer-legend-service-example.html b/examples/0607-mixed-esri-multilayer-legend-service-example.html new file mode 100644 index 00000000..1919d19c --- /dev/null +++ b/examples/0607-mixed-esri-multilayer-legend-service-example.html @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + +

            Esri ArcGIS Multilayer Legend Service

            +

            Use the button to switch another Esri Legend.

            +
            + + + diff --git a/examples/js/controllers.js b/examples/js/controllers.js index 7d451332..e4fe5736 100644 --- a/examples/js/controllers.js +++ b/examples/js/controllers.js @@ -62,9 +62,9 @@ var app = angular.module('webapp'); lat: res.latitude, lng: res.longitude, zoom: 10 - } + }; $scope.ip = res.ip; - }) + }); }; $scope.searchIP(""); }]); @@ -82,7 +82,7 @@ var app = angular.module('webapp'); }); $scope.changeLocation = function(centerHash) { $location.search({ c: centerHash }); - } + }; }]); app.controller('BasicCustomParametersController', [ '$scope', function($scope) { angular.extend($scope, { @@ -296,14 +296,14 @@ var app = angular.module('webapp'); }); app.controller('BasicDynamicAddRemoveMapExample', [ '$scope', 'leafletData', function($scope, leafletData) { } ]); - app.controller("BasicEventsController", [ "$scope", "leafletEvents", function($scope, leafletEvents) { + app.controller("BasicEventsController", [ "$scope", "leafletMapEvents", function($scope, leafletMapEvents) { $scope.center = { lat: 51.505, lng: -0.09, zoom: 8 }; $scope.eventDetected = "No events yet..."; - var mapEvents = leafletEvents.getAvailableMapEvents(); + var mapEvents = leafletMapEvents.getAvailableMapEvents(); for (var k in mapEvents){ var eventName = 'leafletDirectiveMap.' + mapEvents[k]; $scope.$on(eventName, function(event){ @@ -404,7 +404,7 @@ var app = angular.module('webapp'); } } ] - } + }; } }]); app.controller('BasicHideShowMapController', function($scope, $timeout, leafletData) { @@ -424,6 +424,15 @@ var app = angular.module('webapp'); } }); }); + app.controller('BasicLFCenterController', [ '$scope', function($scope) { + angular.extend($scope, { + london: { + lat: 51.505, + lng: -0.09, + zoom: 4 + } + }); + }]); app.controller('BasicLegendController', [ '$scope', function($scope) { angular.extend($scope, { london: { @@ -582,6 +591,53 @@ var app = angular.module('webapp'); $scope.tiles = tilesDict[tiles]; }; } ]); + app.controller('BasicTilesWMSController', [ '$scope', function($scope) { + var tilesDict = { + openstreetmap: { + url: "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", + options: { + attribution: '© OpenStreetMap contributors' + } + }, + standard: { + name: 'MAP Standard', + type: 'wms', + url: 'https://api.minu.mn/wms', + layerParams: { + layers: 'mongolid:mimap', + format: 'image/png', + transparent: true, + tiled: true, + version: '1.3.0', + maxZoom: 19 + } + }, + blue: { + name: 'MAP Blue', + type: 'wms', + url: 'https://api.minu.mn/wms', + layerParams: { + layers: 'mongolid:mimap_blue', // it's published not yet. + format: 'image/png', + transparent: true, + tiled: true, + version: '1.3.0', + maxZoom: 19 + } + } + }; + angular.extend($scope, { + ulaanbaatar: { + lat: 47.918464, + lng: 106.917678, + zoom: 5 + }, + tiles: tilesDict.openstreetmap + }); + $scope.changeTiles = function(tiles) { + $scope.tiles = tilesDict[tiles]; + }; + } ]); app.controller('BasicTilesZoomChangerController', [ "$scope", function($scope) { angular.extend($scope, { london: { @@ -599,6 +655,27 @@ var app = angular.module('webapp'); : "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"; }); } ]); + app.controller("ControlsCustomController", [ "$scope", function($scope) { + angular.extend($scope, { + london: { + lat: 37.8, + lng: -96, + zoom: 5 + }, + tiles: { + name: 'Mapbox Comic', + url: 'http://api.tiles.mapbox.com/v4/{mapid}/{z}/{x}/{y}.png?access_token={apikey}', + type: 'xyz', + options: { + apikey: 'pk.eyJ1IjoiYnVmYW51dm9scyIsImEiOiJLSURpX0pnIn0.2_9NrLz1U9bpwMQBhVk97Q', + mapid: 'bufanuvols.lpa06kfg' + } + }, + controls: { + custom: new L.Control.Fullscreen() + } + }); + }]); app.controller("ControlsCustomLayerControlController", [ "$scope", function($scope) { angular.extend($scope, { layercontrol: { @@ -689,7 +766,8 @@ var app = angular.module('webapp'); layerOptions: { attribution: "© OpenFireMap contributors - © OpenStreetMap contributors", continuousWorld: true - } + }, + group: "Open Fire Map" }; }, existsFireLayer: function() { @@ -706,7 +784,8 @@ var app = angular.module('webapp'); layerOptions: { attribution: "© OpenFireMap contributors - © OpenStreetMap contributors", continuousWorld: true - } + }, + group: "Open Fire Map" }; }, existsEmergencyRooms: function() { @@ -727,7 +806,8 @@ var app = angular.module('webapp'); opacity: 0.25, attribution: "Hillshade layer by GIScience http://www.osm-wms.de", crs: L.CRS.EPSG900913 - } + }, + group: "Raster" }; }, existsHillshadeLayer: function() { @@ -1528,6 +1608,12 @@ var app = angular.module('webapp'); }]); app.controller("LayersEsriFeatureLayerController", [ "$scope", function($scope) { angular.extend($scope, { + layercontrol: { + icons: { + uncheck: "fa fa-toggle-off", + check: "fa fa-toggle-on" + } + }, porland: { lat: 45.526, lng: -122.667, @@ -1547,7 +1633,8 @@ var app = angular.module('webapp'); name: "Simple", type: "agsFeature", url: "https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/Heritage_Trees_Portland/FeatureServer/0", - visible: true + visible: true, + group: "Test" }, points: { name: "Styling Points", @@ -1564,7 +1651,8 @@ var app = angular.module('webapp'); return L.marker(latlng); } } - } + }, + group: "Test" }, lines: { name: "Styling Lines", @@ -1612,7 +1700,8 @@ var app = angular.module('webapp'); } return {color: c, opacity: o, weight: 5}; } - } + }, + group: "Test" }, polygons: { name: "Styling Polygons", @@ -1631,6 +1720,36 @@ var app = angular.module('webapp'); return { color: "white", weight: 2 }; } } + }, + group: "Test" + }, + group: { + name: "Grouped", + type: "group", + layerOptions: { + layers: [{ + name: "Simple", + type: "agsFeature", + url: "https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/Heritage_Trees_Portland/FeatureServer/0", + visible: true, + group: "Test" + }, { + name: "Styling Points", + type: "agsFeature", + url: "https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/Trimet_Transit_Stops/FeatureServer/0", + visible: false, + layerOptions: { + pointToLayer: function (geojson, latlng) { + if(geojson.properties.direction) { + return L.marker(latlng, { + icon: $scope.busIcons[geojson.properties.direction.toLowerCase()] + }); + } else { + return L.marker(latlng); + } + } + } + }] } } } @@ -1769,7 +1888,7 @@ var app = angular.module('webapp'); overlays: { usa_pop: { name: "USA 2000-2010 Population Change", - type: "dynamic", + type: "agsDynamic", url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer", visible: true, layerOptions: { @@ -1779,7 +1898,7 @@ var app = angular.module('webapp'); }, usa_social: { name: "USA Social Vulnerability Index", - type: "dynamic", + type: "agsDynamic", url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer", visible: false, layerOptions: { @@ -2028,6 +2147,59 @@ var app = angular.module('webapp'); $scope.country = leafletEvent.data.name; }); }]); + app.controller("LayersOverlayGeoJSONController", [ "$scope", '$http', function($scope, $http) { + angular.extend($scope, { + world: { + lat: 0, + lng: 0, + zoom: 3 + }, + layers: { + baselayers: { + osm: { + name: 'OpenStreetMap', + url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + type: 'xyz' + }, + }, + overlays:{} + } + }); + $http.get("json/countries.geo.json").success(function(data, status) { + angular.extend($scope.layers.overlays, { + countries: { + name:'World Country Boundaries', + type: 'geoJSONShape', + data: data, + visible: true, + layerOptions: { + style: { + color: '#00D', + fillColor: 'red', + weight: 2.0, + opacity: 0.6, + fillOpacity: 0.2 + } + } + } + }); + }); + $http.get("json/major_cities.json").success(function(data, status) { + angular.extend($scope.layers.overlays, { + cities: { + name:'Major Cities (Awesome Markers)', + type: 'geoJSONAwesomeMarker', + data: data, + visible: true, + icon: { + icon: 'heart', + markerColor: 'red', + prefix: 'fa' + } + } + }); + }); + }]); app.controller("LayersOverlaysHideOnZoomOutController", [ "$scope", function($scope) { angular.extend($scope, { center: { @@ -2693,6 +2865,144 @@ var app = angular.module('webapp'); } }); }]); + app.controller("LegendEsriLegendServiceController", [ "$scope", function($scope) { + angular.extend($scope, { + options: { + controls: { + layers: { + visible: false + } + } + }, + usa: { + lat: 39.931486, + lng: -101.406250, + zoom: 3 + }, + markers: { + m1: { + lat: 39.931486, + lng: -101.406250, + } + }, + layers: { + baselayers: { + mapbox_light: { + name: 'Mapbox Light', + url: 'http://api.tiles.mapbox.com/v4/{mapid}/{z}/{x}/{y}.png?access_token={apikey}', + type: 'xyz', + layerOptions: { + apikey: 'pk.eyJ1IjoiYnVmYW51dm9scyIsImEiOiJLSURpX0pnIn0.2_9NrLz1U9bpwMQBhVk97Q', + mapid: 'bufanuvols.lia22g09' + } + } + }, + overlays: { + usa_pop: { + name: "USA 2000-2010 Population Change", + type: "agsDynamic", + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer", + visible: true, + layerOptions: { + opacity: 0.85, + attribution: "Copyright:© 2014 Esri, DeLorme, HERE, TomTom" + } + }, + usa_social: { + name: "USA Social Vulnerability Index", + type: "agsDynamic", + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer", + visible: false, + layerOptions: { + opacity: 0.85, + attribution: "Copyright:© 2014 Esri, FAO, NOAA" + } + }, + }, + }, + legend: { + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer/legend?f=json", + legendClass: "info legend-esri", + position: "bottomleft", + }, + legendURL1: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer/legend?f=json", + legendURL2: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer/legend?f=json", + switchLegend: function() { + $scope.layers.overlays.usa_social.visible = !$scope.layers.overlays.usa_social.visible; + $scope.legend.url = + $scope.legend.url == $scope.legendURL1? $scope.legendURL2:$scope.legendURL1; + } + }); + }]); + app.controller("LegendEsriMultilayerLegendServiceController", [ "$scope", function($scope) { + angular.extend($scope, { + options: { + controls: { + layers: { + visible: false + } + } + }, + usa: { + lat: 39.931486, + lng: -101.406250, + zoom: 3 + }, + markers: { + m1: { + lat: 39.931486, + lng: -101.406250, + } + }, + layers: { + baselayers: { + mapbox_light: { + name: 'Mapbox Light', + url: 'http://api.tiles.mapbox.com/v4/{mapid}/{z}/{x}/{y}.png?access_token={apikey}', + type: 'xyz', + layerOptions: { + apikey: 'pk.eyJ1IjoiYnVmYW51dm9scyIsImEiOiJLSURpX0pnIn0.2_9NrLz1U9bpwMQBhVk97Q', + mapid: 'bufanuvols.lia22g09' + } + } + }, + overlays: { + usa_pop: { + name: "USA 2000-2010 Population Change", + type: "agsDynamic", + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer", + visible: true, + layerOptions: { + opacity: 0.85, + attribution: "Copyright:© 2014 Esri, DeLorme, HERE, TomTom" + } + }, + usa_social: { + name: "USA Social Vulnerability Index", + type: "agsDynamic", + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer", + visible: false, + layerOptions: { + opacity: 0.85, + attribution: "Copyright:© 2014 Esri, FAO, NOAA" + } + }, + }, + }, + legend: { + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer/legend?f=json", + legendClass: "info legend-esri", + position: "bottomleft", + }, + legendURL1: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer/legend?f=json", + legendURL2: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer/legend?f=json", + switchLegend: function() { + $scope.layers.overlays.usa_social.visible = !$scope.layers.overlays.usa_social.visible; + $scope.legend.url = + $scope.legend.url == $scope.legendURL1? $scope.legendURL2:$scope.legendURL1; + } + }); + }]); app.controller('MarkersAddRemoveController', [ '$scope', function($scope) { angular.extend($scope, { london: { @@ -3033,7 +3343,7 @@ var app = angular.module('webapp'); }); }); } ]); - app.controller("MarkersEventsController", [ "$scope", "leafletEvents", function($scope, leafletEvents) { + app.controller("MarkersEventsController", [ "$scope", "leafletMarkerEvents", "$log", function($scope, leafletMarkerEvents, $log) { $scope.center = { lat: 51.505, lng: -0.09, @@ -3050,23 +3360,52 @@ var app = angular.module('webapp'); } $scope.events = { markers: { - enable: leafletEvents.getAvailableMarkerEvents(), + enable: leafletMarkerEvents.getAvailableEvents(), } }; $scope.eventDetected = "No events yet..."; - var markerEvents = leafletEvents.getAvailableMarkerEvents(); + var markerEvents = leafletMarkerEvents.getAvailableEvents(); for (var k in markerEvents){ - var eventName = 'leafletDirectiveMarker.' + markerEvents[k]; + var eventName = 'leafletDirectiveMarker.myMap.' + markerEvents[k]; $scope.$on(eventName, function(event, args){ $scope.eventDetected = event.name; }); } }]); - app.controller('MarkersGroupController', [ '$scope', function($scope) { - var icons = { - blue: { - type: 'div', - iconSize: [10, 10], + app.controller("MarkersEventsWithIDController", [ "$scope", "leafletMarkerEvents", function($scope, leafletMarkerEvents) { + $scope.center = { + lat: 51.505, + lng: -0.09, + zoom: 8 + }; + $scope.markers = { + london: { + lat: 51.505, + lng: -0.09, + draggable: true, + message: "I'm a draggable marker", + focus: true + } + } + $scope.events = { + markers: { + enable: leafletMarkerEvents.getAvailableEvents(), + } + }; + $scope.eventDetected = "No events yet..."; + var markerEvents = leafletMarkerEvents.getAvailableEvents(); + for (var k in markerEvents){ + var eventName = 'leafletDirectiveMarker.' + markerEvents[k]; + $scope.$on(eventName, function(event, args){ + $scope.eventDetected = event.name; + }); + } + }]); + app.controller('MarkersGroupController', [ '$scope', function($scope) { + var icons = { + blue: { + type: 'div', + iconSize: [10, 10], className: 'blue', iconAnchor: [5, 5] }, @@ -3182,6 +3521,11 @@ var app = angular.module('webapp'); icon: 'tag', markerColor: 'red' }, + vectorMarkerIcon: { + type: 'vectorMarker', + icon: 'tag', + markerColor: 'red' + }, makiMarkerIcon: { type: 'makiMarker', icon: 'beer', @@ -3579,68 +3923,164 @@ var app = angular.module('webapp'); }); }); }]); - app.controller("MixedLayersOverlaysGeoJSONController", ["$scope", function($scope){ - angular.extend($scope, { - sanfrancisco: { - lat: 37.79, - lng: -122.4, - zoom: 17 - }, - defaults: { - scrollWheelZoom: false - }, - layers:{ - baselayers: { - osm:{ - name: "OpenStreetMap (XYZ)", - type: "xyz", - url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - layerOptions: { - subdomains: ['a', 'b', 'c'], - attribution: '© OpenStreetMap contributors', - continuousWorld: true - } - } - } - , - overlays: { - buildings: { - name:'Buildings', - type: 'geoJSON', - url:'http://tile.openstreetmap.us/vectiles-buildings/{z}/{x}/{y}.json', - layerOptions: { - style: { - "color": "#00D", - "fillColor": "#00D", - "weight": 1.0, - "opacity": 0.6, - "fillOpacity": .2 - } - }, - pluginOptions:{ - cliptiles: true - } - }, - Roads:{ - name:'Roads', - type: 'geoJSON', - url: 'http://tile.openstreetmap.us/vectiles-skeletron/{z}/{x}/{y}.json', - layerOptions: { - style: { - "color": "#DD0000 ", - "fillColor": "#DD0000", - "weight": 1.0, - "fillOpacity": .4 - } - }, - pluginOptions:{ - cliptiles: false - } - } - } - } - }) - }]); + app.controller('MixedGeoJSONEventsWithIDController', [ "$scope", "$http", function($scope, $http) { + $scope.$on("leafletDirectiveGeoJson.myMap.mouseover", function(ev, leafletPayload) { + countryMouseover(leafletPayload.leafletObject.feature, leafletPayload.leafletEvent); + }); + $scope.$on("leafletDirectiveGeoJson.myMap.click", function(ev, leafletPayload) { + countryClick(leafletPayload.leafletObject, leafletPayload.leafletEvent); + }); + var continentProperties= { + "009": { + name: 'Oceania', + colors: [ '#CC0066', '#993366', '#990066', '#CC3399', '#CC6699' ] + }, + "019": { + name: 'America', + colors: [ '#006699', '#336666', '#003366', '#3399CC', '#6699CC' ] + }, + "150": { + name: 'Europe', + colors: [ '#FF0000', '#CC3333', '#990000', '#FF3333', '#FF6666' ] + }, + "002": { + name: 'Africa', + colors: [ '#00CC00', '#339933', '#009900', '#33FF33', '#66FF66' ] + }, + "142": { + name: 'Asia', + colors: [ '#FFCC00', '#CC9933', '#999900', '#FFCC33', '#FFCC66' ] + }, + }; + angular.extend($scope, { + center: { + lat: 40.8471, + lng: 14.0625, + zoom: 2 + }, + legend: { + colors: [ '#CC0066', '#006699', '#FF0000', '#00CC00', '#FFCC00' ], + labels: [ 'Oceania', 'America', 'Europe', 'Africa', 'Asia' ] + } + }); + function countryClick(country, event) { + country = country.feature; + console.log(country.properties.name); + } + // Get a country paint color from the continents array of colors + function getColor(country) { + if (!country || !country["region-code"]) { + return "#FFF"; + } + var colors = continentProperties[country["region-code"]].colors; + var index = country["alpha-3"].charCodeAt(0) % colors.length ; + return colors[index]; + } + function style(feature) { + return { + fillColor: getColor($scope.countries[feature.id]), + weight: 2, + opacity: 1, + color: 'white', + dashArray: '3', + fillOpacity: 0.7 + }; + } + // Mouse over function, called from the Leaflet Map Events + function countryMouseover(feature, leafletEvent) { + var layer = leafletEvent.target; + layer.setStyle({ + weight: 2, + color: '#666', + fillColor: 'white' + }); + layer.bringToFront(); + $scope.selectedCountry = feature; + console.log(feature); + } + // Get the countries data from a JSON + $http.get("json/all.json").success(function(data, status) { + // Put the countries on an associative array + $scope.countries = {}; + for (var i=0; i< data.length; i++) { + var country = data[i]; + $scope.countries[country['alpha-3']] = country; + } + // Get the countries geojson data from a JSON + $http.get("json/countries.geo.json").success(function(data, status) { + angular.extend($scope, { + geojson: { + data: data, + style: style, + resetStyleOnMouseout: true + }, + selectedCountry: {} + }); + }); + }); + }]); + app.controller("MixedLayersOverlaysGeoJSONController", ["$scope", function($scope){ + angular.extend($scope, { + sanfrancisco: { + lat: 37.79, + lng: -122.4, + zoom: 17 + }, + defaults: { + scrollWheelZoom: false + }, + layers:{ + baselayers: { + osm:{ + name: "OpenStreetMap (XYZ)", + type: "xyz", + url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + layerOptions: { + subdomains: ['a', 'b', 'c'], + attribution: '© OpenStreetMap contributors', + continuousWorld: true + } + } + } + , + overlays: { + buildings: { + name:'Buildings', + type: 'geoJSON', + url:'http://tile.openstreetmap.us/vectiles-buildings/{z}/{x}/{y}.json', + layerOptions: { + style: { + "color": "#00D", + "fillColor": "#00D", + "weight": 1.0, + "opacity": 0.6, + "fillOpacity": .2 + } + }, + pluginOptions:{ + cliptiles: true + } + }, + Roads:{ + name:'Roads', + type: 'geoJSON', + url: 'http://tile.openstreetmap.us/vectiles-skeletron/{z}/{x}/{y}.json', + layerOptions: { + style: { + "color": "#DD0000 ", + "fillColor": "#DD0000", + "weight": 1.0, + "fillOpacity": .4 + } + }, + pluginOptions:{ + cliptiles: false + } + } + } + } + }) + }]); app.controller('MixedMOverlaysMarkersNestedNoWatchController', function ($scope, leafletData, $timeout) { var _clonedMarkers; $timeout(function () { @@ -3802,66 +4242,123 @@ var app = angular.module('webapp'); console.log(data); }); }]); - app.controller("MixedMarkersNestedEventsController", ["$scope", "leafletEvents", function ($scope, leafletEvents) { - $scope.map = { - show: true - }; - $scope.layers = { - baselayers: { - osm: { - name: 'OpenStreetMap', - type: 'xyz', - url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - layerOptions: { - subdomains: ['a', 'b', 'c'], - attribution: '© OpenStreetMap contributors', - continuousWorld: true - } - } - }, - overlays: { - london: { - name: 'London', - type: 'group', - visible: true + app.controller("MixedMarkersNestedEventsController", ["$scope", "leafletEvents", function ($scope, leafletEvents) { + $scope.map = { + show: true + }; + $scope.layers = { + baselayers: { + osm: { + name: 'OpenStreetMap', + type: 'xyz', + url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + layerOptions: { + subdomains: ['a', 'b', 'c'], + attribution: '© OpenStreetMap contributors', + continuousWorld: true } } - }; - $scope.center = { - lat: 51.505, - lng: -0.09, - zoom: 8 - }; - $scope.markers = { + }, + overlays: { london: { - 1: { - lat: 51.505, - lng: -0.09, - draggable: true, - focus: true - } + name: 'London', + type: 'group', + visible: true } - }; - $scope.events = { - markers: { - enable: leafletEvents.getAvailableMarkerEvents() + } + }; + $scope.center = { + lat: 51.505, + lng: -0.09, + zoom: 8 + }; + $scope.markers = { + london: { + 1: { + lat: 51.505, + lng: -0.09, + draggable: true, + focus: true } - }; - $scope.eventDetected = "No events yet..."; - var markerEvents = leafletEvents.getAvailableMarkerEvents(); - for (var k in markerEvents) { - var eventName = 'leafletDirectiveMarker.' + markerEvents[k]; - $scope.$on(eventName, function (event, args) { - $scope.eventDetected = event.name; - $scope.args = { - layerName: args.layerName, - model: args.model, - modelName: args.modelName - }; - }); } - }]); - app.controller("PathEventsController", [ "$scope", function($scope) { + }; + $scope.events = { + markers: { + enable: leafletEvents.getAvailableMarkerEvents() + } + }; + $scope.eventDetected = "No events yet..."; + var markerEvents = leafletEvents.getAvailableMarkerEvents(); + for (var k in markerEvents) { + var eventName = 'leafletDirectiveMarker.' + markerEvents[k]; + $scope.$on(eventName, function (event, args) { + $scope.eventDetected = event.name; + $scope.args = { + layerName: args.layerName, + model: args.model, + modelName: args.modelName + }; + }); + } + }]); + app.controller("PathEventsController", function($scope, $log) { + var paths = {}; + $scope.clicked = 0; + var marylandIslands = { + 'Fort Carroll': { + lat: 39.214766, + lng: -76.519003 + }, + 'Gibson Island': { + lat: 39.077642, + lng: -76.433344 + }, + 'Solomons Island': { + lat: 38.320145, + lng: -76.457334 + } + }; + angular.forEach(marylandIslands, function (v, k) { + paths[k] = { + type: "circleMarker", + latlngs: v, + stroke: false, + fillColor: "#00FFFF", + fillOpacity: 0.7, + radius: 10, + clickable: true + }; + }); + angular.extend($scope, { + center: { + lat:38.976492, + lng:-76.49231, + zoom: 8 + }, + layers: { + baselayers: { + xyz: { + name: 'OpenStreetMap (XYZ)', + url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + type: 'xyz' + } + } + }, + events: { + path: { + enable: [ 'click', 'mouseover' ] + } + }, + paths: paths + }); + $scope.$on('leafletDirectivePath.myMap.click', function (event) { + $scope.clicked++; + }); + $scope.$on('leafletDirectivePath.myMap.mouseover', function (event, path) { + $scope.mouseover = path.modelName; + }); + }); + app.controller("PathEventsWithIDController", function($scope, $log) { var paths = {}; $scope.clicked = 0; var marylandIslands = { @@ -3917,7 +4414,7 @@ var app = angular.module('webapp'); $scope.$on('leafletDirectivePath.mouseover', function (event, path) { $scope.mouseover = path.modelName; }); - }]); + }); app.controller("PathSimpleController", [ "$scope", function($scope) { angular.extend($scope, { london: { diff --git a/examples/js/controllers/BasicCenterGeoIPController.js b/examples/js/controllers/BasicCenterGeoIPController.js index 0083edd2..5c488fa5 100644 --- a/examples/js/controllers/BasicCenterGeoIPController.js +++ b/examples/js/controllers/BasicCenterGeoIPController.js @@ -13,9 +13,9 @@ lat: res.latitude, lng: res.longitude, zoom: 10 - } + }; $scope.ip = res.ip; - }) + }); }; $scope.searchIP(""); }]); \ No newline at end of file diff --git a/examples/js/controllers/BasicCenterUrlHashController.js b/examples/js/controllers/BasicCenterUrlHashController.js index 5f7961f7..b8a44240 100644 --- a/examples/js/controllers/BasicCenterUrlHashController.js +++ b/examples/js/controllers/BasicCenterUrlHashController.js @@ -12,5 +12,5 @@ }); $scope.changeLocation = function(centerHash) { $location.search({ c: centerHash }); - } + }; }]); \ No newline at end of file diff --git a/examples/js/controllers/BasicEventsController.js b/examples/js/controllers/BasicEventsController.js index 01503ccc..ad5da651 100644 --- a/examples/js/controllers/BasicEventsController.js +++ b/examples/js/controllers/BasicEventsController.js @@ -1,11 +1,11 @@ - app.controller("BasicEventsController", [ "$scope", "leafletEvents", function($scope, leafletEvents) { + app.controller("BasicEventsController", [ "$scope", "leafletMapEvents", function($scope, leafletMapEvents) { $scope.center = { lat: 51.505, lng: -0.09, zoom: 8 }; $scope.eventDetected = "No events yet..."; - var mapEvents = leafletEvents.getAvailableMapEvents(); + var mapEvents = leafletMapEvents.getAvailableMapEvents(); for (var k in mapEvents){ var eventName = 'leafletDirectiveMap.' + mapEvents[k]; $scope.$on(eventName, function(event){ diff --git a/examples/js/controllers/BasicGeoJSONUpdateController.js b/examples/js/controllers/BasicGeoJSONUpdateController.js index 18cd9e76..ccfed4ee 100644 --- a/examples/js/controllers/BasicGeoJSONUpdateController.js +++ b/examples/js/controllers/BasicGeoJSONUpdateController.js @@ -88,6 +88,6 @@ } } ] - } + }; } }]); \ No newline at end of file diff --git a/examples/js/controllers/BasicLFCenterController.js b/examples/js/controllers/BasicLFCenterController.js new file mode 100644 index 00000000..a4414253 --- /dev/null +++ b/examples/js/controllers/BasicLFCenterController.js @@ -0,0 +1,9 @@ + app.controller('BasicLFCenterController', [ '$scope', function($scope) { + angular.extend($scope, { + london: { + lat: 51.505, + lng: -0.09, + zoom: 4 + } + }); + }]); \ No newline at end of file diff --git a/examples/js/controllers/BasicTilesWMSController.js b/examples/js/controllers/BasicTilesWMSController.js new file mode 100644 index 00000000..4d8f389f --- /dev/null +++ b/examples/js/controllers/BasicTilesWMSController.js @@ -0,0 +1,47 @@ + app.controller('BasicTilesWMSController', [ '$scope', function($scope) { + var tilesDict = { + openstreetmap: { + url: "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", + options: { + attribution: '© OpenStreetMap contributors' + } + }, + standard: { + name: 'MAP Standard', + type: 'wms', + url: 'https://api.minu.mn/wms', + layerParams: { + layers: 'mongolid:mimap', + format: 'image/png', + transparent: true, + tiled: true, + version: '1.3.0', + maxZoom: 19 + } + }, + blue: { + name: 'MAP Blue', + type: 'wms', + url: 'https://api.minu.mn/wms', + layerParams: { + layers: 'mongolid:mimap_blue', // it's published not yet. + format: 'image/png', + transparent: true, + tiled: true, + version: '1.3.0', + maxZoom: 19 + } + } + }; + angular.extend($scope, { + ulaanbaatar: { + lat: 47.918464, + lng: 106.917678, + zoom: 5 + }, + tiles: tilesDict.openstreetmap + }); + $scope.changeTiles = function(tiles) { + $scope.tiles = tilesDict[tiles]; + }; + } ]); \ No newline at end of file diff --git a/examples/js/controllers/ControlsCustomController.js b/examples/js/controllers/ControlsCustomController.js new file mode 100644 index 00000000..9f19f5db --- /dev/null +++ b/examples/js/controllers/ControlsCustomController.js @@ -0,0 +1,21 @@ + app.controller("ControlsCustomController", [ "$scope", function($scope) { + angular.extend($scope, { + london: { + lat: 37.8, + lng: -96, + zoom: 5 + }, + tiles: { + name: 'Mapbox Comic', + url: 'http://api.tiles.mapbox.com/v4/{mapid}/{z}/{x}/{y}.png?access_token={apikey}', + type: 'xyz', + options: { + apikey: 'pk.eyJ1IjoiYnVmYW51dm9scyIsImEiOiJLSURpX0pnIn0.2_9NrLz1U9bpwMQBhVk97Q', + mapid: 'bufanuvols.lpa06kfg' + } + }, + controls: { + custom: new L.Control.Fullscreen() + } + }); + }]); \ No newline at end of file diff --git a/examples/js/controllers/ControlsCustomLayerControlController.js b/examples/js/controllers/ControlsCustomLayerControlController.js index 9fe8b1f1..3a9d2d63 100644 --- a/examples/js/controllers/ControlsCustomLayerControlController.js +++ b/examples/js/controllers/ControlsCustomLayerControlController.js @@ -88,7 +88,8 @@ layerOptions: { attribution: "© OpenFireMap contributors - © OpenStreetMap contributors", continuousWorld: true - } + }, + group: "Open Fire Map" }; }, existsFireLayer: function() { @@ -105,7 +106,8 @@ layerOptions: { attribution: "© OpenFireMap contributors - © OpenStreetMap contributors", continuousWorld: true - } + }, + group: "Open Fire Map" }; }, existsEmergencyRooms: function() { @@ -126,7 +128,8 @@ opacity: 0.25, attribution: "Hillshade layer by GIScience http://www.osm-wms.de", crs: L.CRS.EPSG900913 - } + }, + group: "Raster" }; }, existsHillshadeLayer: function() { diff --git a/examples/js/controllers/LayersEsriFeatureLayerController.js b/examples/js/controllers/LayersEsriFeatureLayerController.js index dd681226..ae3c3dbd 100644 --- a/examples/js/controllers/LayersEsriFeatureLayerController.js +++ b/examples/js/controllers/LayersEsriFeatureLayerController.js @@ -1,5 +1,11 @@ app.controller("LayersEsriFeatureLayerController", [ "$scope", function($scope) { angular.extend($scope, { + layercontrol: { + icons: { + uncheck: "fa fa-toggle-off", + check: "fa fa-toggle-on" + } + }, porland: { lat: 45.526, lng: -122.667, @@ -19,7 +25,8 @@ name: "Simple", type: "agsFeature", url: "https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/Heritage_Trees_Portland/FeatureServer/0", - visible: true + visible: true, + group: "Test" }, points: { name: "Styling Points", @@ -36,7 +43,8 @@ return L.marker(latlng); } } - } + }, + group: "Test" }, lines: { name: "Styling Lines", @@ -84,7 +92,8 @@ } return {color: c, opacity: o, weight: 5}; } - } + }, + group: "Test" }, polygons: { name: "Styling Polygons", @@ -103,6 +112,36 @@ return { color: "white", weight: 2 }; } } + }, + group: "Test" + }, + group: { + name: "Grouped", + type: "group", + layerOptions: { + layers: [{ + name: "Simple", + type: "agsFeature", + url: "https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/Heritage_Trees_Portland/FeatureServer/0", + visible: true, + group: "Test" + }, { + name: "Styling Points", + type: "agsFeature", + url: "https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/Trimet_Transit_Stops/FeatureServer/0", + visible: false, + layerOptions: { + pointToLayer: function (geojson, latlng) { + if(geojson.properties.direction) { + return L.marker(latlng, { + icon: $scope.busIcons[geojson.properties.direction.toLowerCase()] + }); + } else { + return L.marker(latlng); + } + } + } + }] } } } diff --git a/examples/js/controllers/LayersEsriLegendServiceController.js b/examples/js/controllers/LayersEsriLegendServiceController.js index a7c96593..3424b9a7 100644 --- a/examples/js/controllers/LayersEsriLegendServiceController.js +++ b/examples/js/controllers/LayersEsriLegendServiceController.js @@ -33,7 +33,7 @@ overlays: { usa_pop: { name: "USA 2000-2010 Population Change", - type: "dynamic", + type: "agsDynamic", url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer", visible: true, layerOptions: { @@ -43,7 +43,7 @@ }, usa_social: { name: "USA Social Vulnerability Index", - type: "dynamic", + type: "agsDynamic", url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer", visible: false, layerOptions: { diff --git a/examples/js/controllers/LayersOverlayGeoJSONController.js b/examples/js/controllers/LayersOverlayGeoJSONController.js new file mode 100644 index 00000000..0a838b17 --- /dev/null +++ b/examples/js/controllers/LayersOverlayGeoJSONController.js @@ -0,0 +1,53 @@ + app.controller("LayersOverlayGeoJSONController", [ "$scope", '$http', function($scope, $http) { + angular.extend($scope, { + world: { + lat: 0, + lng: 0, + zoom: 3 + }, + layers: { + baselayers: { + osm: { + name: 'OpenStreetMap', + url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + type: 'xyz' + }, + }, + overlays:{} + } + }); + $http.get("json/countries.geo.json").success(function(data, status) { + angular.extend($scope.layers.overlays, { + countries: { + name:'World Country Boundaries', + type: 'geoJSONShape', + data: data, + visible: true, + layerOptions: { + style: { + color: '#00D', + fillColor: 'red', + weight: 2.0, + opacity: 0.6, + fillOpacity: 0.2 + } + } + } + }); + }); + $http.get("json/major_cities.json").success(function(data, status) { + angular.extend($scope.layers.overlays, { + cities: { + name:'Major Cities (Awesome Markers)', + type: 'geoJSONAwesomeMarker', + data: data, + visible: true, + icon: { + icon: 'heart', + markerColor: 'red', + prefix: 'fa' + } + } + }); + }); + }]); \ No newline at end of file diff --git a/examples/js/controllers/LegendEsriLegendServiceController.js b/examples/js/controllers/LegendEsriLegendServiceController.js new file mode 100644 index 00000000..c455c240 --- /dev/null +++ b/examples/js/controllers/LegendEsriLegendServiceController.js @@ -0,0 +1,69 @@ + app.controller("LegendEsriLegendServiceController", [ "$scope", function($scope) { + angular.extend($scope, { + options: { + controls: { + layers: { + visible: false + } + } + }, + usa: { + lat: 39.931486, + lng: -101.406250, + zoom: 3 + }, + markers: { + m1: { + lat: 39.931486, + lng: -101.406250, + } + }, + layers: { + baselayers: { + mapbox_light: { + name: 'Mapbox Light', + url: 'http://api.tiles.mapbox.com/v4/{mapid}/{z}/{x}/{y}.png?access_token={apikey}', + type: 'xyz', + layerOptions: { + apikey: 'pk.eyJ1IjoiYnVmYW51dm9scyIsImEiOiJLSURpX0pnIn0.2_9NrLz1U9bpwMQBhVk97Q', + mapid: 'bufanuvols.lia22g09' + } + } + }, + overlays: { + usa_pop: { + name: "USA 2000-2010 Population Change", + type: "agsDynamic", + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer", + visible: true, + layerOptions: { + opacity: 0.85, + attribution: "Copyright:© 2014 Esri, DeLorme, HERE, TomTom" + } + }, + usa_social: { + name: "USA Social Vulnerability Index", + type: "agsDynamic", + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer", + visible: false, + layerOptions: { + opacity: 0.85, + attribution: "Copyright:© 2014 Esri, FAO, NOAA" + } + }, + }, + }, + legend: { + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer/legend?f=json", + legendClass: "info legend-esri", + position: "bottomleft", + }, + legendURL1: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer/legend?f=json", + legendURL2: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer/legend?f=json", + switchLegend: function() { + $scope.layers.overlays.usa_social.visible = !$scope.layers.overlays.usa_social.visible; + $scope.legend.url = + $scope.legend.url == $scope.legendURL1? $scope.legendURL2:$scope.legendURL1; + } + }); + }]); \ No newline at end of file diff --git a/examples/js/controllers/LegendEsriMultilayerLegendServiceController.js b/examples/js/controllers/LegendEsriMultilayerLegendServiceController.js new file mode 100644 index 00000000..c4303e1d --- /dev/null +++ b/examples/js/controllers/LegendEsriMultilayerLegendServiceController.js @@ -0,0 +1,69 @@ + app.controller("LegendEsriMultilayerLegendServiceController", [ "$scope", function($scope) { + angular.extend($scope, { + options: { + controls: { + layers: { + visible: false + } + } + }, + usa: { + lat: 39.931486, + lng: -101.406250, + zoom: 3 + }, + markers: { + m1: { + lat: 39.931486, + lng: -101.406250, + } + }, + layers: { + baselayers: { + mapbox_light: { + name: 'Mapbox Light', + url: 'http://api.tiles.mapbox.com/v4/{mapid}/{z}/{x}/{y}.png?access_token={apikey}', + type: 'xyz', + layerOptions: { + apikey: 'pk.eyJ1IjoiYnVmYW51dm9scyIsImEiOiJLSURpX0pnIn0.2_9NrLz1U9bpwMQBhVk97Q', + mapid: 'bufanuvols.lia22g09' + } + } + }, + overlays: { + usa_pop: { + name: "USA 2000-2010 Population Change", + type: "agsDynamic", + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer", + visible: true, + layerOptions: { + opacity: 0.85, + attribution: "Copyright:© 2014 Esri, DeLorme, HERE, TomTom" + } + }, + usa_social: { + name: "USA Social Vulnerability Index", + type: "agsDynamic", + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer", + visible: false, + layerOptions: { + opacity: 0.85, + attribution: "Copyright:© 2014 Esri, FAO, NOAA" + } + }, + }, + }, + legend: { + url: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer/legend?f=json", + legendClass: "info legend-esri", + position: "bottomleft", + }, + legendURL1: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_1990-2000_Population_Change/MapServer/legend?f=json", + legendURL2: "http://services.arcgisonline.com/arcgis/rest/services/Demographics/USA_Social_Vulnerability_Index/MapServer/legend?f=json", + switchLegend: function() { + $scope.layers.overlays.usa_social.visible = !$scope.layers.overlays.usa_social.visible; + $scope.legend.url = + $scope.legend.url == $scope.legendURL1? $scope.legendURL2:$scope.legendURL1; + } + }); + }]); \ No newline at end of file diff --git a/examples/js/controllers/MarkersEventsController.js b/examples/js/controllers/MarkersEventsController.js index 61229e2a..a51f6620 100644 --- a/examples/js/controllers/MarkersEventsController.js +++ b/examples/js/controllers/MarkersEventsController.js @@ -1,4 +1,4 @@ - app.controller("MarkersEventsController", [ "$scope", "leafletEvents", function($scope, leafletEvents) { + app.controller("MarkersEventsController", [ "$scope", "leafletMarkerEvents", "$log", function($scope, leafletMarkerEvents, $log) { $scope.center = { lat: 51.505, lng: -0.09, @@ -15,13 +15,13 @@ } $scope.events = { markers: { - enable: leafletEvents.getAvailableMarkerEvents(), + enable: leafletMarkerEvents.getAvailableEvents(), } }; $scope.eventDetected = "No events yet..."; - var markerEvents = leafletEvents.getAvailableMarkerEvents(); + var markerEvents = leafletMarkerEvents.getAvailableEvents(); for (var k in markerEvents){ - var eventName = 'leafletDirectiveMarker.' + markerEvents[k]; + var eventName = 'leafletDirectiveMarker.myMap.' + markerEvents[k]; $scope.$on(eventName, function(event, args){ $scope.eventDetected = event.name; }); diff --git a/examples/js/controllers/MarkersEventsWithIDController.js b/examples/js/controllers/MarkersEventsWithIDController.js new file mode 100644 index 00000000..4e10464f --- /dev/null +++ b/examples/js/controllers/MarkersEventsWithIDController.js @@ -0,0 +1,29 @@ + app.controller("MarkersEventsWithIDController", [ "$scope", "leafletMarkerEvents", function($scope, leafletMarkerEvents) { + $scope.center = { + lat: 51.505, + lng: -0.09, + zoom: 8 + }; + $scope.markers = { + london: { + lat: 51.505, + lng: -0.09, + draggable: true, + message: "I'm a draggable marker", + focus: true + } + } + $scope.events = { + markers: { + enable: leafletMarkerEvents.getAvailableEvents(), + } + }; + $scope.eventDetected = "No events yet..."; + var markerEvents = leafletMarkerEvents.getAvailableEvents(); + for (var k in markerEvents){ + var eventName = 'leafletDirectiveMarker.' + markerEvents[k]; + $scope.$on(eventName, function(event, args){ + $scope.eventDetected = event.name; + }); + } + }]); \ No newline at end of file diff --git a/examples/js/controllers/MarkersIconsController.js b/examples/js/controllers/MarkersIconsController.js index 41ff75f1..51915c17 100644 --- a/examples/js/controllers/MarkersIconsController.js +++ b/examples/js/controllers/MarkersIconsController.js @@ -44,6 +44,11 @@ icon: 'tag', markerColor: 'red' }, + vectorMarkerIcon: { + type: 'vectorMarker', + icon: 'tag', + markerColor: 'red' + }, makiMarkerIcon: { type: 'makiMarker', icon: 'beer', diff --git a/examples/js/controllers/MixedGeoJSONEventsWithIDController.js b/examples/js/controllers/MixedGeoJSONEventsWithIDController.js new file mode 100644 index 00000000..2b5a81c2 --- /dev/null +++ b/examples/js/controllers/MixedGeoJSONEventsWithIDController.js @@ -0,0 +1,96 @@ + app.controller('MixedGeoJSONEventsWithIDController', [ "$scope", "$http", function($scope, $http) { + $scope.$on("leafletDirectiveGeoJson.myMap.mouseover", function(ev, leafletPayload) { + countryMouseover(leafletPayload.leafletObject.feature, leafletPayload.leafletEvent); + }); + $scope.$on("leafletDirectiveGeoJson.myMap.click", function(ev, leafletPayload) { + countryClick(leafletPayload.leafletObject, leafletPayload.leafletEvent); + }); + var continentProperties= { + "009": { + name: 'Oceania', + colors: [ '#CC0066', '#993366', '#990066', '#CC3399', '#CC6699' ] + }, + "019": { + name: 'America', + colors: [ '#006699', '#336666', '#003366', '#3399CC', '#6699CC' ] + }, + "150": { + name: 'Europe', + colors: [ '#FF0000', '#CC3333', '#990000', '#FF3333', '#FF6666' ] + }, + "002": { + name: 'Africa', + colors: [ '#00CC00', '#339933', '#009900', '#33FF33', '#66FF66' ] + }, + "142": { + name: 'Asia', + colors: [ '#FFCC00', '#CC9933', '#999900', '#FFCC33', '#FFCC66' ] + }, + }; + angular.extend($scope, { + center: { + lat: 40.8471, + lng: 14.0625, + zoom: 2 + }, + legend: { + colors: [ '#CC0066', '#006699', '#FF0000', '#00CC00', '#FFCC00' ], + labels: [ 'Oceania', 'America', 'Europe', 'Africa', 'Asia' ] + } + }); + function countryClick(country, event) { + country = country.feature; + console.log(country.properties.name); + } + // Get a country paint color from the continents array of colors + function getColor(country) { + if (!country || !country["region-code"]) { + return "#FFF"; + } + var colors = continentProperties[country["region-code"]].colors; + var index = country["alpha-3"].charCodeAt(0) % colors.length ; + return colors[index]; + } + function style(feature) { + return { + fillColor: getColor($scope.countries[feature.id]), + weight: 2, + opacity: 1, + color: 'white', + dashArray: '3', + fillOpacity: 0.7 + }; + } + // Mouse over function, called from the Leaflet Map Events + function countryMouseover(feature, leafletEvent) { + var layer = leafletEvent.target; + layer.setStyle({ + weight: 2, + color: '#666', + fillColor: 'white' + }); + layer.bringToFront(); + $scope.selectedCountry = feature; + console.log(feature); + } + // Get the countries data from a JSON + $http.get("json/all.json").success(function(data, status) { + // Put the countries on an associative array + $scope.countries = {}; + for (var i=0; i< data.length; i++) { + var country = data[i]; + $scope.countries[country['alpha-3']] = country; + } + // Get the countries geojson data from a JSON + $http.get("json/countries.geo.json").success(function(data, status) { + angular.extend($scope, { + geojson: { + data: data, + style: style, + resetStyleOnMouseout: true + }, + selectedCountry: {} + }); + }); + }); + }]); \ No newline at end of file diff --git a/examples/js/controllers/MixedLayersOverlaysGeoJSONController.js b/examples/js/controllers/MixedLayersOverlaysGeoJSONController.js index ebb6fbf5..4b2e9e3b 100644 --- a/examples/js/controllers/MixedLayersOverlaysGeoJSONController.js +++ b/examples/js/controllers/MixedLayersOverlaysGeoJSONController.js @@ -1,62 +1,62 @@ - app.controller("MixedLayersOverlaysGeoJSONController", ["$scope", function($scope){ - angular.extend($scope, { - sanfrancisco: { - lat: 37.79, - lng: -122.4, - zoom: 17 - }, - defaults: { - scrollWheelZoom: false - }, - layers:{ - baselayers: { - osm:{ - name: "OpenStreetMap (XYZ)", - type: "xyz", - url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - layerOptions: { - subdomains: ['a', 'b', 'c'], - attribution: '© OpenStreetMap contributors', - continuousWorld: true - } - } - } - , - overlays: { - buildings: { - name:'Buildings', - type: 'geoJSON', - url:'http://tile.openstreetmap.us/vectiles-buildings/{z}/{x}/{y}.json', - layerOptions: { - style: { - "color": "#00D", - "fillColor": "#00D", - "weight": 1.0, - "opacity": 0.6, - "fillOpacity": .2 - } - }, - pluginOptions:{ - cliptiles: true - } - }, - Roads:{ - name:'Roads', - type: 'geoJSON', - url: 'http://tile.openstreetmap.us/vectiles-skeletron/{z}/{x}/{y}.json', - layerOptions: { - style: { - "color": "#DD0000 ", - "fillColor": "#DD0000", - "weight": 1.0, - "fillOpacity": .4 - } - }, - pluginOptions:{ - cliptiles: false - } - } - } - } - }) - }]); \ No newline at end of file + app.controller("MixedLayersOverlaysGeoJSONController", ["$scope", function($scope){ + angular.extend($scope, { + sanfrancisco: { + lat: 37.79, + lng: -122.4, + zoom: 17 + }, + defaults: { + scrollWheelZoom: false + }, + layers:{ + baselayers: { + osm:{ + name: "OpenStreetMap (XYZ)", + type: "xyz", + url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + layerOptions: { + subdomains: ['a', 'b', 'c'], + attribution: '© OpenStreetMap contributors', + continuousWorld: true + } + } + } + , + overlays: { + buildings: { + name:'Buildings', + type: 'geoJSON', + url:'http://tile.openstreetmap.us/vectiles-buildings/{z}/{x}/{y}.json', + layerOptions: { + style: { + "color": "#00D", + "fillColor": "#00D", + "weight": 1.0, + "opacity": 0.6, + "fillOpacity": .2 + } + }, + pluginOptions:{ + cliptiles: true + } + }, + Roads:{ + name:'Roads', + type: 'geoJSON', + url: 'http://tile.openstreetmap.us/vectiles-skeletron/{z}/{x}/{y}.json', + layerOptions: { + style: { + "color": "#DD0000 ", + "fillColor": "#DD0000", + "weight": 1.0, + "fillOpacity": .4 + } + }, + pluginOptions:{ + cliptiles: false + } + } + } + } + }) + }]); \ No newline at end of file diff --git a/examples/js/controllers/MixedMarkersNestedEventsController.js b/examples/js/controllers/MixedMarkersNestedEventsController.js index 40cf9b70..f096a1ab 100644 --- a/examples/js/controllers/MixedMarkersNestedEventsController.js +++ b/examples/js/controllers/MixedMarkersNestedEventsController.js @@ -1,59 +1,59 @@ - app.controller("MixedMarkersNestedEventsController", ["$scope", "leafletEvents", function ($scope, leafletEvents) { - $scope.map = { - show: true - }; - $scope.layers = { - baselayers: { - osm: { - name: 'OpenStreetMap', - type: 'xyz', - url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - layerOptions: { - subdomains: ['a', 'b', 'c'], - attribution: '© OpenStreetMap contributors', - continuousWorld: true - } - } - }, - overlays: { - london: { - name: 'London', - type: 'group', - visible: true + app.controller("MixedMarkersNestedEventsController", ["$scope", "leafletEvents", function ($scope, leafletEvents) { + $scope.map = { + show: true + }; + $scope.layers = { + baselayers: { + osm: { + name: 'OpenStreetMap', + type: 'xyz', + url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + layerOptions: { + subdomains: ['a', 'b', 'c'], + attribution: '© OpenStreetMap contributors', + continuousWorld: true } } - }; - $scope.center = { - lat: 51.505, - lng: -0.09, - zoom: 8 - }; - $scope.markers = { + }, + overlays: { london: { - 1: { - lat: 51.505, - lng: -0.09, - draggable: true, - focus: true - } + name: 'London', + type: 'group', + visible: true } - }; - $scope.events = { - markers: { - enable: leafletEvents.getAvailableMarkerEvents() + } + }; + $scope.center = { + lat: 51.505, + lng: -0.09, + zoom: 8 + }; + $scope.markers = { + london: { + 1: { + lat: 51.505, + lng: -0.09, + draggable: true, + focus: true } - }; - $scope.eventDetected = "No events yet..."; - var markerEvents = leafletEvents.getAvailableMarkerEvents(); - for (var k in markerEvents) { - var eventName = 'leafletDirectiveMarker.' + markerEvents[k]; - $scope.$on(eventName, function (event, args) { - $scope.eventDetected = event.name; - $scope.args = { - layerName: args.layerName, - model: args.model, - modelName: args.modelName - }; - }); } - }]); \ No newline at end of file + }; + $scope.events = { + markers: { + enable: leafletEvents.getAvailableMarkerEvents() + } + }; + $scope.eventDetected = "No events yet..."; + var markerEvents = leafletEvents.getAvailableMarkerEvents(); + for (var k in markerEvents) { + var eventName = 'leafletDirectiveMarker.' + markerEvents[k]; + $scope.$on(eventName, function (event, args) { + $scope.eventDetected = event.name; + $scope.args = { + layerName: args.layerName, + model: args.model, + modelName: args.modelName + }; + }); + } + }]); \ No newline at end of file diff --git a/examples/js/controllers/PathEventsController.js b/examples/js/controllers/PathEventsController.js index 415af07f..3529afad 100644 --- a/examples/js/controllers/PathEventsController.js +++ b/examples/js/controllers/PathEventsController.js @@ -1,4 +1,4 @@ - app.controller("PathEventsController", [ "$scope", function($scope) { + app.controller("PathEventsController", function($scope, $log) { var paths = {}; $scope.clicked = 0; var marylandIslands = { @@ -48,10 +48,10 @@ }, paths: paths }); - $scope.$on('leafletDirectivePath.click', function (event) { + $scope.$on('leafletDirectivePath.myMap.click', function (event) { $scope.clicked++; }); - $scope.$on('leafletDirectivePath.mouseover', function (event, path) { + $scope.$on('leafletDirectivePath.myMap.mouseover', function (event, path) { $scope.mouseover = path.modelName; }); - }]); \ No newline at end of file + }); \ No newline at end of file diff --git a/examples/js/controllers/PathEventsWithIDController.js b/examples/js/controllers/PathEventsWithIDController.js new file mode 100644 index 00000000..f2be21dd --- /dev/null +++ b/examples/js/controllers/PathEventsWithIDController.js @@ -0,0 +1,57 @@ + app.controller("PathEventsWithIDController", function($scope, $log) { + var paths = {}; + $scope.clicked = 0; + var marylandIslands = { + 'Fort Carroll': { + lat: 39.214766, + lng: -76.519003 + }, + 'Gibson Island': { + lat: 39.077642, + lng: -76.433344 + }, + 'Solomons Island': { + lat: 38.320145, + lng: -76.457334 + } + }; + angular.forEach(marylandIslands, function (v, k) { + paths[k] = { + type: "circleMarker", + latlngs: v, + stroke: false, + fillColor: "#00FFFF", + fillOpacity: 0.7, + radius: 10, + clickable: true + }; + }); + angular.extend($scope, { + center: { + lat:38.976492, + lng:-76.49231, + zoom: 8 + }, + layers: { + baselayers: { + xyz: { + name: 'OpenStreetMap (XYZ)', + url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + type: 'xyz' + } + } + }, + events: { + path: { + enable: [ 'click', 'mouseover' ] + } + }, + paths: paths + }); + $scope.$on('leafletDirectivePath.click', function (event) { + $scope.clicked++; + }); + $scope.$on('leafletDirectivePath.mouseover', function (event, path) { + $scope.mouseover = path.modelName; + }); + }); \ No newline at end of file diff --git a/examples/json/README b/examples/json/README index 7e74b187..60318635 100644 --- a/examples/json/README +++ b/examples/json/README @@ -1,2 +1,3 @@ countries.geo.json: https://raw.github.com/johan/world.geo.json/master/countries.geo.json all.json: https://raw.github.com/lukes/ISO-3166-Countries-with-Regional-Codes/master/all/all.json +major_cities: https://github.com/mahemoff/geodata diff --git a/examples/json/examples.json b/examples/json/examples.json index 425f30f2..932c32e3 100644 --- a/examples/json/examples.json +++ b/examples/json/examples.json @@ -1,7 +1,7 @@ { "basic": [ { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:42:52.113Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/first-example", @@ -9,7 +9,7 @@ "title": "First steps, basic example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:42:55.670Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/center-example", @@ -17,7 +17,15 @@ "title": "Center map example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:42:59.576Z", + "section": "basic", + "onlyStandAlone": false, + "id": "/basic/lf-center-example", + "extUrl": "0101-basic-lf-center-example.html", + "title": "Center map example" + }, + { + "date": "2015-11-04T20:43:03.340Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/center-autodiscover-example", @@ -25,7 +33,7 @@ "title": "Center autodiscover example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:07.060Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/center-url-hash-example", @@ -33,7 +41,7 @@ "title": "Center map with URL synchronization example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:10.816Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/custom-parameters-example", @@ -41,7 +49,7 @@ "title": "Using custom default parameters" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:14.396Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/bounds-example", @@ -49,7 +57,7 @@ "title": "Map bounds example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:17.583Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/maxbounds-example", @@ -57,7 +65,7 @@ "title": "Setting MaxBounds in a map" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:21.003Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/tiles-example", @@ -65,7 +73,7 @@ "title": "Changing tiles example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:25.650Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/tiles-zoom-changer-example", @@ -73,7 +81,7 @@ "title": "Dynamic tile changer based on zoom level" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:28.720Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/center-geoip-example", @@ -81,7 +89,7 @@ "title": "Center by IP (GeoIP) example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:32.083Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/map-without-animations-example", @@ -89,7 +97,7 @@ "title": "Map with disabled animations example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:35.836Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/legend-example", @@ -97,7 +105,7 @@ "title": "Legend example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:39.126Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/maxbounds-pad-example", @@ -105,7 +113,7 @@ "title": "Extend Maxbounds with Pad" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:42.546Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/geojson-simple-example", @@ -113,7 +121,7 @@ "title": "Simple GeoJSON example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:46.313Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/geojson-center-example", @@ -121,7 +129,7 @@ "title": "Center to GeoJSON example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:50.956Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/events-example", @@ -129,7 +137,7 @@ "title": "Events example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:54.416Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/access-leaflet-object-example", @@ -137,7 +145,7 @@ "title": "Direct access to the Leaflet Map Object" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:43:57.606Z", "section": "basic", "onlyStandAlone": true, "id": "/basic/routing-show-hide-map-example", @@ -145,7 +153,7 @@ "title": "Angular routing show/hide map example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:05.156Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/double-map-events-example", @@ -153,7 +161,7 @@ "title": "Different map events broadcasting" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:01.656Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/double-map-access-map-object-example", @@ -161,7 +169,7 @@ "title": "Accesing the map object with two (or more) maps on screen" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:08.740Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/double-map-sharing-attributes-example", @@ -169,7 +177,7 @@ "title": "Two maps sharing center example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:12.456Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/double-map-toggle-example", @@ -177,7 +185,7 @@ "title": "Toggle between two maps on screen" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:15.820Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/geojson-update-example", @@ -185,7 +193,7 @@ "title": "GeoJSON update example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:19.080Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/hide-show-map-example", @@ -193,7 +201,7 @@ "title": "Hide/Show map example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:24.493Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/geojson-non-nested-example", @@ -201,7 +209,7 @@ "title": "GeoJSON non nested example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:28.033Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/geojson-nested-example", @@ -209,17 +217,25 @@ "title": "GeoJSON nested example" }, { - "date": "2015-07-09T22:57:30.029Z", + "date": "2015-11-04T20:44:31.510Z", "section": "basic", "onlyStandAlone": false, "id": "/basic/bounds-nominatim-example", "extUrl": "0126-basic-bounds-nominatim-example.html", "title": "Bounds Nominatim map example" + }, + { + "date": "2015-11-04T20:44:35.190Z", + "section": "basic", + "onlyStandAlone": false, + "id": "/basic/tiles-wms-example", + "extUrl": "0127-basic-tiles-wms-example.html", + "title": "Loading WMS tilesDict example" } ], "layers": [ { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:38.906Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/simple-example", @@ -227,7 +243,7 @@ "title": "Layers simple example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:42.246Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/overlays-simple-example", @@ -235,7 +251,7 @@ "title": "Baselayer with overlays" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:45.690Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/imageoverlay-example", @@ -243,7 +259,7 @@ "title": "Layer with image overlay and maxBounds" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:49.193Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/dynamic-addition-example", @@ -251,7 +267,7 @@ "title": "Dynamic addition/removal of layers" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:52.556Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/googlemaps-example", @@ -259,7 +275,7 @@ "title": "Google maps example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:56.063Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/googlemaps-fullsize-example", @@ -267,7 +283,7 @@ "title": "Google Maps fullsize example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:44:59.666Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/hide-baselayer-on-selector-example", @@ -275,7 +291,7 @@ "title": "Baselayer hidden on switch selector to show only overlay" }, { - "date": "2015-06-18T17:06:23.841Z", + "date": "2015-11-04T20:45:03.666Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/esri-dynamic-layer-example", @@ -283,7 +299,7 @@ "title": "Esri ArcGIS Dynamic Map Layer" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:07.320Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/esri-legend-service-example", @@ -291,7 +307,7 @@ "title": "Esri ArcGIS Legend Service" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:10.783Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/webgl-heatmap-example", @@ -299,7 +315,7 @@ "title": "HeatMap WebGL overlay example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:14.183Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/layergroup-simple-example", @@ -307,7 +323,7 @@ "title": "Layer Groups with nested layer definitions" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:17.673Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/hide-overlays-on-selector-example", @@ -315,7 +331,7 @@ "title": "Overlay not shown in selector" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:22.956Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/bingmaps-example", @@ -323,7 +339,7 @@ "title": "Bing maps" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:26.233Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/utfgrid-example", @@ -331,7 +347,7 @@ "title": "Baselayer with UTFGrid interactivity in Overlay" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:30.336Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/overlays-markercluster-example", @@ -339,7 +355,7 @@ "title": "This is a map with overlays and a markercluster" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:33.766Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/overlays-markers-nested-example", @@ -347,7 +363,7 @@ "title": "Layers and overlays with nested markers example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:37.353Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/overlays-paths-example", @@ -355,7 +371,7 @@ "title": "Different overlays for paths" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:40.563Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/wms-with-different-projection-example", @@ -363,7 +379,7 @@ "title": "Load a map in non standard projection" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:43.616Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/heatmap-example", @@ -371,7 +387,7 @@ "title": "HeatMap example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:46.940Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/overlays-hide-on-zoomout-example", @@ -379,7 +395,7 @@ "title": "Baselayer with overlay which is hidden on Zoom less than 4 " }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:45:51.923Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/refresh-overlay-every-minute-example", @@ -387,7 +403,7 @@ "title": "Refreshable overlays example" }, { - "date": "2015-06-17T22:15:13.900Z", + "date": "2015-11-04T20:45:55.230Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/esri-base-layer-example", @@ -395,7 +411,7 @@ "title": "Esri ArcGIS Basemap Layer" }, { - "date": "2015-06-18T16:34:29.457Z", + "date": "2015-11-04T20:45:58.553Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/esri-feature-layer-example", @@ -403,7 +419,7 @@ "title": "Esri ArcGIS Feature Layer" }, { - "date": "2015-06-18T17:25:44.179Z", + "date": "2015-11-04T20:46:02.083Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/esri-tiled-map-layer-example", @@ -411,7 +427,7 @@ "title": "Esri ArcGIS Tiled Map Layer" }, { - "date": "2015-06-18T17:39:19.817Z", + "date": "2015-11-04T20:46:05.456Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/esri-image-layer-example", @@ -419,7 +435,7 @@ "title": "Esri ArcGIS Image Layer" }, { - "date": "2015-06-18T21:34:46.359Z", + "date": "2015-11-04T20:46:09.446Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/esri-clustered-layer-example", @@ -427,7 +443,7 @@ "title": "Esri ArcGIS Clustered Layer" }, { - "date": "2015-06-18T21:39:54.350Z", + "date": "2015-11-04T20:46:14.750Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/esri-heatmap-layer-example", @@ -435,17 +451,25 @@ "title": "Esri ArcGIS Heatmap Layer" }, { - "date": "2015-07-09T22:57:30.029Z", + "date": "2015-11-04T20:46:18.423Z", "section": "layers", "onlyStandAlone": false, "id": "/layers/yandex-example", "extUrl": "0230-layers-yandex-example.html", "title": "Yandex layer example" + }, + { + "date": "2015-11-04T20:46:21.683Z", + "section": "layers", + "onlyStandAlone": false, + "id": "/layers/overlay-geojson-example", + "extUrl": "0231-layers-overlay-geojson-example.html", + "title": "GeoJSON Shape Layer and GeoJSON Awesome Marker Layer" } ], "paths": [ { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:46:24.996Z", "section": "paths", "onlyStandAlone": false, "id": "/paths/simple-example", @@ -453,7 +477,7 @@ "title": "Paths simple example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:46:28.110Z", "section": "paths", "onlyStandAlone": false, "id": "/paths/types-example", @@ -461,7 +485,7 @@ "title": "Types of paths" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:46:31.426Z", "section": "paths", "onlyStandAlone": false, "id": "/paths/ajax-load-example", @@ -469,7 +493,7 @@ "title": "Load remote paths example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:46:35.436Z", "section": "paths", "onlyStandAlone": false, "id": "/paths/3000-items-example", @@ -477,7 +501,7 @@ "title": "3000 items in a map performance" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:46:38.863Z", "section": "paths", "onlyStandAlone": false, "id": "/paths/advanced-example", @@ -485,7 +509,7 @@ "title": "Advanced Paths Example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:46:42.513Z", "section": "paths", "onlyStandAlone": false, "id": "/paths/change-in-group-layer-example", @@ -493,7 +517,7 @@ "title": "Path change in group layer" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:46:45.923Z", "section": "paths", "onlyStandAlone": false, "id": "/paths/decorations-simple-example", @@ -501,7 +525,15 @@ "title": "Path decoration example" }, { - "date": "2015-07-09T22:57:30.029Z", + "date": "2015-11-04T21:20:05.410Z", + "section": "paths", + "onlyStandAlone": false, + "id": "/paths/events-example-with-id", + "extUrl": "0307-paths-events-example-with-id.html", + "title": "Paths specific events propagation exampl" + }, + { + "date": "2015-11-04T21:19:28.183Z", "section": "paths", "onlyStandAlone": false, "id": "/paths/events-example", @@ -511,7 +543,7 @@ ], "controls": [ { - "date": "2015-06-24T16:47:34.186Z", + "date": "2015-11-04T20:46:55.920Z", "section": "controls", "onlyStandAlone": false, "id": "/controls/custom-layer-control-example", @@ -519,7 +551,7 @@ "title": "Dynamic addition and deletion of Overlays control" }, { - "date": "2015-07-09T22:57:30.029Z", + "date": "2015-11-04T20:46:59.943Z", "section": "controls", "onlyStandAlone": false, "id": "/controls/draw-example", @@ -527,7 +559,7 @@ "title": "Draw control example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:47:04.940Z", "section": "controls", "onlyStandAlone": false, "id": "/controls/scale-example", @@ -535,7 +567,7 @@ "title": "Scale control example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:47:08.293Z", "section": "controls", "onlyStandAlone": false, "id": "/controls/fullscreen-example", @@ -543,7 +575,7 @@ "title": "Fullscreen control example" }, { - "date": "2015-07-09T22:57:30.029Z", + "date": "2015-11-04T20:47:11.930Z", "section": "controls", "onlyStandAlone": false, "id": "/controls/minimap-example", @@ -551,17 +583,25 @@ "title": "Minimap control example" }, { - "date": "2015-07-09T22:57:30.029Z", + "date": "2015-11-04T20:47:15.526Z", "section": "controls", "onlyStandAlone": false, "id": "/controls/search-example", "extUrl": "0405-controls-search-example.html", "title": "Search control example" + }, + { + "date": "2015-11-04T20:47:18.690Z", + "section": "controls", + "onlyStandAlone": false, + "id": "/controls/custom-example", + "extUrl": "0406-controls-custom-example.html", + "title": "Fullscreen control example" } ], "markers": [ { - "date": "2015-07-09T22:57:30.029Z", + "date": "2015-11-04T20:47:21.896Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/simple-example", @@ -569,7 +609,7 @@ "title": "Markers simple example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:47:25.256Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/events-add-example", @@ -577,7 +617,7 @@ "title": "Markers with events example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:47:28.810Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/add-remove-example", @@ -585,7 +625,7 @@ "title": "Add/remove markers easily example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:47:32.033Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/icons-example", @@ -593,7 +633,7 @@ "title": "Changing the marker icons" }, { - "date": "2015-07-09T22:57:30.029Z", + "date": "2015-11-04T20:47:37.293Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/popup-example", @@ -601,7 +641,7 @@ "title": "Marker Popup properties" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:47:40.513Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/label-example", @@ -609,104 +649,105 @@ "title": "Marker with label example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:47:44.880Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/groups-example", "extUrl": "0506-markers-groups-example.html", - "title": "This is a map with two hidden marker groups" + "title": "Marker groups" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:47:48.606Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/rotation-example", - "extUrl": "0506-markers-rotation-example.html", + "extUrl": "0507-markers-rotation-example.html", "title": "Changing Icon Rotation" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:47:52.536Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/change-opacity-example", - "extUrl": "0507-markers-change-opacity-example.html", + "extUrl": "0508-markers-change-opacity-example.html", "title": "Change icon opacity" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:47:56.913Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/clustering-example", - "extUrl": "0508-markers-clustering-example.html", + "extUrl": "0509-markers-clustering-example.html", "title": "Marker clustering example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:48:01.010Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/clustering-without-overlays-example", - "extUrl": "0509-markers-clustering-without-overlays-example.html", + "extUrl": "0510-markers-clustering-without-overlays-example.html", "title": "Marker clustering example without layers" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:48:05.473Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/modal-markercluster-example", - "extUrl": "0510-markers-modal-markercluster-example.html", + "extUrl": "0511-markers-modal-markercluster-example.html", "title": "Markercluster in a SemanticUI modal" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:48:10.166Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/clustering-10000-markers-example", - "extUrl": "0511-markers-clustering-10000-markers-example.html", + "extUrl": "0512-markers-clustering-10000-markers-example.html", "title": "Marker clustering example (10000 markers)" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T21:19:51.237Z", + "section": "markers", + "onlyStandAlone": false, + "id": "/markers/events-example-with-id", + "extUrl": "0513-markers-events-example-with-id.html", + "title": "Marker Events example" + }, + { + "date": "2015-11-04T20:48:17.390Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/events-example", - "extUrl": "0512-markers-events-example.html", + "extUrl": "0513-markers-events-example.html", "title": "Marker Events example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:48:20.490Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/delayed-events", - "extUrl": "0513-markers-delayed-events.html", + "extUrl": "0514-markers-delayed-events.html", "title": "Markers delayed events example" }, { - "date": "2015-06-16T19:58:11.778Z", + "date": "2015-11-04T20:48:24.070Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/angular-template-example", - "extUrl": "0514-markers-angular-template-example.html", + "extUrl": "0515-markers-angular-template-example.html", "title": "Markers angular template example" }, { - "date": "2015-06-16T19:58:11.782Z", + "date": "2015-11-04T20:48:28.303Z", "section": "markers", "onlyStandAlone": false, "id": "/markers/two-maps-events-example", - "extUrl": "0515-markers-two-maps-events-example.html", + "extUrl": "0516-markers-two-maps-events-example.html", "title": "Two maps with markers and events" - }, - { - "date": "2015-06-16T19:58:11.782Z", - "section": "markers", - "onlyStandAlone": false, - "id": "/markers/cluster-issue", - "extUrl": "0755-markers-cluster-issue.html" } ], "mixed": [ { - "date": "2015-06-16T19:58:11.782Z", + "date": "2015-11-04T20:48:34.176Z", "section": "mixed", "onlyStandAlone": false, "id": "/mixed/image-legend-example", @@ -714,7 +755,15 @@ "title": "Image Legend Service" }, { - "date": "2015-06-16T19:58:11.782Z", + "date": "2015-11-04T20:48:37.930Z", + "section": "mixed", + "onlyStandAlone": false, + "id": "/mixed/geojson-events-example-w-id", + "extUrl": "0601-mixed-geojson-events-example-w-id.html", + "title": "World map flags example" + }, + { + "date": "2015-11-04T20:48:41.520Z", "section": "mixed", "onlyStandAlone": false, "id": "/mixed/geojson-events-example", @@ -722,7 +771,7 @@ "title": "World map flags example" }, { - "date": "2015-06-16T19:58:11.782Z", + "date": "2015-11-04T20:48:44.910Z", "section": "mixed", "onlyStandAlone": false, "id": "/mixed/mapbox-tiles-geojson-example", @@ -730,15 +779,15 @@ "title": "Mapbox tiles and Mapbox GeoJSON loading" }, { - "date": "2015-06-16T19:58:11.782Z", + "date": "2015-11-04T20:48:48.416Z", "section": "mixed", "onlyStandAlone": false, "id": "/mixed/layers-overlays-geojson-example", "extUrl": "0603-mixed-layers-overlays-geojson-example.html", - "title": "\t\t GeoJSON TileLayers" + "title": "GeoJSON TileLayers" }, { - "date": "2015-06-16T19:58:11.782Z", + "date": "2015-11-04T20:48:51.793Z", "section": "mixed", "onlyStandAlone": false, "id": "/mixed/markers-nested-events-example", @@ -746,12 +795,28 @@ "title": "Marker Events example" }, { - "date": "2015-06-16T19:58:11.782Z", + "date": "2015-11-04T20:48:56.626Z", "section": "mixed", "onlyStandAlone": false, "id": "/mixed/overlays-markers-nested-no-watch-example", "extUrl": "0605-mixed-overlays-markers-nested-no-watch-example.html", "title": "Overlays with nested markers no watchers example" + }, + { + "date": "2015-11-04T20:48:59.606Z", + "section": "mixed", + "onlyStandAlone": false, + "id": "/mixed/esri-legend-service-example", + "extUrl": "0606-mixed-esri-legend-service-example.html", + "title": "Esri ArcGIS Legend Service" + }, + { + "date": "2015-11-04T20:49:03.750Z", + "section": "mixed", + "onlyStandAlone": false, + "id": "/mixed/esri-multilayer-legend-service-example", + "extUrl": "0607-mixed-esri-multilayer-legend-service-example.html", + "title": "Esri ArcGIS Multilayer Legend Service" } ] } \ No newline at end of file diff --git a/examples/json/major_cities.json b/examples/json/major_cities.json new file mode 100644 index 00000000..938475a5 --- /dev/null +++ b/examples/json/major_cities.json @@ -0,0 +1,7275 @@ +{ + "type": "FeatureCollection", + "features": [{ + "geometry": { + "type": "Point", + "coordinates": [-176.633, 51.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Adak,_Alaska", + "city": "Adak" + }, + "id": "Adak" + }, { + "geometry": { + "type": "Point", + "coordinates": [-175.2, -21.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nuku%CA%BBalofa", + "city": "Nuku%CA%BBalofa" + }, + "id": "Nuku%CA%BBalofa" + }, { + "geometry": { + "type": "Point", + "coordinates": [-171.833, -13.833] + }, + "type": "Feature", + "properties": { + "wikipedia": "Apia", + "city": "Apia" + }, + "id": "Apia" + }, { + "geometry": { + "type": "Point", + "coordinates": [-170.7, -14.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Pago_Pago", + "city": "Pago Pago" + }, + "id": "Pago Pago" + }, { + "geometry": { + "type": "Point", + "coordinates": [-169.917, -19.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Alofi", + "city": "Alofi" + }, + "id": "Alofi" + }, { + "geometry": { + "type": "Point", + "coordinates": [-159.767, -21.2] + }, + "type": "Feature", + "properties": { + "wikipedia": "Avarua", + "city": "Avarua" + }, + "id": "Avarua" + }, { + "geometry": { + "type": "Point", + "coordinates": [-157.817, 21.3] + }, + "type": "Feature", + "properties": { + "wikipedia": "Honolulu", + "city": "Honolulu" + }, + "id": "Honolulu" + }, { + "geometry": { + "type": "Point", + "coordinates": [-155.1, 19.7] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hilo,_Hawaii", + "city": "Hilo" + }, + "id": "Hilo" + }, { + "geometry": { + "type": "Point", + "coordinates": [-149.883, 61.217] + }, + "type": "Feature", + "properties": { + "wikipedia": "Anchorage,_Alaska", + "city": "Anchorage" + }, + "id": "Anchorage" + }, { + "geometry": { + "type": "Point", + "coordinates": [-149.567, -17.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "Papeete", + "city": "Papeete" + }, + "id": "Papeete" + }, { + "geometry": { + "type": "Point", + "coordinates": [-147.7, 64.833] + }, + "type": "Feature", + "properties": { + "wikipedia": "Fairbanks,_Alaska", + "city": "Fairbanks" + }, + "id": "Fairbanks" + }, { + "geometry": { + "type": "Point", + "coordinates": [-135.317, 57.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sitka,_Alaska", + "city": "Sitka" + }, + "id": "Sitka" + }, { + "geometry": { + "type": "Point", + "coordinates": [-135.05, 60.717] + }, + "type": "Feature", + "properties": { + "wikipedia": "Whitehorse,_Yukon", + "city": "Whitehorse" + }, + "id": "Whitehorse" + }, { + "geometry": { + "type": "Point", + "coordinates": [-134.5, 58.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Juneau,_Alaska", + "city": "Juneau" + }, + "id": "Juneau" + }, { + "geometry": { + "type": "Point", + "coordinates": [-130.1, -25.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Adamstown,_Pitcairn_Islands", + "city": "Adamstown" + }, + "id": "Adamstown" + }, { + "geometry": { + "type": "Point", + "coordinates": [-123.1, 49.25] + }, + "type": "Feature", + "properties": { + "wikipedia": "Vancouver", + "city": "Vancouver" + }, + "id": "Vancouver" + }, { + "geometry": { + "type": "Point", + "coordinates": [-12.05, 3.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Rabi_Island", + "city": "Rabi Island" + }, + "id": "Rabi Island" + }, { + "geometry": { + "type": "Point", + "coordinates": [-122.667, 45.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Portland,_Oregon", + "city": "Portland" + }, + "id": "Portland" + }, { + "geometry": { + "type": "Point", + "coordinates": [-122.417, 37.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "San_Francisco", + "city": "San Francisco" + }, + "id": "San Francisco" + }, { + "geometry": { + "type": "Point", + "coordinates": [-122.317, 47.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Seattle", + "city": "Seattle" + }, + "id": "Seattle" + }, { + "geometry": { + "type": "Point", + "coordinates": [-121.467, 38.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sacramento,_California", + "city": "Sacramento" + }, + "id": "Sacramento" + }, { + "geometry": { + "type": "Point", + "coordinates": [-118.25, 34.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Los_Angeles", + "city": "Los Angeles" + }, + "id": "Los Angeles" + }, { + "geometry": { + "type": "Point", + "coordinates": [-117.383, 33.933] + }, + "type": "Feature", + "properties": { + "wikipedia": "Riverside,_California", + "city": "Riverside" + }, + "id": "Riverside" + }, { + "geometry": { + "type": "Point", + "coordinates": [-117.15, 32.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "San_Diego", + "city": "San Diego" + }, + "id": "San Diego" + }, { + "geometry": { + "type": "Point", + "coordinates": [-117.033, 32.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tijuana", + "city": "Tijuana" + }, + "id": "Tijuana" + }, { + "geometry": { + "type": "Point", + "coordinates": [-115.467, 32.667] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mexicali", + "city": "Mexicali" + }, + "id": "Mexicali" + }, { + "geometry": { + "type": "Point", + "coordinates": [-115.133, 36.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Las_Vegas,_Nevada", + "city": "Las Vegas" + }, + "id": "Las Vegas" + }, { + "geometry": { + "type": "Point", + "coordinates": [-114.4, 62.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Yellowknife", + "city": "Yellowknife" + }, + "id": "Yellowknife" + }, { + "geometry": { + "type": "Point", + "coordinates": [-114.05, 51.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Calgary", + "city": "Calgary" + }, + "id": "Calgary" + }, { + "geometry": { + "type": "Point", + "coordinates": [-113.517, 53.567] + }, + "type": "Feature", + "properties": { + "wikipedia": "Edmonton", + "city": "Edmonton" + }, + "id": "Edmonton" + }, { + "geometry": { + "type": "Point", + "coordinates": [-112.067, 33.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Phoenix,_Arizona", + "city": "Phoenix" + }, + "id": "Phoenix" + }, { + "geometry": { + "type": "Point", + "coordinates": [-111.883, 40.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Salt_Lake_City", + "city": "Salt Lake City" + }, + "id": "Salt Lake City" + }, { + "geometry": { + "type": "Point", + "coordinates": [-110.917, 32.2] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tucson,_Arizona", + "city": "Tucson" + }, + "id": "Tucson" + }, { + "geometry": { + "type": "Point", + "coordinates": [-109.433, 27.15] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hanga_Roa", + "city": "Hanga Roa" + }, + "id": "Hanga Roa" + }, { + "geometry": { + "type": "Point", + "coordinates": [-106.65, 52.117] + }, + "type": "Feature", + "properties": { + "wikipedia": "Saskatoon", + "city": "Saskatoon" + }, + "id": "Saskatoon" + }, { + "geometry": { + "type": "Point", + "coordinates": [-106.6, 35.1] + }, + "type": "Feature", + "properties": { + "wikipedia": "Albuquerque,_New_Mexico", + "city": "Albuquerque" + }, + "id": "Albuquerque" + }, { + "geometry": { + "type": "Point", + "coordinates": [-106.417, 31.783] + }, + "type": "Feature", + "properties": { + "wikipedia": "El_Paso,_Texas", + "city": "El Paso" + }, + "id": "El Paso" + }, { + "geometry": { + "type": "Point", + "coordinates": [-106, 28.1] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chihuahua,_Chihuahua", + "city": "Chihuahua" + }, + "id": "Chihuahua" + }, { + "geometry": { + "type": "Point", + "coordinates": [-104.983, 39.733] + }, + "type": "Feature", + "properties": { + "wikipedia": "Denver", + "city": "Denver" + }, + "id": "Denver" + }, { + "geometry": { + "type": "Point", + "coordinates": [-104.667, 24.017] + }, + "type": "Feature", + "properties": { + "wikipedia": "Durango,_Durango", + "city": "Durango" + }, + "id": "Durango" + }, { + "geometry": { + "type": "Point", + "coordinates": [-104.617, 50.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Regina,_Saskatchewan", + "city": "Regina" + }, + "id": "Regina" + }, { + "geometry": { + "type": "Point", + "coordinates": [-103.4, 20.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "Zapopan,_Jalisco", + "city": "Zapopan" + }, + "id": "Zapopan" + }, { + "geometry": { + "type": "Point", + "coordinates": [-103.35, 20.667] + }, + "type": "Feature", + "properties": { + "wikipedia": "Guadalajara,_Jalisco", + "city": "Guadalajara" + }, + "id": "Guadalajara" + }, { + "geometry": { + "type": "Point", + "coordinates": [-100.3, 25.667] + }, + "type": "Feature", + "properties": { + "wikipedia": "Monterrey", + "city": "Monterrey" + }, + "id": "Monterrey" + }, { + "geometry": { + "type": "Point", + "coordinates": [-99.117, 19.4] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mexico_City", + "city": "Mexico City" + }, + "id": "Mexico City" + }, { + "geometry": { + "type": "Point", + "coordinates": [-98.467, 29.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "San_Antonio", + "city": "San Antonio" + }, + "id": "San Antonio" + }, { + "geometry": { + "type": "Point", + "coordinates": [-98.2, 19.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Puebla,_Puebla", + "city": "Puebla" + }, + "id": "Puebla" + }, { + "geometry": { + "type": "Point", + "coordinates": [-97.767, 30.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Austin,_Texas", + "city": "Austin" + }, + "id": "Austin" + }, { + "geometry": { + "type": "Point", + "coordinates": [-97.533, 35.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Oklahoma_City", + "city": "Oklahoma City" + }, + "id": "Oklahoma City" + }, { + "geometry": { + "type": "Point", + "coordinates": [-97.333, 37.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Wichita,_Kansas", + "city": "Wichita" + }, + "id": "Wichita" + }, { + "geometry": { + "type": "Point", + "coordinates": [-97.133, 49.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Winnipeg", + "city": "Winnipeg" + }, + "id": "Winnipeg" + }, { + "geometry": { + "type": "Point", + "coordinates": [-96.8, 32.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dallas", + "city": "Dallas" + }, + "id": "Dallas" + }, { + "geometry": { + "type": "Point", + "coordinates": [-96.133, 19.183] + }, + "type": "Feature", + "properties": { + "wikipedia": "Veracruz,_Veracruz", + "city": "Veracruz" + }, + "id": "Veracruz" + }, { + "geometry": { + "type": "Point", + "coordinates": [-95.367, 29.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Houston", + "city": "Houston" + }, + "id": "Houston" + }, { + "geometry": { + "type": "Point", + "coordinates": [-94.567, 39.1] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kansas_City,_Missouri", + "city": "Kansas City" + }, + "id": "Kansas City" + }, { + "geometry": { + "type": "Point", + "coordinates": [-93.25, 44.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Minneapolis", + "city": "Minneapolis" + }, + "id": "Minneapolis" + }, { + "geometry": { + "type": "Point", + "coordinates": [-91.517, 14.833] + }, + "type": "Feature", + "properties": { + "wikipedia": "Quetzaltenango", + "city": "Quetzaltenango" + }, + "id": "Quetzaltenango" + }, { + "geometry": { + "type": "Point", + "coordinates": [-90.55, 14.633] + }, + "type": "Feature", + "properties": { + "wikipedia": "Guatemala_City", + "city": "Guatemala City" + }, + "id": "Guatemala City" + }, { + "geometry": { + "type": "Point", + "coordinates": [-90.183, 38.617] + }, + "type": "Feature", + "properties": { + "wikipedia": "St._Louis,_Missouri", + "city": "St. Louis" + }, + "id": "St. Louis" + }, { + "geometry": { + "type": "Point", + "coordinates": [-90.067, 29.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "New_Orleans", + "city": "New Orleans" + }, + "id": "New Orleans" + }, { + "geometry": { + "type": "Point", + "coordinates": [-89.967, 35.117] + }, + "type": "Feature", + "properties": { + "wikipedia": "Memphis,_Tennessee", + "city": "Memphis" + }, + "id": "Memphis" + }, { + "geometry": { + "type": "Point", + "coordinates": [-89.617, 20.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "M%C3%A9rida,_Yucat%C3%A1n", + "city": "M%C3%A9rida" + }, + "id": "M%C3%A9rida" + }, { + "geometry": { + "type": "Point", + "coordinates": [-89.183, 13.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "San_Salvador", + "city": "San Salvador" + }, + "id": "San Salvador" + }, { + "geometry": { + "type": "Point", + "coordinates": [-88.767, 17.25] + }, + "type": "Feature", + "properties": { + "wikipedia": "Belmopan", + "city": "Belmopan" + }, + "id": "Belmopan" + }, { + "geometry": { + "type": "Point", + "coordinates": [-88.183, 17.483] + }, + "type": "Feature", + "properties": { + "wikipedia": "Belize_City", + "city": "Belize City" + }, + "id": "Belize City" + }, { + "geometry": { + "type": "Point", + "coordinates": [-87.95, 47.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Milwaukee", + "city": "Milwaukee" + }, + "id": "Milwaukee" + }, { + "geometry": { + "type": "Point", + "coordinates": [-87.617, 41.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chicago", + "city": "Chicago" + }, + "id": "Chicago" + }, { + "geometry": { + "type": "Point", + "coordinates": [-87.217, 14.083] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tegucigalpa", + "city": "Tegucigalpa" + }, + "id": "Tegucigalpa" + }, { + "geometry": { + "type": "Point", + "coordinates": [-86.783, 36.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nashville,_Tennessee", + "city": "Nashville" + }, + "id": "Nashville" + }, { + "geometry": { + "type": "Point", + "coordinates": [-86.25, 12.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Managua", + "city": "Managua" + }, + "id": "Managua" + }, { + "geometry": { + "type": "Point", + "coordinates": [-86.15, 39.783] + }, + "type": "Feature", + "properties": { + "wikipedia": "Indianapolis", + "city": "Indianapolis" + }, + "id": "Indianapolis" + }, { + "geometry": { + "type": "Point", + "coordinates": [-85.75, 38.25] + }, + "type": "Feature", + "properties": { + "wikipedia": "Louisville,_Kentucky", + "city": "Louisville" + }, + "id": "Louisville" + }, { + "geometry": { + "type": "Point", + "coordinates": [-84.5, 39.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cincinnati", + "city": "Cincinnati" + }, + "id": "Cincinnati" + }, { + "geometry": { + "type": "Point", + "coordinates": [-84.383, 33.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Atlanta", + "city": "Atlanta" + }, + "id": "Atlanta" + }, { + "geometry": { + "type": "Point", + "coordinates": [-84.083, 9.933] + }, + "type": "Feature", + "properties": { + "wikipedia": "San_Jos%C3%A9,_Costa_Rica", + "city": "San Jos%C3%A9" + }, + "id": "San Jos%C3%A9" + }, { + "geometry": { + "type": "Point", + "coordinates": [-83.05, 42.333] + }, + "type": "Feature", + "properties": { + "wikipedia": "Detroit", + "city": "Detroit" + }, + "id": "Detroit" + }, { + "geometry": { + "type": "Point", + "coordinates": [-82.983, 39.983] + }, + "type": "Feature", + "properties": { + "wikipedia": "Columbus,_Ohio", + "city": "Columbus" + }, + "id": "Columbus" + }, { + "geometry": { + "type": "Point", + "coordinates": [-82.467, 27.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tampa,_Florida", + "city": "Tampa" + }, + "id": "Tampa" + }, { + "geometry": { + "type": "Point", + "coordinates": [-82.383, 23.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Havana", + "city": "Havana" + }, + "id": "Havana" + }, { + "geometry": { + "type": "Point", + "coordinates": [-81.667, 41.483] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cleveland", + "city": "Cleveland" + }, + "id": "Cleveland" + }, { + "geometry": { + "type": "Point", + "coordinates": [-81.65, 30.317] + }, + "type": "Feature", + "properties": { + "wikipedia": "Jacksonville,_Florida", + "city": "Jacksonville" + }, + "id": "Jacksonville" + }, { + "geometry": { + "type": "Point", + "coordinates": [100.317, 5.417] + }, + "type": "Feature", + "properties": { + "wikipedia": "George_Town,_Penang", + "city": "George Town" + }, + "id": "George Town" + }, { + "geometry": { + "type": "Point", + "coordinates": [-80.817, 35.2] + }, + "type": "Feature", + "properties": { + "wikipedia": "Charlotte,_North_Carolina", + "city": "Charlotte" + }, + "id": "Charlotte" + }, { + "geometry": { + "type": "Point", + "coordinates": [-80.217, 25.783] + }, + "type": "Feature", + "properties": { + "wikipedia": "Miami", + "city": "Miami" + }, + "id": "Miami" + }, { + "geometry": { + "type": "Point", + "coordinates": [-79.967, 40.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Pittsburgh", + "city": "Pittsburgh" + }, + "id": "Pittsburgh" + }, { + "geometry": { + "type": "Point", + "coordinates": [-79.883, 2.183] + }, + "type": "Feature", + "properties": { + "wikipedia": "Guayaquil", + "city": "Guayaquil" + }, + "id": "Guayaquil" + }, { + "geometry": { + "type": "Point", + "coordinates": [-79.517, 8.983] + }, + "type": "Feature", + "properties": { + "wikipedia": "Panama_City", + "city": "Panama City" + }, + "id": "Panama City" + }, { + "geometry": { + "type": "Point", + "coordinates": [-79.383, 43.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Toronto", + "city": "Toronto" + }, + "id": "Toronto" + }, { + "geometry": { + "type": "Point", + "coordinates": [-78.85, 42.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Buffalo,_New_York", + "city": "Buffalo" + }, + "id": "Buffalo" + }, { + "geometry": { + "type": "Point", + "coordinates": [-78.633, 35.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Raleigh,_North_Carolina", + "city": "Raleigh" + }, + "id": "Raleigh" + }, { + "geometry": { + "type": "Point", + "coordinates": [-78.583, 0.25] + }, + "type": "Feature", + "properties": { + "wikipedia": "Quito", + "city": "Quito" + }, + "id": "Quito" + }, { + "geometry": { + "type": "Point", + "coordinates": [-77.6, 43.15] + }, + "type": "Feature", + "properties": { + "wikipedia": "Rochester,_New_York", + "city": "Rochester" + }, + "id": "Rochester" + }, { + "geometry": { + "type": "Point", + "coordinates": [-77.333, 25.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nassau,_Bahamas", + "city": "Nassau" + }, + "id": "Nassau" + }, { + "geometry": { + "type": "Point", + "coordinates": [-77.033, 38.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Washington,_D.C.", + "city": "Washington" + }, + "id": "Washington" + }, { + "geometry": { + "type": "Point", + "coordinates": [-77.017, -12.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lima", + "city": "Lima" + }, + "id": "Lima" + }, { + "geometry": { + "type": "Point", + "coordinates": [167.967, -29.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kingston,_Norfolk_Island", + "city": "Kingston" + }, + "id": "Kingston" + }, { + "geometry": { + "type": "Point", + "coordinates": [-76.617, 39.283] + }, + "type": "Feature", + "properties": { + "wikipedia": "Baltimore", + "city": "Baltimore" + }, + "id": "Baltimore" + }, { + "geometry": { + "type": "Point", + "coordinates": [-76.517, 3.417] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cali", + "city": "Cali" + }, + "id": "Cali" + }, { + "geometry": { + "type": "Point", + "coordinates": [-75.983, 36.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Virginia_Beach", + "city": "Virginia Beach" + }, + "id": "Virginia Beach" + }, { + "geometry": { + "type": "Point", + "coordinates": [-75.8, 20.017] + }, + "type": "Feature", + "properties": { + "wikipedia": "Santiago_de_Cuba", + "city": "Santiago de Cuba" + }, + "id": "Santiago de Cuba" + }, { + "geometry": { + "type": "Point", + "coordinates": [-75.683, 45.417] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ottawa", + "city": "Ottawa" + }, + "id": "Ottawa" + }, { + "geometry": { + "type": "Point", + "coordinates": [-75.567, 6.233] + }, + "type": "Feature", + "properties": { + "wikipedia": "Medell%C3%ADn", + "city": "Medell%C3%ADn" + }, + "id": "Medell%C3%ADn" + }, { + "geometry": { + "type": "Point", + "coordinates": [-75.5, 10.4] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cartagena,_Colombia", + "city": "Cartagena" + }, + "id": "Cartagena" + }, { + "geometry": { + "type": "Point", + "coordinates": [-75.167, 39.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Philadelphia", + "city": "Philadelphia" + }, + "id": "Philadelphia" + }, { + "geometry": { + "type": "Point", + "coordinates": [-74.783, 10.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Barranquilla", + "city": "Barranquilla" + }, + "id": "Barranquilla" + }, { + "geometry": { + "type": "Point", + "coordinates": [-74.183, 39.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Forked_River", + "city": "Forked River" + }, + "id": "Forked River" + }, { + "geometry": { + "type": "Point", + "coordinates": [-74.133, 41.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Jersey_City,_New_Jersey", + "city": "Jersey City" + }, + "id": "Jersey City" + }, { + "geometry": { + "type": "Point", + "coordinates": [-74.067, 4.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bogot%C3%A1", + "city": "Bogot%C3%A1" + }, + "id": "Bogot%C3%A1" + }, { + "geometry": { + "type": "Point", + "coordinates": [-74, 40.717] + }, + "type": "Feature", + "properties": { + "wikipedia": "New_York_City", + "city": "New York City" + }, + "id": "New York City" + }, { + "geometry": { + "type": "Point", + "coordinates": [-73.55, 45.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Montreal", + "city": "Montreal" + }, + "id": "Montreal" + }, { + "geometry": { + "type": "Point", + "coordinates": [-73.25, -3.733] + }, + "type": "Feature", + "properties": { + "wikipedia": "Iquitos", + "city": "Iquitos" + }, + "id": "Iquitos" + }, { + "geometry": { + "type": "Point", + "coordinates": [-73.233, -39.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Valdivia,_Chile", + "city": "Valdivia" + }, + "id": "Valdivia" + }, { + "geometry": { + "type": "Point", + "coordinates": [-73.05, -36.833] + }, + "type": "Feature", + "properties": { + "wikipedia": "Concepci%C3%B3n,_Chile", + "city": "Concepci%C3%B3n" + }, + "id": "Concepci%C3%B3n" + }, { + "geometry": { + "type": "Point", + "coordinates": [-72.333, 18.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "Port-au-Prince", + "city": "Port-au-Prince" + }, + "id": "Port-au-Prince" + }, { + "geometry": { + "type": "Point", + "coordinates": [-71.967, -13.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cusco", + "city": "Cusco" + }, + "id": "Cusco" + }, { + "geometry": { + "type": "Point", + "coordinates": [-71.633, -10.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Maracaibo", + "city": "Maracaibo" + }, + "id": "Maracaibo" + }, { + "geometry": { + "type": "Point", + "coordinates": [-71.617, -33.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Valpara%C3%ADso", + "city": "Valpara%C3%ADso" + }, + "id": "Valpara%C3%ADso" + }, { + "geometry": { + "type": "Point", + "coordinates": [-71.533, -16.4] + }, + "type": "Feature", + "properties": { + "wikipedia": "Arequipa", + "city": "Arequipa" + }, + "id": "Arequipa" + }, { + "geometry": { + "type": "Point", + "coordinates": [-71.417, 41.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Providence,_Rhode_Island", + "city": "Providence" + }, + "id": "Providence" + }, { + "geometry": { + "type": "Point", + "coordinates": [-71.3, -41.15] + }, + "type": "Feature", + "properties": { + "wikipedia": "San_Carlos_de_Bariloche", + "city": "San Carlos de Bariloche" + }, + "id": "San Carlos de Bariloche" + }, { + "geometry": { + "type": "Point", + "coordinates": [-71.25, -29.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "La_Serena,_Chile", + "city": "La Serena" + }, + "id": "La Serena" + }, { + "geometry": { + "type": "Point", + "coordinates": [-71.217, 46.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Quebec_City", + "city": "Quebec City" + }, + "id": "Quebec City" + }, { + "geometry": { + "type": "Point", + "coordinates": [-71.133, 21.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cockburn_Town", + "city": "Cockburn Town" + }, + "id": "Cockburn Town" + }, { + "geometry": { + "type": "Point", + "coordinates": [-71.05, 42.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Boston", + "city": "Boston" + }, + "id": "Boston" + }, { + "geometry": { + "type": "Point", + "coordinates": [-70.933, -53.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Punta_Arenas,_Chile", + "city": "Punta Arenas" + }, + "id": "Punta Arenas" + }, { + "geometry": { + "type": "Point", + "coordinates": [-70.667, -33.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Santiago,_Chile", + "city": "Santiago" + }, + "id": "Santiago" + }, { + "geometry": { + "type": "Point", + "coordinates": [-70.4, -23.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Antofagasta", + "city": "Antofagasta" + }, + "id": "Antofagasta" + }, { + "geometry": { + "type": "Point", + "coordinates": [-70.15, -20.217] + }, + "type": "Feature", + "properties": { + "wikipedia": "Iquique", + "city": "Iquique" + }, + "id": "Iquique" + }, { + "geometry": { + "type": "Point", + "coordinates": [-70.033, 12.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Oranjestad,_Aruba", + "city": "Oranjestad" + }, + "id": "Oranjestad" + }, { + "geometry": { + "type": "Point", + "coordinates": [-69.917, 18.483] + }, + "type": "Feature", + "properties": { + "wikipedia": "Santo_Domingo", + "city": "Santo Domingo" + }, + "id": "Santo Domingo" + }, { + "geometry": { + "type": "Point", + "coordinates": [-69.35, -10.117] + }, + "type": "Feature", + "properties": { + "wikipedia": "Rio_Branco", + "city": "Rio Branco" + }, + "id": "Rio Branco" + }, { + "geometry": { + "type": "Point", + "coordinates": [-68.933, 12.117] + }, + "type": "Feature", + "properties": { + "wikipedia": "Willemstad", + "city": "Willemstad" + }, + "id": "Willemstad" + }, { + "geometry": { + "type": "Point", + "coordinates": [-68.933, -22.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Calama,_Chile", + "city": "Calama" + }, + "id": "Calama" + }, { + "geometry": { + "type": "Point", + "coordinates": [-68.817, -32.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mendoza,_Argentina", + "city": "Mendoza" + }, + "id": "Mendoza" + }, { + "geometry": { + "type": "Point", + "coordinates": [-68.517, 63.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Iqaluit", + "city": "Iqaluit" + }, + "id": "Iqaluit" + }, { + "geometry": { + "type": "Point", + "coordinates": [-68.3, -54.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ushuaia", + "city": "Ushuaia" + }, + "id": "Ushuaia" + }, { + "geometry": { + "type": "Point", + "coordinates": [-68.15, -16.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "La_Paz", + "city": "La Paz" + }, + "id": "La Paz" + }, { + "geometry": { + "type": "Point", + "coordinates": [-67.617, 54.933] + }, + "type": "Feature", + "properties": { + "wikipedia": "Puerto_Williams", + "city": "Puerto Williams" + }, + "id": "Puerto Williams" + }, { + "geometry": { + "type": "Point", + "coordinates": [-66.917, 10.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Caracas", + "city": "Caracas" + }, + "id": "Caracas" + }, { + "geometry": { + "type": "Point", + "coordinates": [-66.667, 45.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Fredericton", + "city": "Fredericton" + }, + "id": "Fredericton" + }, { + "geometry": { + "type": "Point", + "coordinates": [-66.067, 18.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "San_Juan,_Puerto_Rico", + "city": "San Juan" + }, + "id": "San Juan" + }, { + "geometry": { + "type": "Point", + "coordinates": [-66.05, 45.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Saint_John,_New_Brunswick", + "city": "Saint John" + }, + "id": "Saint John" + }, { + "geometry": { + "type": "Point", + "coordinates": [-65.25, -19.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sucre", + "city": "Sucre" + }, + "id": "Sucre" + }, { + "geometry": { + "type": "Point", + "coordinates": [-64.95, -18.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Charlotte_Amalie,_United_States_Virgin_Islands", + "city": "Charlotte Amalie" + }, + "id": "Charlotte Amalie" + }, { + "geometry": { + "type": "Point", + "coordinates": [175.283, -37.783] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hamilton,_New_Zealand", + "city": "Hamilton" + }, + "id": "Hamilton" + }, { + "geometry": { + "type": "Point", + "coordinates": [-64.617, 18.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Road_Town", + "city": "Road Town" + }, + "id": "Road Town" + }, { + "geometry": { + "type": "Point", + "coordinates": [-64.183, -31.4] + }, + "type": "Feature", + "properties": { + "wikipedia": "C%C3%B3rdoba,_Argentina", + "city": "C%C3%B3rdoba" + }, + "id": "C%C3%B3rdoba" + }, { + "geometry": { + "type": "Point", + "coordinates": [-63.9, -8.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Porto_Velho", + "city": "Porto Velho" + }, + "id": "Porto Velho" + }, { + "geometry": { + "type": "Point", + "coordinates": [-63.6, 44.667] + }, + "type": "Feature", + "properties": { + "wikipedia": "City_of_Halifax", + "city": "City of Halifax" + }, + "id": "City of Halifax" + }, { + "geometry": { + "type": "Point", + "coordinates": [-63.167, -17.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Santa_Cruz_de_la_Sierra", + "city": "Santa Cruz de la Sierra" + }, + "id": "Santa Cruz de la Sierra" + }, { + "geometry": { + "type": "Point", + "coordinates": [-63.133, 46.233] + }, + "type": "Feature", + "properties": { + "wikipedia": "Charlottetown", + "city": "Charlottetown" + }, + "id": "Charlottetown" + }, { + "geometry": { + "type": "Point", + "coordinates": [-63.05, 18.217] + }, + "type": "Feature", + "properties": { + "wikipedia": "The_Valley,_Anguilla", + "city": "The Valley" + }, + "id": "The Valley" + }, { + "geometry": { + "type": "Point", + "coordinates": [-61.717, 15.983] + }, + "type": "Feature", + "properties": { + "wikipedia": "Basse-Terre", + "city": "Basse-Terre" + }, + "id": "Basse-Terre" + }, { + "geometry": { + "type": "Point", + "coordinates": [-62.267, -38.717] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bah%C3%ADa_Blanca", + "city": "Bah%C3%ADa Blanca" + }, + "id": "Bah%C3%ADa Blanca" + }, { + "geometry": { + "type": "Point", + "coordinates": [-52.7, 47.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "St._John%27s,_Newfoundland_and_Labrador", + "city": "St. John%27s" + }, + "id": "St. John%27s" + }, { + "geometry": { + "type": "Point", + "coordinates": [-61.75, 12.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "St._George%27s,_Grenada", + "city": "St. George%27s" + }, + "id": "St. George%27s" + }, { + "geometry": { + "type": "Point", + "coordinates": [-61.517, 10.667] + }, + "type": "Feature", + "properties": { + "wikipedia": "Port_of_Spain", + "city": "Port of Spain" + }, + "id": "Port of Spain" + }, { + "geometry": { + "type": "Point", + "coordinates": [-61.467, 10.283] + }, + "type": "Feature", + "properties": { + "wikipedia": "San_Fernando,_Trinidad_and_Tobago", + "city": "San Fernando" + }, + "id": "San Fernando" + }, { + "geometry": { + "type": "Point", + "coordinates": [-61.383, 15.3] + }, + "type": "Feature", + "properties": { + "wikipedia": "Roseau", + "city": "Roseau" + }, + "id": "Roseau" + }, { + "geometry": { + "type": "Point", + "coordinates": [-61.383, 10.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chaguanas", + "city": "Chaguanas" + }, + "id": "Chaguanas" + }, { + "geometry": { + "type": "Point", + "coordinates": [-61.233, 13.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kingstown", + "city": "Kingstown" + }, + "id": "Kingstown" + }, { + "geometry": { + "type": "Point", + "coordinates": [-61.083, 14.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Fort-de-France", + "city": "Fort-de-France" + }, + "id": "Fort-de-France" + }, { + "geometry": { + "type": "Point", + "coordinates": [-60.983, 14.017] + }, + "type": "Feature", + "properties": { + "wikipedia": "Castries", + "city": "Castries" + }, + "id": "Castries" + }, { + "geometry": { + "type": "Point", + "coordinates": [-60.667, -32.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Rosario,_Santa_Fe", + "city": "Rosario" + }, + "id": "Rosario" + }, { + "geometry": { + "type": "Point", + "coordinates": [-60.65, 2.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Boa_Vista,_Roraima", + "city": "Boa Vista" + }, + "id": "Boa Vista" + }, { + "geometry": { + "type": "Point", + "coordinates": [-60.017, -3.1] + }, + "type": "Feature", + "properties": { + "wikipedia": "Manaus", + "city": "Manaus" + }, + "id": "Manaus" + }, { + "geometry": { + "type": "Point", + "coordinates": [-59.617, 13.083] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bridgetown", + "city": "Bridgetown" + }, + "id": "Bridgetown" + }, { + "geometry": { + "type": "Point", + "coordinates": [-58.367, -34.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Buenos_Aires", + "city": "Buenos Aires" + }, + "id": "Buenos Aires" + }, { + "geometry": { + "type": "Point", + "coordinates": [-57.85, 51.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Stanley,_Falkland_Islands", + "city": "Stanley" + }, + "id": "Stanley" + }, { + "geometry": { + "type": "Point", + "coordinates": [-57.667, -25.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Asunci%C3%B3n", + "city": "Asunci%C3%B3n" + }, + "id": "Asunci%C3%B3n" + }, { + "geometry": { + "type": "Point", + "coordinates": [-56.167, 46.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "Saint-Pierre,_Saint_Pierre_and_Miquelon", + "city": "Saint-Pierre" + }, + "id": "Saint-Pierre" + }, { + "geometry": { + "type": "Point", + "coordinates": [-56.167, -34.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Montevideo", + "city": "Montevideo" + }, + "id": "Montevideo" + }, { + "geometry": { + "type": "Point", + "coordinates": [-56.083, -15.583] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cuiab%C3%A1", + "city": "Cuiab%C3%A1" + }, + "id": "Cuiab%C3%A1" + }, { + "geometry": { + "type": "Point", + "coordinates": [-55.167, 5.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Paramaribo", + "city": "Paramaribo" + }, + "id": "Paramaribo" + }, { + "geometry": { + "type": "Point", + "coordinates": [-54.633, -20.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Campo_Grande", + "city": "Campo Grande" + }, + "id": "Campo Grande" + }, { + "geometry": { + "type": "Point", + "coordinates": [-54.617, -25.417] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ciudad_del_Este", + "city": "Ciudad del Este" + }, + "id": "Ciudad del Este" + }, { + "geometry": { + "type": "Point", + "coordinates": [-53.45, -33.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chu%C3%AD", + "city": "Chu%C3%AD" + }, + "id": "Chu%C3%AD" + }, { + "geometry": { + "type": "Point", + "coordinates": [-52.333, -31.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "Pelotas", + "city": "Pelotas" + }, + "id": "Pelotas" + }, { + "geometry": { + "type": "Point", + "coordinates": [-52.317, 4.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cayenne", + "city": "Cayenne" + }, + "id": "Cayenne" + }, { + "geometry": { + "type": "Point", + "coordinates": [-51.75, 64.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nuuk", + "city": "Nuuk" + }, + "id": "Nuuk" + }, { + "geometry": { + "type": "Point", + "coordinates": [-51.217, 30.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Porto_Alegre", + "city": "Porto Alegre" + }, + "id": "Porto Alegre" + }, { + "geometry": { + "type": "Point", + "coordinates": [-51.05, 0.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Macap%C3%A1", + "city": "Macap%C3%A1" + }, + "id": "Macap%C3%A1" + }, { + "geometry": { + "type": "Point", + "coordinates": [-50.4, -22.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Assis", + "city": "Assis" + }, + "id": "Assis" + }, { + "geometry": { + "type": "Point", + "coordinates": [-49.25, -25.417] + }, + "type": "Feature", + "properties": { + "wikipedia": "Curitiba", + "city": "Curitiba" + }, + "id": "Curitiba" + }, { + "geometry": { + "type": "Point", + "coordinates": [-48.483, 1.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bel%C3%A9m", + "city": "Bel%C3%A9m" + }, + "id": "Bel%C3%A9m" + }, { + "geometry": { + "type": "Point", + "coordinates": [-47.9, -15.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bras%C3%ADlia", + "city": "Bras%C3%ADlia" + }, + "id": "Bras%C3%ADlia" + }, { + "geometry": { + "type": "Point", + "coordinates": [-47.05, -22.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Campinas", + "city": "Campinas" + }, + "id": "Campinas" + }, { + "geometry": { + "type": "Point", + "coordinates": [-46.633, -23.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "S%C3%A3o_Paulo", + "city": "S%C3%A3o Paulo" + }, + "id": "S%C3%A3o Paulo" + }, { + "geometry": { + "type": "Point", + "coordinates": [-45.867, -23.183] + }, + "type": "Feature", + "properties": { + "wikipedia": "S%C3%A3o_Jos%C3%A9_dos_Campos", + "city": "S%C3%A3o Jos%C3%A9 dos Campos" + }, + "id": "S%C3%A3o Jos%C3%A9 dos Campos" + }, { + "geometry": { + "type": "Point", + "coordinates": [-43.233, -22.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Rio_de_Janeiro", + "city": "Rio de Janeiro" + }, + "id": "Rio de Janeiro" + }, { + "geometry": { + "type": "Point", + "coordinates": [-40.333, -20.317] + }, + "type": "Feature", + "properties": { + "wikipedia": "Vit%C3%B3ria,_Brazil", + "city": "Vit%C3%B3ria" + }, + "id": "Vit%C3%B3ria" + }, { + "geometry": { + "type": "Point", + "coordinates": [-39.05, -14.783] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ilh%C3%A9us", + "city": "Ilh%C3%A9us" + }, + "id": "Ilh%C3%A9us" + }, { + "geometry": { + "type": "Point", + "coordinates": [-38.567, -3.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "Fortaleza", + "city": "Fortaleza" + }, + "id": "Fortaleza" + }, { + "geometry": { + "type": "Point", + "coordinates": [-35.717, -9.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Macei%C3%B3", + "city": "Macei%C3%B3" + }, + "id": "Macei%C3%B3" + }, { + "geometry": { + "type": "Point", + "coordinates": [-34.867, -8.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Recife", + "city": "Recife" + }, + "id": "Recife" + }, { + "geometry": { + "type": "Point", + "coordinates": [-28.633, 38.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "Horta_(Azores)", + "city": "Horta (Azores)" + }, + "id": "Horta (Azores)" + }, { + "geometry": { + "type": "Point", + "coordinates": [-27.217, 38.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Angra_do_Hero%C3%ADsmo", + "city": "Angra do Hero%C3%ADsmo" + }, + "id": "Angra do Hero%C3%ADsmo" + }, { + "geometry": { + "type": "Point", + "coordinates": [-25.667, 37.733] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ponta_Delgada,_S%C3%A3o_Miguel_Island", + "city": "Ponta Delgada" + }, + "id": "Ponta Delgada" + }, { + "geometry": { + "type": "Point", + "coordinates": [-23.517, 14.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Praia", + "city": "Praia" + }, + "id": "Praia" + }, { + "geometry": { + "type": "Point", + "coordinates": [-21.933, 64.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Reykjav%C3%ADk", + "city": "Reykjav%C3%ADk" + }, + "id": "Reykjav%C3%ADk" + }, { + "geometry": { + "type": "Point", + "coordinates": [-17.433, 14.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dakar", + "city": "Dakar" + }, + "id": "Dakar" + }, { + "geometry": { + "type": "Point", + "coordinates": [-17.1, 14.833] + }, + "type": "Feature", + "properties": { + "wikipedia": "Thi%C3%A8s", + "city": "Thi%C3%A8s" + }, + "id": "Thi%C3%A8s" + }, { + "geometry": { + "type": "Point", + "coordinates": [-16.667, 13.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Serekunda", + "city": "Serekunda" + }, + "id": "Serekunda" + }, { + "geometry": { + "type": "Point", + "coordinates": [-16.65, 13.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Brikama", + "city": "Brikama" + }, + "id": "Brikama" + }, { + "geometry": { + "type": "Point", + "coordinates": [-16.567, 13.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Banjul", + "city": "Banjul" + }, + "id": "Banjul" + }, { + "geometry": { + "type": "Point", + "coordinates": [-16.25, 28.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Santa_Cruz_de_Tenerife", + "city": "Santa Cruz de Tenerife" + }, + "id": "Santa Cruz de Tenerife" + }, { + "geometry": { + "type": "Point", + "coordinates": [-15.95, 18.1] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nouakchott", + "city": "Nouakchott" + }, + "id": "Nouakchott" + }, { + "geometry": { + "type": "Point", + "coordinates": [-15.583, 11.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bissau", + "city": "Bissau" + }, + "id": "Bissau" + }, { + "geometry": { + "type": "Point", + "coordinates": [-15.433, 28.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Las_Palmas_de_Gran_Canaria", + "city": "Las Palmas de Gran Canaria" + }, + "id": "Las Palmas de Gran Canaria" + }, { + "geometry": { + "type": "Point", + "coordinates": [-13.7, 9.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Conakry", + "city": "Conakry" + }, + "id": "Conakry" + }, { + "geometry": { + "type": "Point", + "coordinates": [-13.267, 8.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Freetown", + "city": "Freetown" + }, + "id": "Freetown" + }, { + "geometry": { + "type": "Point", + "coordinates": [-13.2, 27.15] + }, + "type": "Feature", + "properties": { + "wikipedia": "El_Aai%C3%BAn", + "city": "El Aai%C3%BAn" + }, + "id": "El Aai%C3%BAn" + }, { + "geometry": { + "type": "Point", + "coordinates": [-10.767, 6.317] + }, + "type": "Feature", + "properties": { + "wikipedia": "Monrovia", + "city": "Monrovia" + }, + "id": "Monrovia" + }, { + "geometry": { + "type": "Point", + "coordinates": [-9.183, 38.7] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lisbon", + "city": "Lisbon" + }, + "id": "Lisbon" + }, { + "geometry": { + "type": "Point", + "coordinates": [-8.633, 41.15] + }, + "type": "Feature", + "properties": { + "wikipedia": "Porto", + "city": "Porto" + }, + "id": "Porto" + }, { + "geometry": { + "type": "Point", + "coordinates": [-8.467, 51.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cork_(city)", + "city": "Cork (city)" + }, + "id": "Cork (city)" + }, { + "geometry": { + "type": "Point", + "coordinates": [-8, 31.633] + }, + "type": "Feature", + "properties": { + "wikipedia": "Marrakech", + "city": "Marrakech" + }, + "id": "Marrakech" + }, { + "geometry": { + "type": "Point", + "coordinates": [-8, 12.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bamako", + "city": "Bamako" + }, + "id": "Bamako" + }, { + "geometry": { + "type": "Point", + "coordinates": [-7.583, 33.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "Casablanca", + "city": "Casablanca" + }, + "id": "Casablanca" + }, { + "geometry": { + "type": "Point", + "coordinates": [-7.567, 12.983] + }, + "type": "Feature", + "properties": { + "wikipedia": "Koulikoro", + "city": "Koulikoro" + }, + "id": "Koulikoro" + }, { + "geometry": { + "type": "Point", + "coordinates": [-6.833, 34.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Rabat", + "city": "Rabat" + }, + "id": "Rabat" + }, { + "geometry": { + "type": "Point", + "coordinates": [-6.783, 62] + }, + "type": "Feature", + "properties": { + "wikipedia": "T%C3%B3rshavn", + "city": "T%C3%B3rshavn" + }, + "id": "T%C3%B3rshavn" + }, { + "geometry": { + "type": "Point", + "coordinates": [-6.267, 53.333] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dublin", + "city": "Dublin" + }, + "id": "Dublin" + }, { + "geometry": { + "type": "Point", + "coordinates": [-5.983, 37.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Seville", + "city": "Seville" + }, + "id": "Seville" + }, { + "geometry": { + "type": "Point", + "coordinates": [-5.917, 54.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Belfast", + "city": "Belfast" + }, + "id": "Belfast" + }, { + "geometry": { + "type": "Point", + "coordinates": [-5.733, -15.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Jamestown,_Saint_Helena", + "city": "Jamestown" + }, + "id": "Jamestown" + }, { + "geometry": { + "type": "Point", + "coordinates": [-5.35, 36.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Gibraltar", + "city": "Gibraltar" + }, + "id": "Gibraltar" + }, { + "geometry": { + "type": "Point", + "coordinates": [-5.283, 6.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Yamoussoukro", + "city": "Yamoussoukro" + }, + "id": "Yamoussoukro" + }, { + "geometry": { + "type": "Point", + "coordinates": [-4.483, 54.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Douglas,_Isle_of_Man", + "city": "Douglas" + }, + "id": "Douglas" + }, { + "geometry": { + "type": "Point", + "coordinates": [-4.417, 36.717] + }, + "type": "Feature", + "properties": { + "wikipedia": "M%C3%A1laga", + "city": "M%C3%A1laga" + }, + "id": "M%C3%A1laga" + }, { + "geometry": { + "type": "Point", + "coordinates": [-4.25, 55.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Glasgow", + "city": "Glasgow" + }, + "id": "Glasgow" + }, { + "geometry": { + "type": "Point", + "coordinates": [-4.017, 5.333] + }, + "type": "Feature", + "properties": { + "wikipedia": "Abidjan", + "city": "Abidjan" + }, + "id": "Abidjan" + }, { + "geometry": { + "type": "Point", + "coordinates": [-3.683, 40.4] + }, + "type": "Feature", + "properties": { + "wikipedia": "Madrid", + "city": "Madrid" + }, + "id": "Madrid" + }, { + "geometry": { + "type": "Point", + "coordinates": [-3.183, 51.483] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cardiff", + "city": "Cardiff" + }, + "id": "Cardiff" + }, { + "geometry": { + "type": "Point", + "coordinates": [-3.15, 55.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Edinburgh", + "city": "Edinburgh" + }, + "id": "Edinburgh" + }, { + "geometry": { + "type": "Point", + "coordinates": [-3, 16.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "Timbuktu", + "city": "Timbuktu" + }, + "id": "Timbuktu" + }, { + "geometry": { + "type": "Point", + "coordinates": [-2.983, 53.4] + }, + "type": "Feature", + "properties": { + "wikipedia": "Liverpool", + "city": "Liverpool" + }, + "id": "Liverpool" + }, { + "geometry": { + "type": "Point", + "coordinates": [-2.917, 43.25] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bilbao", + "city": "Bilbao" + }, + "id": "Bilbao" + }, { + "geometry": { + "type": "Point", + "coordinates": [-2.233, 53.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Manchester", + "city": "Manchester" + }, + "id": "Manchester" + }, { + "geometry": { + "type": "Point", + "coordinates": [-2.1, 57.15] + }, + "type": "Feature", + "properties": { + "wikipedia": "Aberdeen", + "city": "Aberdeen" + }, + "id": "Aberdeen" + }, { + "geometry": { + "type": "Point", + "coordinates": [-1.883, 52.483] + }, + "type": "Feature", + "properties": { + "wikipedia": "Birmingham", + "city": "Birmingham" + }, + "id": "Birmingham" + }, { + "geometry": { + "type": "Point", + "coordinates": [-1.55, 53.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Leeds", + "city": "Leeds" + }, + "id": "Leeds" + }, { + "geometry": { + "type": "Point", + "coordinates": [-1.55, 47.217] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nantes", + "city": "Nantes" + }, + "id": "Nantes" + }, { + "geometry": { + "type": "Point", + "coordinates": [-1.533, 12.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ouagadougou", + "city": "Ouagadougou" + }, + "id": "Ouagadougou" + }, { + "geometry": { + "type": "Point", + "coordinates": [-0.85, 9.4] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tamale,_Ghana", + "city": "Tamale" + }, + "id": "Tamale" + }, { + "geometry": { + "type": "Point", + "coordinates": [-0.367, 39.483] + }, + "type": "Feature", + "properties": { + "wikipedia": "Valencia,_Spain", + "city": "Valencia" + }, + "id": "Valencia" + }, { + "geometry": { + "type": "Point", + "coordinates": [-0.2, 5.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Accra", + "city": "Accra" + }, + "id": "Accra" + }, { + "geometry": { + "type": "Point", + "coordinates": [-0.117, 51.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "London", + "city": "London" + }, + "id": "London" + }, { + "geometry": { + "type": "Point", + "coordinates": [0, 51.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Greenwich", + "city": "Greenwich" + }, + "id": "Greenwich" + }, { + "geometry": { + "type": "Point", + "coordinates": [1.2, 6.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lom%C3%A9", + "city": "Lom%C3%A9" + }, + "id": "Lom%C3%A9" + }, { + "geometry": { + "type": "Point", + "coordinates": [1.433, 43.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Toulouse", + "city": "Toulouse" + }, + "id": "Toulouse" + }, { + "geometry": { + "type": "Point", + "coordinates": [1.5, 42.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Andorra_la_Vella", + "city": "Andorra la Vella" + }, + "id": "Andorra la Vella" + }, { + "geometry": { + "type": "Point", + "coordinates": [1.717, 39.633] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ibiza", + "city": "Ibiza" + }, + "id": "Ibiza" + }, { + "geometry": { + "type": "Point", + "coordinates": [2.1, 13.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Niamey", + "city": "Niamey" + }, + "id": "Niamey" + }, { + "geometry": { + "type": "Point", + "coordinates": [2.183, 41.383] + }, + "type": "Feature", + "properties": { + "wikipedia": "Barcelona", + "city": "Barcelona" + }, + "id": "Barcelona" + }, { + "geometry": { + "type": "Point", + "coordinates": [2.333, 48.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Paris", + "city": "Paris" + }, + "id": "Paris" + }, { + "geometry": { + "type": "Point", + "coordinates": [2.417, 6.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cotonou", + "city": "Cotonou" + }, + "id": "Cotonou" + }, { + "geometry": { + "type": "Point", + "coordinates": [2.6, 6.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Porto-Novo", + "city": "Porto-Novo" + }, + "id": "Porto-Novo" + }, { + "geometry": { + "type": "Point", + "coordinates": [2.65, 39.567] + }, + "type": "Feature", + "properties": { + "wikipedia": "Palma,_Majorca", + "city": "Palma" + }, + "id": "Palma" + }, { + "geometry": { + "type": "Point", + "coordinates": [3.217, 36.7] + }, + "type": "Feature", + "properties": { + "wikipedia": "Algiers", + "city": "Algiers" + }, + "id": "Algiers" + }, { + "geometry": { + "type": "Point", + "coordinates": [3.383, 6.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lagos", + "city": "Lagos" + }, + "id": "Lagos" + }, { + "geometry": { + "type": "Point", + "coordinates": [3.883, 7.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ibadan", + "city": "Ibadan" + }, + "id": "Ibadan" + }, { + "geometry": { + "type": "Point", + "coordinates": [4.3, 52.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "The_Hague", + "city": "The Hague" + }, + "id": "The Hague" + }, { + "geometry": { + "type": "Point", + "coordinates": [4.35, 50.833] + }, + "type": "Feature", + "properties": { + "wikipedia": "Brussels", + "city": "Brussels" + }, + "id": "Brussels" + }, { + "geometry": { + "type": "Point", + "coordinates": [4.4, 51.217] + }, + "type": "Feature", + "properties": { + "wikipedia": "Antwerp", + "city": "Antwerp" + }, + "id": "Antwerp" + }, { + "geometry": { + "type": "Point", + "coordinates": [4.467, 51.933] + }, + "type": "Feature", + "properties": { + "wikipedia": "Rotterdam", + "city": "Rotterdam" + }, + "id": "Rotterdam" + }, { + "geometry": { + "type": "Point", + "coordinates": [4.833, 45.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lyon", + "city": "Lyon" + }, + "id": "Lyon" + }, { + "geometry": { + "type": "Point", + "coordinates": [4.883, 52.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Amsterdam", + "city": "Amsterdam" + }, + "id": "Amsterdam" + }, { + "geometry": { + "type": "Point", + "coordinates": [5.367, 43.3] + }, + "type": "Feature", + "properties": { + "wikipedia": "Marseille", + "city": "Marseille" + }, + "id": "Marseille" + }, { + "geometry": { + "type": "Point", + "coordinates": [5.4, 60.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bergen", + "city": "Bergen" + }, + "id": "Bergen" + }, { + "geometry": { + "type": "Point", + "coordinates": [6.117, 49.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Luxembourg_(city)", + "city": "Luxembourg (city)" + }, + "id": "Luxembourg (city)" + }, { + "geometry": { + "type": "Point", + "coordinates": [6.15, 46.2] + }, + "type": "Feature", + "properties": { + "wikipedia": "Geneva", + "city": "Geneva" + }, + "id": "Geneva" + }, { + "geometry": { + "type": "Point", + "coordinates": [6.683, 0.333] + }, + "type": "Feature", + "properties": { + "wikipedia": "S%C3%A3o_Tom%C3%A9", + "city": "S%C3%A3o Tom%C3%A9" + }, + "id": "S%C3%A3o Tom%C3%A9" + }, { + "geometry": { + "type": "Point", + "coordinates": [6.783, 51.233] + }, + "type": "Feature", + "properties": { + "wikipedia": "D%C3%BCsseldorf", + "city": "D%C3%BCsseldorf" + }, + "id": "D%C3%BCsseldorf" + }, { + "geometry": { + "type": "Point", + "coordinates": [6.967, 50.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cologne", + "city": "Cologne" + }, + "id": "Cologne" + }, { + "geometry": { + "type": "Point", + "coordinates": [7, 43.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cannes", + "city": "Cannes" + }, + "id": "Cannes" + }, { + "geometry": { + "type": "Point", + "coordinates": [7.267, 43.7] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nice", + "city": "Nice" + }, + "id": "Nice" + }, { + "geometry": { + "type": "Point", + "coordinates": [7.4, 43.733] + }, + "type": "Feature", + "properties": { + "wikipedia": "Monaco", + "city": "Monaco" + }, + "id": "Monaco" + }, { + "geometry": { + "type": "Point", + "coordinates": [7.45, 46.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bern", + "city": "Bern" + }, + "id": "Bern" + }, { + "geometry": { + "type": "Point", + "coordinates": [7.483, 9.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Abuja", + "city": "Abuja" + }, + "id": "Abuja" + }, { + "geometry": { + "type": "Point", + "coordinates": [7.5, 6.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Enugu", + "city": "Enugu" + }, + "id": "Enugu" + }, { + "geometry": { + "type": "Point", + "coordinates": [7.7, 45.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Turin", + "city": "Turin" + }, + "id": "Turin" + }, { + "geometry": { + "type": "Point", + "coordinates": [7.75, 48.583] + }, + "type": "Feature", + "properties": { + "wikipedia": "Strasbourg", + "city": "Strasbourg" + }, + "id": "Strasbourg" + }, { + "geometry": { + "type": "Point", + "coordinates": [8.517, 12] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kano", + "city": "Kano" + }, + "id": "Kano" + }, { + "geometry": { + "type": "Point", + "coordinates": [8.55, 47.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Z%C3%BCrich", + "city": "Z%C3%BCrich" + }, + "id": "Z%C3%BCrich" + }, { + "geometry": { + "type": "Point", + "coordinates": [8.683, 50.1] + }, + "type": "Feature", + "properties": { + "wikipedia": "Frankfurt", + "city": "Frankfurt" + }, + "id": "Frankfurt" + }, { + "geometry": { + "type": "Point", + "coordinates": [8.767, 3.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Malabo", + "city": "Malabo" + }, + "id": "Malabo" + }, { + "geometry": { + "type": "Point", + "coordinates": [9.167, 48.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "Stuttgart", + "city": "Stuttgart" + }, + "id": "Stuttgart" + }, { + "geometry": { + "type": "Point", + "coordinates": [9.183, 45.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Milan", + "city": "Milan" + }, + "id": "Milan" + }, { + "geometry": { + "type": "Point", + "coordinates": [9.45, 0.383] + }, + "type": "Feature", + "properties": { + "wikipedia": "Libreville", + "city": "Libreville" + }, + "id": "Libreville" + }, { + "geometry": { + "type": "Point", + "coordinates": [9.517, 47.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Vaduz", + "city": "Vaduz" + }, + "id": "Vaduz" + }, { + "geometry": { + "type": "Point", + "coordinates": [9.7, 4.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Douala", + "city": "Douala" + }, + "id": "Douala" + }, { + "geometry": { + "type": "Point", + "coordinates": [9.717, 52.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hanover", + "city": "Hanover" + }, + "id": "Hanover" + }, { + "geometry": { + "type": "Point", + "coordinates": [9.983, 53.583] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hamburg", + "city": "Hamburg" + }, + "id": "Hamburg" + }, { + "geometry": { + "type": "Point", + "coordinates": [10.167, 36.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tunis", + "city": "Tunis" + }, + "id": "Tunis" + }, { + "geometry": { + "type": "Point", + "coordinates": [10.2, 56.15] + }, + "type": "Feature", + "properties": { + "wikipedia": "Aarhus", + "city": "Aarhus" + }, + "id": "Aarhus" + }, { + "geometry": { + "type": "Point", + "coordinates": [10.75, 59.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Oslo", + "city": "Oslo" + }, + "id": "Oslo" + }, { + "geometry": { + "type": "Point", + "coordinates": [11.383, 47.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Innsbruck", + "city": "Innsbruck" + }, + "id": "Innsbruck" + }, { + "geometry": { + "type": "Point", + "coordinates": [11.517, 3.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Yaound%C3%A9", + "city": "Yaound%C3%A9" + }, + "id": "Yaound%C3%A9" + }, { + "geometry": { + "type": "Point", + "coordinates": [11.567, 48.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Munich", + "city": "Munich" + }, + "id": "Munich" + }, { + "geometry": { + "type": "Point", + "coordinates": [11.967, 57.7] + }, + "type": "Feature", + "properties": { + "wikipedia": "Gothenburg", + "city": "Gothenburg" + }, + "id": "Gothenburg" + }, { + "geometry": { + "type": "Point", + "coordinates": [12.383, 51.333] + }, + "type": "Feature", + "properties": { + "wikipedia": "Leipzig", + "city": "Leipzig" + }, + "id": "Leipzig" + }, { + "geometry": { + "type": "Point", + "coordinates": [12.433, 43.933] + }, + "type": "Feature", + "properties": { + "wikipedia": "City_of_San_Marino", + "city": "City of San Marino" + }, + "id": "City of San Marino" + }, { + "geometry": { + "type": "Point", + "coordinates": [12.45, 41.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Vatican_City", + "city": "Vatican City" + }, + "id": "Vatican City" + }, { + "geometry": { + "type": "Point", + "coordinates": [12.5, 41.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Rome", + "city": "Rome" + }, + "id": "Rome" + }, { + "geometry": { + "type": "Point", + "coordinates": [12.567, 55.667] + }, + "type": "Feature", + "properties": { + "wikipedia": "Copenhagen", + "city": "Copenhagen" + }, + "id": "Copenhagen" + }, { + "geometry": { + "type": "Point", + "coordinates": [13.033, 55.583] + }, + "type": "Feature", + "properties": { + "wikipedia": "Malm%C3%B6", + "city": "Malm%C3%B6" + }, + "id": "Malm%C3%B6" + }, { + "geometry": { + "type": "Point", + "coordinates": [13.033, 47.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Salzburg", + "city": "Salzburg" + }, + "id": "Salzburg" + }, { + "geometry": { + "type": "Point", + "coordinates": [13.183, 32.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tripoli", + "city": "Tripoli" + }, + "id": "Tripoli" + }, { + "geometry": { + "type": "Point", + "coordinates": [13.233, -8.833] + }, + "type": "Feature", + "properties": { + "wikipedia": "Luanda", + "city": "Luanda" + }, + "id": "Luanda" + }, { + "geometry": { + "type": "Point", + "coordinates": [13.417, 52.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Berlin", + "city": "Berlin" + }, + "id": "Berlin" + }, { + "geometry": { + "type": "Point", + "coordinates": [13.733, 51.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dresden", + "city": "Dresden" + }, + "id": "Dresden" + }, { + "geometry": { + "type": "Point", + "coordinates": [14.25, 40.833] + }, + "type": "Feature", + "properties": { + "wikipedia": "Naples", + "city": "Naples" + }, + "id": "Naples" + }, { + "geometry": { + "type": "Point", + "coordinates": [14.283, 48.3] + }, + "type": "Feature", + "properties": { + "wikipedia": "Linz", + "city": "Linz" + }, + "id": "Linz" + }, { + "geometry": { + "type": "Point", + "coordinates": [14.417, 50.083] + }, + "type": "Feature", + "properties": { + "wikipedia": "Prague", + "city": "Prague" + }, + "id": "Prague" + }, { + "geometry": { + "type": "Point", + "coordinates": [14.433, 27.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sabha,_Libya", + "city": "Sabha" + }, + "id": "Sabha" + }, { + "geometry": { + "type": "Point", + "coordinates": [14.45, 35.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Birkirkara", + "city": "Birkirkara" + }, + "id": "Birkirkara" + }, { + "geometry": { + "type": "Point", + "coordinates": [14.5, 46.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ljubljana", + "city": "Ljubljana" + }, + "id": "Ljubljana" + }, { + "geometry": { + "type": "Point", + "coordinates": [14.5, 35.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Valletta", + "city": "Valletta" + }, + "id": "Valletta" + }, { + "geometry": { + "type": "Point", + "coordinates": [15.05, 12.1] + }, + "type": "Feature", + "properties": { + "wikipedia": "N%27Djamena", + "city": "N%27Djamena" + }, + "id": "N%27Djamena" + }, { + "geometry": { + "type": "Point", + "coordinates": [15.283, -4.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Brazzaville", + "city": "Brazzaville" + }, + "id": "Brazzaville" + }, { + "geometry": { + "type": "Point", + "coordinates": [15.317, -4.317] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kinshasa", + "city": "Kinshasa" + }, + "id": "Kinshasa" + }, { + "geometry": { + "type": "Point", + "coordinates": [15.433, 47.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Graz", + "city": "Graz" + }, + "id": "Graz" + }, { + "geometry": { + "type": "Point", + "coordinates": [15.55, 78.217] + }, + "type": "Feature", + "properties": { + "wikipedia": "Longyearbyen", + "city": "Longyearbyen" + }, + "id": "Longyearbyen" + }, { + "geometry": { + "type": "Point", + "coordinates": [15.983, 45.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Zagreb", + "city": "Zagreb" + }, + "id": "Zagreb" + }, { + "geometry": { + "type": "Point", + "coordinates": [16.367, 48.2] + }, + "type": "Feature", + "properties": { + "wikipedia": "Vienna", + "city": "Vienna" + }, + "id": "Vienna" + }, { + "geometry": { + "type": "Point", + "coordinates": [16.433, 43.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Split_(city)", + "city": "Split (city)" + }, + "id": "Split (city)" + }, { + "geometry": { + "type": "Point", + "coordinates": [17.1, 48.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bratislava", + "city": "Bratislava" + }, + "id": "Bratislava" + }, { + "geometry": { + "type": "Point", + "coordinates": [18.067, 59.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Stockholm", + "city": "Stockholm" + }, + "id": "Stockholm" + }, { + "geometry": { + "type": "Point", + "coordinates": [18.35, 43.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sarajevo", + "city": "Sarajevo" + }, + "id": "Sarajevo" + }, { + "geometry": { + "type": "Point", + "coordinates": [18.417, -33.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cape_Town", + "city": "Cape Town" + }, + "id": "Cape Town" + }, { + "geometry": { + "type": "Point", + "coordinates": [18.583, 4.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bangui", + "city": "Bangui" + }, + "id": "Bangui" + }, { + "geometry": { + "type": "Point", + "coordinates": [18.667, 54.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Gda%C5%84sk", + "city": "Gda%C5%84sk" + }, + "id": "Gda%C5%84sk" + }, { + "geometry": { + "type": "Point", + "coordinates": [19.05, 47.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Budapest", + "city": "Budapest" + }, + "id": "Budapest" + }, { + "geometry": { + "type": "Point", + "coordinates": [19.267, 42.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Podgorica", + "city": "Podgorica" + }, + "id": "Podgorica" + }, { + "geometry": { + "type": "Point", + "coordinates": [19.817, 41.317] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tirana", + "city": "Tirana" + }, + "id": "Tirana" + }, { + "geometry": { + "type": "Point", + "coordinates": [19.933, 50.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Krak%C3%B3w", + "city": "Krak%C3%B3w" + }, + "id": "Krak%C3%B3w" + }, { + "geometry": { + "type": "Point", + "coordinates": [20.45, 44.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Belgrade", + "city": "Belgrade" + }, + "id": "Belgrade" + }, { + "geometry": { + "type": "Point", + "coordinates": [20.517, 54.717] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kaliningrad", + "city": "Kaliningrad" + }, + "id": "Kaliningrad" + }, { + "geometry": { + "type": "Point", + "coordinates": [21, 52.233] + }, + "type": "Feature", + "properties": { + "wikipedia": "Warsaw", + "city": "Warsaw" + }, + "id": "Warsaw" + }, { + "geometry": { + "type": "Point", + "coordinates": [21.167, 42.667] + }, + "type": "Feature", + "properties": { + "wikipedia": "Pristina", + "city": "Pristina" + }, + "id": "Pristina" + }, { + "geometry": { + "type": "Point", + "coordinates": [21.433, 42] + }, + "type": "Feature", + "properties": { + "wikipedia": "Skopje", + "city": "Skopje" + }, + "id": "Skopje" + }, { + "geometry": { + "type": "Point", + "coordinates": [22.95, 40.633] + }, + "type": "Feature", + "properties": { + "wikipedia": "Thessaloniki", + "city": "Thessaloniki" + }, + "id": "Thessaloniki" + }, { + "geometry": { + "type": "Point", + "coordinates": [23.333, 42.7] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sofia", + "city": "Sofia" + }, + "id": "Sofia" + }, { + "geometry": { + "type": "Point", + "coordinates": [23.717, 37.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Athens", + "city": "Athens" + }, + "id": "Athens" + }, { + "geometry": { + "type": "Point", + "coordinates": [23.75, 61.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tampere", + "city": "Tampere" + }, + "id": "Tampere" + }, { + "geometry": { + "type": "Point", + "coordinates": [24.017, 49.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lviv", + "city": "Lviv" + }, + "id": "Lviv" + }, { + "geometry": { + "type": "Point", + "coordinates": [24.133, 56.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Riga", + "city": "Riga" + }, + "id": "Riga" + }, { + "geometry": { + "type": "Point", + "coordinates": [24.65, 60.2] + }, + "type": "Feature", + "properties": { + "wikipedia": "Espoo", + "city": "Espoo" + }, + "id": "Espoo" + }, { + "geometry": { + "type": "Point", + "coordinates": [24.75, 59.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tallinn", + "city": "Tallinn" + }, + "id": "Tallinn" + }, { + "geometry": { + "type": "Point", + "coordinates": [24.933, 60.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Helsinki", + "city": "Helsinki" + }, + "id": "Helsinki" + }, { + "geometry": { + "type": "Point", + "coordinates": [25.283, 54.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Vilnius", + "city": "Vilnius" + }, + "id": "Vilnius" + }, { + "geometry": { + "type": "Point", + "coordinates": [25.6, -33.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Port_Elizabeth", + "city": "Port Elizabeth" + }, + "id": "Port Elizabeth" + }, { + "geometry": { + "type": "Point", + "coordinates": [25.867, -17.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Livingstone,_Zambia", + "city": "Livingstone" + }, + "id": "Livingstone" + }, { + "geometry": { + "type": "Point", + "coordinates": [25.9, -24.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Gaborone", + "city": "Gaborone" + }, + "id": "Gaborone" + }, { + "geometry": { + "type": "Point", + "coordinates": [26.1, 44.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bucharest", + "city": "Bucharest" + }, + "id": "Bucharest" + }, { + "geometry": { + "type": "Point", + "coordinates": [26.217, -29.1] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bloemfontein", + "city": "Bloemfontein" + }, + "id": "Bloemfontein" + }, { + "geometry": { + "type": "Point", + "coordinates": [26.717, 58.383] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tartu", + "city": "Tartu" + }, + "id": "Tartu" + }, { + "geometry": { + "type": "Point", + "coordinates": [27.15, 38.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "%C4%B0zmir", + "city": "%C4%B0zmir" + }, + "id": "%C4%B0zmir" + }, { + "geometry": { + "type": "Point", + "coordinates": [27.467, -11.667] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lubumbashi", + "city": "Lubumbashi" + }, + "id": "Lubumbashi" + }, { + "geometry": { + "type": "Point", + "coordinates": [27.467, -29.3] + }, + "type": "Feature", + "properties": { + "wikipedia": "Maseru", + "city": "Maseru" + }, + "id": "Maseru" + }, { + "geometry": { + "type": "Point", + "coordinates": [27.5, -21.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Francistown", + "city": "Francistown" + }, + "id": "Francistown" + }, { + "geometry": { + "type": "Point", + "coordinates": [27.567, 53.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Minsk", + "city": "Minsk" + }, + "id": "Minsk" + }, { + "geometry": { + "type": "Point", + "coordinates": [28.033, -26.2] + }, + "type": "Feature", + "properties": { + "wikipedia": "Johannesburg", + "city": "Johannesburg" + }, + "id": "Johannesburg" + }, { + "geometry": { + "type": "Point", + "coordinates": [28.183, -25.733] + }, + "type": "Feature", + "properties": { + "wikipedia": "Pretoria", + "city": "Pretoria" + }, + "id": "Pretoria" + }, { + "geometry": { + "type": "Point", + "coordinates": [28.283, -15.417] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lusaka", + "city": "Lusaka" + }, + "id": "Lusaka" + }, { + "geometry": { + "type": "Point", + "coordinates": [28.633, -12.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ndola", + "city": "Ndola" + }, + "id": "Ndola" + }, { + "geometry": { + "type": "Point", + "coordinates": [28.567, -20.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bulawayo", + "city": "Bulawayo" + }, + "id": "Bulawayo" + }, { + "geometry": { + "type": "Point", + "coordinates": [28.867, 47] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chi%C5%9Fin%C4%83u", + "city": "Chi%C5%9Fin%C4%83u" + }, + "id": "Chi%C5%9Fin%C4%83u" + }, { + "geometry": { + "type": "Point", + "coordinates": [28.967, 41] + }, + "type": "Feature", + "properties": { + "wikipedia": "Istanbul", + "city": "Istanbul" + }, + "id": "Istanbul" + }, { + "geometry": { + "type": "Point", + "coordinates": [29.067, 40.183] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bursa", + "city": "Bursa" + }, + "id": "Bursa" + }, { + "geometry": { + "type": "Point", + "coordinates": [29.367, -3.383] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bujumbura", + "city": "Bujumbura" + }, + "id": "Bujumbura" + }, { + "geometry": { + "type": "Point", + "coordinates": [29.633, 46.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tiraspol", + "city": "Tiraspol" + }, + "id": "Tiraspol" + }, { + "geometry": { + "type": "Point", + "coordinates": [29.917, 31.2] + }, + "type": "Feature", + "properties": { + "wikipedia": "Alexandria", + "city": "Alexandria" + }, + "id": "Alexandria" + }, { + "geometry": { + "type": "Point", + "coordinates": [30.05, -1.933] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kigali", + "city": "Kigali" + }, + "id": "Kigali" + }, { + "geometry": { + "type": "Point", + "coordinates": [30.333, 59.933] + }, + "type": "Feature", + "properties": { + "wikipedia": "Saint_Petersburg", + "city": "Saint Petersburg" + }, + "id": "Saint Petersburg" + }, { + "geometry": { + "type": "Point", + "coordinates": [30.517, 50.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kiev", + "city": "Kiev" + }, + "id": "Kiev" + }, { + "geometry": { + "type": "Point", + "coordinates": [30.733, 46.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Odessa", + "city": "Odessa" + }, + "id": "Odessa" + }, { + "geometry": { + "type": "Point", + "coordinates": [31.05, -17.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Harare", + "city": "Harare" + }, + "id": "Harare" + }, { + "geometry": { + "type": "Point", + "coordinates": [31.05, -29.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Durban", + "city": "Durban" + }, + "id": "Durban" + }, { + "geometry": { + "type": "Point", + "coordinates": [31.133, -26.317] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mbabane", + "city": "Mbabane" + }, + "id": "Mbabane" + }, { + "geometry": { + "type": "Point", + "coordinates": [31.2, -26.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lobamba", + "city": "Lobamba" + }, + "id": "Lobamba" + }, { + "geometry": { + "type": "Point", + "coordinates": [31.217, 30.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cairo", + "city": "Cairo" + }, + "id": "Cairo" + }, { + "geometry": { + "type": "Point", + "coordinates": [31.367, -26.483] + }, + "type": "Feature", + "properties": { + "wikipedia": "Manzini,_Swaziland", + "city": "Manzini" + }, + "id": "Manzini" + }, { + "geometry": { + "type": "Point", + "coordinates": [32.283, 31.25] + }, + "type": "Feature", + "properties": { + "wikipedia": "Port_Said", + "city": "Port Said" + }, + "id": "Port Said" + }, { + "geometry": { + "type": "Point", + "coordinates": [32.483, 37.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Konya", + "city": "Konya" + }, + "id": "Konya" + }, { + "geometry": { + "type": "Point", + "coordinates": [32.483, 15.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Omdurman", + "city": "Omdurman" + }, + "id": "Omdurman" + }, { + "geometry": { + "type": "Point", + "coordinates": [32.533, 15.633] + }, + "type": "Feature", + "properties": { + "wikipedia": "Khartoum", + "city": "Khartoum" + }, + "id": "Khartoum" + }, { + "geometry": { + "type": "Point", + "coordinates": [32.55, 29.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Suez", + "city": "Suez" + }, + "id": "Suez" + }, { + "geometry": { + "type": "Point", + "coordinates": [32.583, -25.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Maputo", + "city": "Maputo" + }, + "id": "Maputo" + }, { + "geometry": { + "type": "Point", + "coordinates": [32.65, 25.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Luxor", + "city": "Luxor" + }, + "id": "Luxor" + }, { + "geometry": { + "type": "Point", + "coordinates": [32.833, 39.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ankara", + "city": "Ankara" + }, + "id": "Ankara" + }, { + "geometry": { + "type": "Point", + "coordinates": [32.9, -2.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mwanza", + "city": "Mwanza" + }, + "id": "Mwanza" + }, { + "geometry": { + "type": "Point", + "coordinates": [33.083, 68.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Murmansk", + "city": "Murmansk" + }, + "id": "Murmansk" + }, { + "geometry": { + "type": "Point", + "coordinates": [33.35, 35.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nicosia", + "city": "Nicosia" + }, + "id": "Nicosia" + }, { + "geometry": { + "type": "Point", + "coordinates": [33.783, -13.983] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lilongwe", + "city": "Lilongwe" + }, + "id": "Lilongwe" + }, { + "geometry": { + "type": "Point", + "coordinates": [34.1, 44.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Simferopol", + "city": "Simferopol" + }, + "id": "Simferopol" + }, { + "geometry": { + "type": "Point", + "coordinates": [34.45, 31.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Gaza", + "city": "Gaza" + }, + "id": "Gaza" + }, { + "geometry": { + "type": "Point", + "coordinates": [34.633, 36.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mersin", + "city": "Mersin" + }, + "id": "Mersin" + }, { + "geometry": { + "type": "Point", + "coordinates": [34.8, 32.083] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tel_Aviv", + "city": "Tel Aviv" + }, + "id": "Tel Aviv" + }, { + "geometry": { + "type": "Point", + "coordinates": [35, -15.783] + }, + "type": "Feature", + "properties": { + "wikipedia": "Blantyre,_Malawi", + "city": "Blantyre" + }, + "id": "Blantyre" + }, { + "geometry": { + "type": "Point", + "coordinates": [35.217, 31.783] + }, + "type": "Feature", + "properties": { + "wikipedia": "Jerusalem", + "city": "Jerusalem" + }, + "id": "Jerusalem" + }, { + "geometry": { + "type": "Point", + "coordinates": [35.317, 37] + }, + "type": "Feature", + "properties": { + "wikipedia": "Adana", + "city": "Adana" + }, + "id": "Adana" + }, { + "geometry": { + "type": "Point", + "coordinates": [35.5, 33.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Beirut", + "city": "Beirut" + }, + "id": "Beirut" + }, { + "geometry": { + "type": "Point", + "coordinates": [35.733, -6.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dodoma", + "city": "Dodoma" + }, + "id": "Dodoma" + }, { + "geometry": { + "type": "Point", + "coordinates": [35.933, 31.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Amman", + "city": "Amman" + }, + "id": "Amman" + }, { + "geometry": { + "type": "Point", + "coordinates": [36.283, 33.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Damascus", + "city": "Damascus" + }, + "id": "Damascus" + }, { + "geometry": { + "type": "Point", + "coordinates": [36.317, 49.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kharkiv", + "city": "Kharkiv" + }, + "id": "Kharkiv" + }, { + "geometry": { + "type": "Point", + "coordinates": [36.817, -1.283] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nairobi", + "city": "Nairobi" + }, + "id": "Nairobi" + }, { + "geometry": { + "type": "Point", + "coordinates": [37.383, 37.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Gaziantep", + "city": "Gaziantep" + }, + "id": "Gaziantep" + }, { + "geometry": { + "type": "Point", + "coordinates": [37.6, 55.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Moscow", + "city": "Moscow" + }, + "id": "Moscow" + }, { + "geometry": { + "type": "Point", + "coordinates": [38.733, 9.017] + }, + "type": "Feature", + "properties": { + "wikipedia": "Addis_Ababa", + "city": "Addis Ababa" + }, + "id": "Addis Ababa" + }, { + "geometry": { + "type": "Point", + "coordinates": [38.933, 15.333] + }, + "type": "Feature", + "properties": { + "wikipedia": "Asmara", + "city": "Asmara" + }, + "id": "Asmara" + }, { + "geometry": { + "type": "Point", + "coordinates": [39.167, 21.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "Jeddah", + "city": "Jeddah" + }, + "id": "Jeddah" + }, { + "geometry": { + "type": "Point", + "coordinates": [39.2, -6.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Zanzibar_City", + "city": "Zanzibar City" + }, + "id": "Zanzibar City" + }, { + "geometry": { + "type": "Point", + "coordinates": [39.267, -6.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dar_es_Salaam", + "city": "Dar es Salaam" + }, + "id": "Dar es Salaam" + }, { + "geometry": { + "type": "Point", + "coordinates": [39.6, 24.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Medina", + "city": "Medina" + }, + "id": "Medina" + }, { + "geometry": { + "type": "Point", + "coordinates": [39.817, 21.417] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mecca", + "city": "Mecca" + }, + "id": "Mecca" + }, { + "geometry": { + "type": "Point", + "coordinates": [41.017, 43] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sukhumi", + "city": "Sukhumi" + }, + "id": "Sukhumi" + }, { + "geometry": { + "type": "Point", + "coordinates": [43.133, 11.583] + }, + "type": "Feature", + "properties": { + "wikipedia": "Djibouti_(city)", + "city": "Djibouti (city)" + }, + "id": "Djibouti (city)" + }, { + "geometry": { + "type": "Point", + "coordinates": [43.2, -11.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Moroni,_Comoros", + "city": "Moroni" + }, + "id": "Moroni" + }, { + "geometry": { + "type": "Point", + "coordinates": [43.967, 42.233] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tskhinvali", + "city": "Tskhinvali" + }, + "id": "Tskhinvali" + }, { + "geometry": { + "type": "Point", + "coordinates": [44.2, 15.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sana%27a", + "city": "Sana%27a" + }, + "id": "Sana%27a" + }, { + "geometry": { + "type": "Point", + "coordinates": [44.417, 33.317] + }, + "type": "Feature", + "properties": { + "wikipedia": "Baghdad", + "city": "Baghdad" + }, + "id": "Baghdad" + }, { + "geometry": { + "type": "Point", + "coordinates": [44, 56.333] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nizhny_Novgorod", + "city": "Nizhny Novgorod" + }, + "id": "Nizhny Novgorod" + }, { + "geometry": { + "type": "Point", + "coordinates": [44, 9.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hargeisa", + "city": "Hargeisa" + }, + "id": "Hargeisa" + }, { + "geometry": { + "type": "Point", + "coordinates": [44.017, 36.333] + }, + "type": "Feature", + "properties": { + "wikipedia": "Arbil", + "city": "Arbil" + }, + "id": "Arbil" + }, { + "geometry": { + "type": "Point", + "coordinates": [44.517, 40.183] + }, + "type": "Feature", + "properties": { + "wikipedia": "Yerevan", + "city": "Yerevan" + }, + "id": "Yerevan" + }, { + "geometry": { + "type": "Point", + "coordinates": [44.783, 41.717] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tbilisi", + "city": "Tbilisi" + }, + "id": "Tbilisi" + }, { + "geometry": { + "type": "Point", + "coordinates": [45.217, -12.783] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mamoudzou", + "city": "Mamoudzou" + }, + "id": "Mamoudzou" + }, { + "geometry": { + "type": "Point", + "coordinates": [45.35, 2.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mogadishu", + "city": "Mogadishu" + }, + "id": "Mogadishu" + }, { + "geometry": { + "type": "Point", + "coordinates": [46.283, 38.083] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tabriz", + "city": "Tabriz" + }, + "id": "Tabriz" + }, { + "geometry": { + "type": "Point", + "coordinates": [46.717, 24.7] + }, + "type": "Feature", + "properties": { + "wikipedia": "Riyadh", + "city": "Riyadh" + }, + "id": "Riyadh" + }, { + "geometry": { + "type": "Point", + "coordinates": [46.75, 39.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Stepanakert", + "city": "Stepanakert" + }, + "id": "Stepanakert" + }, { + "geometry": { + "type": "Point", + "coordinates": [47.517, -18.933] + }, + "type": "Feature", + "properties": { + "wikipedia": "Antananarivo", + "city": "Antananarivo" + }, + "id": "Antananarivo" + }, { + "geometry": { + "type": "Point", + "coordinates": [47.817, 30.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Basra", + "city": "Basra" + }, + "id": "Basra" + }, { + "geometry": { + "type": "Point", + "coordinates": [47.967, 29.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kuwait_City", + "city": "Kuwait City" + }, + "id": "Kuwait City" + }, { + "geometry": { + "type": "Point", + "coordinates": [49.883, 40.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Baku", + "city": "Baku" + }, + "id": "Baku" + }, { + "geometry": { + "type": "Point", + "coordinates": [50.117, 26.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dammam", + "city": "Dammam" + }, + "id": "Dammam" + }, { + "geometry": { + "type": "Point", + "coordinates": [50.167, 53.233] + }, + "type": "Feature", + "properties": { + "wikipedia": "Samara,_Russia", + "city": "Samara" + }, + "id": "Samara" + }, { + "geometry": { + "type": "Point", + "coordinates": [50.583, 26.217] + }, + "type": "Feature", + "properties": { + "wikipedia": "Manama", + "city": "Manama" + }, + "id": "Manama" + }, { + "geometry": { + "type": "Point", + "coordinates": [51.417, 35.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tehran", + "city": "Tehran" + }, + "id": "Tehran" + }, { + "geometry": { + "type": "Point", + "coordinates": [51.533, 25.283] + }, + "type": "Feature", + "properties": { + "wikipedia": "Doha", + "city": "Doha" + }, + "id": "Doha" + }, { + "geometry": { + "type": "Point", + "coordinates": [54.367, 24.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Abu_Dhabi", + "city": "Abu Dhabi" + }, + "id": "Abu Dhabi" + }, { + "geometry": { + "type": "Point", + "coordinates": [55.3, 25.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dubai", + "city": "Dubai" + }, + "id": "Dubai" + }, { + "geometry": { + "type": "Point", + "coordinates": [55.45, -4.617] + }, + "type": "Feature", + "properties": { + "wikipedia": "Victoria,_Seychelles", + "city": "Victoria" + }, + "id": "Victoria" + }, { + "geometry": { + "type": "Point", + "coordinates": [55.45, -20.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Saint-Denis,_R%C3%A9union", + "city": "Saint-Denis" + }, + "id": "Saint-Denis" + }, { + "geometry": { + "type": "Point", + "coordinates": [56.317, 58] + }, + "type": "Feature", + "properties": { + "wikipedia": "Perm", + "city": "Perm" + }, + "id": "Perm" + }, { + "geometry": { + "type": "Point", + "coordinates": [57.5, -20.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Port_Louis", + "city": "Port Louis" + }, + "id": "Port Louis" + }, { + "geometry": { + "type": "Point", + "coordinates": [58.333, 37.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ashgabat", + "city": "Ashgabat" + }, + "id": "Ashgabat" + }, { + "geometry": { + "type": "Point", + "coordinates": [58.533, 23.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Muscat,_Oman", + "city": "Muscat" + }, + "id": "Muscat" + }, { + "geometry": { + "type": "Point", + "coordinates": [59.6, 42.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nukus", + "city": "Nukus" + }, + "id": "Nukus" + }, { + "geometry": { + "type": "Point", + "coordinates": [59.6, 36.3] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mashhad", + "city": "Mashhad" + }, + "id": "Mashhad" + }, { + "geometry": { + "type": "Point", + "coordinates": [60.583, 56.833] + }, + "type": "Feature", + "properties": { + "wikipedia": "Yekaterinburg", + "city": "Yekaterinburg" + }, + "id": "Yekaterinburg" + }, { + "geometry": { + "type": "Point", + "coordinates": [65.717, 31.617] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kandahar", + "city": "Kandahar" + }, + "id": "Kandahar" + }, { + "geometry": { + "type": "Point", + "coordinates": [67, 24.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Karachi", + "city": "Karachi" + }, + "id": "Karachi" + }, { + "geometry": { + "type": "Point", + "coordinates": [78.467, 17.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hyderabad,_Andhra_Pradesh", + "city": "Hyderabad" + }, + "id": "Hyderabad" + }, { + "geometry": { + "type": "Point", + "coordinates": [68.767, 38.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dushanbe", + "city": "Dushanbe" + }, + "id": "Dushanbe" + }, { + "geometry": { + "type": "Point", + "coordinates": [69.167, 34.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kabul", + "city": "Kabul" + }, + "id": "Kabul" + }, { + "geometry": { + "type": "Point", + "coordinates": [69.217, 41.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tashkent", + "city": "Tashkent" + }, + "id": "Tashkent" + }, { + "geometry": { + "type": "Point", + "coordinates": [71.45, 51.183] + }, + "type": "Feature", + "properties": { + "wikipedia": "Astana", + "city": "Astana" + }, + "id": "Astana" + }, { + "geometry": { + "type": "Point", + "coordinates": [71.45, 30.2] + }, + "type": "Feature", + "properties": { + "wikipedia": "Multan", + "city": "Multan" + }, + "id": "Multan" + }, { + "geometry": { + "type": "Point", + "coordinates": [71.5, 34] + }, + "type": "Feature", + "properties": { + "wikipedia": "Peshawar", + "city": "Peshawar" + }, + "id": "Peshawar" + }, { + "geometry": { + "type": "Point", + "coordinates": [71.967, 41.633] + }, + "type": "Feature", + "properties": { + "wikipedia": "Namangan", + "city": "Namangan" + }, + "id": "Namangan" + }, { + "geometry": { + "type": "Point", + "coordinates": [72.567, 23.017] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ahmedabad", + "city": "Ahmedabad" + }, + "id": "Ahmedabad" + }, { + "geometry": { + "type": "Point", + "coordinates": [72.817, 18.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mumbai", + "city": "Mumbai" + }, + "id": "Mumbai" + }, { + "geometry": { + "type": "Point", + "coordinates": [72.817, 21.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Surat,_Gujarat", + "city": "Surat" + }, + "id": "Surat" + }, { + "geometry": { + "type": "Point", + "coordinates": [72.983, 31.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Faisalabad", + "city": "Faisalabad" + }, + "id": "Faisalabad" + }, { + "geometry": { + "type": "Point", + "coordinates": [73.033, 33.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Rawalpindi", + "city": "Rawalpindi" + }, + "id": "Rawalpindi" + }, { + "geometry": { + "type": "Point", + "coordinates": [73.067, 33.717] + }, + "type": "Feature", + "properties": { + "wikipedia": "Islamabad", + "city": "Islamabad" + }, + "id": "Islamabad" + }, { + "geometry": { + "type": "Point", + "coordinates": [73.367, 54.983] + }, + "type": "Feature", + "properties": { + "wikipedia": "Omsk", + "city": "Omsk" + }, + "id": "Omsk" + }, { + "geometry": { + "type": "Point", + "coordinates": [73.5, 4.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mal%C3%A9", + "city": "Mal%C3%A9" + }, + "id": "Mal%C3%A9" + }, { + "geometry": { + "type": "Point", + "coordinates": [73.85, 18.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Pune", + "city": "Pune" + }, + "id": "Pune" + }, { + "geometry": { + "type": "Point", + "coordinates": [74.333, 31.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lahore", + "city": "Lahore" + }, + "id": "Lahore" + }, { + "geometry": { + "type": "Point", + "coordinates": [74.6, 42.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bishkek", + "city": "Bishkek" + }, + "id": "Bishkek" + }, { + "geometry": { + "type": "Point", + "coordinates": [74.783, 34.083] + }, + "type": "Feature", + "properties": { + "wikipedia": "Srinagar", + "city": "Srinagar" + }, + "id": "Srinagar" + }, { + "geometry": { + "type": "Point", + "coordinates": [74.85, 31.633] + }, + "type": "Feature", + "properties": { + "wikipedia": "Amritsar", + "city": "Amritsar" + }, + "id": "Amritsar" + }, { + "geometry": { + "type": "Point", + "coordinates": [75.817, 26.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Jaipur", + "city": "Jaipur" + }, + "id": "Jaipur" + }, { + "geometry": { + "type": "Point", + "coordinates": [75.85, 30.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ludhiana", + "city": "Ludhiana" + }, + "id": "Ludhiana" + }, { + "geometry": { + "type": "Point", + "coordinates": [76.883, 43.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Almaty", + "city": "Almaty" + }, + "id": "Almaty" + }, { + "geometry": { + "type": "Point", + "coordinates": [77.2, 28.617] + }, + "type": "Feature", + "properties": { + "wikipedia": "New_Delhi", + "city": "New Delhi" + }, + "id": "New Delhi" + }, { + "geometry": { + "type": "Point", + "coordinates": [77.567, 12.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bangalore", + "city": "Bangalore" + }, + "id": "Bangalore" + }, { + "geometry": { + "type": "Point", + "coordinates": [79.017, 21.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nagpur", + "city": "Nagpur" + }, + "id": "Nagpur" + }, { + "geometry": { + "type": "Point", + "coordinates": [79.867, 6.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Colombo", + "city": "Colombo" + }, + "id": "Colombo" + }, { + "geometry": { + "type": "Point", + "coordinates": [79.883, 6.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sri_Jayawardenapura-Kotte", + "city": "Sri Jayawardenapura-Kotte" + }, + "id": "Sri Jayawardenapura-Kotte" + }, { + "geometry": { + "type": "Point", + "coordinates": [80.267, 13.083] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chennai", + "city": "Chennai" + }, + "id": "Chennai" + }, { + "geometry": { + "type": "Point", + "coordinates": [80.333, 26.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kanpur", + "city": "Kanpur" + }, + "id": "Kanpur" + }, { + "geometry": { + "type": "Point", + "coordinates": [80.633, 7.283] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kandy", + "city": "Kandy" + }, + "id": "Kandy" + }, { + "geometry": { + "type": "Point", + "coordinates": [80.917, 26.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lucknow", + "city": "Lucknow" + }, + "id": "Lucknow" + }, { + "geometry": { + "type": "Point", + "coordinates": [81.7, 7.717] + }, + "type": "Feature", + "properties": { + "wikipedia": "Batticaloa", + "city": "Batticaloa" + }, + "id": "Batticaloa" + }, { + "geometry": { + "type": "Point", + "coordinates": [82.933, 55.017] + }, + "type": "Feature", + "properties": { + "wikipedia": "Novosibirsk", + "city": "Novosibirsk" + }, + "id": "Novosibirsk" + }, { + "geometry": { + "type": "Point", + "coordinates": [85.133, 25.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Patna", + "city": "Patna" + }, + "id": "Patna" + }, { + "geometry": { + "type": "Point", + "coordinates": [85.333, 27.7] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kathmandu", + "city": "Kathmandu" + }, + "id": "Kathmandu" + }, { + "geometry": { + "type": "Point", + "coordinates": [87.583, 43.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "%C3%9Cr%C3%BCmqi", + "city": "%C3%9Cr%C3%BCmqi" + }, + "id": "%C3%9Cr%C3%BCmqi" + }, { + "geometry": { + "type": "Point", + "coordinates": [88.2, 69.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Norilsk", + "city": "Norilsk" + }, + "id": "Norilsk" + }, { + "geometry": { + "type": "Point", + "coordinates": [88.367, 22.567] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kolkata", + "city": "Kolkata" + }, + "id": "Kolkata" + }, { + "geometry": { + "type": "Point", + "coordinates": [88.617, 27.317] + }, + "type": "Feature", + "properties": { + "wikipedia": "Gangtok", + "city": "Gangtok" + }, + "id": "Gangtok" + }, { + "geometry": { + "type": "Point", + "coordinates": [88.867, 29.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Shigatse", + "city": "Shigatse" + }, + "id": "Shigatse" + }, { + "geometry": { + "type": "Point", + "coordinates": [89.633, 27.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Thimphu", + "city": "Thimphu" + }, + "id": "Thimphu" + }, { + "geometry": { + "type": "Point", + "coordinates": [90.367, 23.7] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dhaka", + "city": "Dhaka" + }, + "id": "Dhaka" + }, { + "geometry": { + "type": "Point", + "coordinates": [91.117, 29.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lhasa", + "city": "Lhasa" + }, + "id": "Lhasa" + }, { + "geometry": { + "type": "Point", + "coordinates": [91.2, 23.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Agartala", + "city": "Agartala" + }, + "id": "Agartala" + }, { + "geometry": { + "type": "Point", + "coordinates": [91.767, 26.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Guwahati", + "city": "Guwahati" + }, + "id": "Guwahati" + }, { + "geometry": { + "type": "Point", + "coordinates": [91.8, 22.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chittagong", + "city": "Chittagong" + }, + "id": "Chittagong" + }, { + "geometry": { + "type": "Point", + "coordinates": [91.883, 25.567] + }, + "type": "Feature", + "properties": { + "wikipedia": "Shillong", + "city": "Shillong" + }, + "id": "Shillong" + }, { + "geometry": { + "type": "Point", + "coordinates": [92.75, 11.667] + }, + "type": "Feature", + "properties": { + "wikipedia": "Port_Blair", + "city": "Port Blair" + }, + "id": "Port Blair" + }, { + "geometry": { + "type": "Point", + "coordinates": [94.9, 27.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dibrugarh", + "city": "Dibrugarh" + }, + "id": "Dibrugarh" + }, { + "geometry": { + "type": "Point", + "coordinates": [95.317, 5.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Banda_Aceh", + "city": "Banda Aceh" + }, + "id": "Banda Aceh" + }, { + "geometry": { + "type": "Point", + "coordinates": [96.1, 19.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Naypyidaw", + "city": "Naypyidaw" + }, + "id": "Naypyidaw" + }, { + "geometry": { + "type": "Point", + "coordinates": [96.167, 16.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Yangon", + "city": "Yangon" + }, + "id": "Yangon" + }, { + "geometry": { + "type": "Point", + "coordinates": [98.667, 3.583] + }, + "type": "Feature", + "properties": { + "wikipedia": "Medan", + "city": "Medan" + }, + "id": "Medan" + }, { + "geometry": { + "type": "Point", + "coordinates": [98.4, 7.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Phuket_(city)", + "city": "Phuket (city)" + }, + "id": "Phuket (city)" + }, { + "geometry": { + "type": "Point", + "coordinates": [98.983, 18.783] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chiang_Mai", + "city": "Chiang Mai" + }, + "id": "Chiang Mai" + }, { + "geometry": { + "type": "Point", + "coordinates": [99.333, 9.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Surat_Thani", + "city": "Surat Thani" + }, + "id": "Surat Thani" + }, { + "geometry": { + "type": "Point", + "coordinates": [100.35, -0.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Padang,_Indonesia", + "city": "Padang" + }, + "id": "Padang" + }, { + "geometry": { + "type": "Point", + "coordinates": [100.367, 6.117] + }, + "type": "Feature", + "properties": { + "wikipedia": "Alor_Star", + "city": "Alor Star" + }, + "id": "Alor Star" + }, { + "geometry": { + "type": "Point", + "coordinates": [100.467, 7.017] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hat_Yai", + "city": "Hat Yai" + }, + "id": "Hat Yai" + }, { + "geometry": { + "type": "Point", + "coordinates": [100.483, 13.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bangkok", + "city": "Bangkok" + }, + "id": "Bangkok" + }, { + "geometry": { + "type": "Point", + "coordinates": [100.867, 12.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Pattaya", + "city": "Pattaya" + }, + "id": "Pattaya" + }, { + "geometry": { + "type": "Point", + "coordinates": [101.067, 4.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ipoh", + "city": "Ipoh" + }, + "id": "Ipoh" + }, { + "geometry": { + "type": "Point", + "coordinates": [101.45, 0.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "Pekanbaru", + "city": "Pekanbaru" + }, + "id": "Pekanbaru" + }, { + "geometry": { + "type": "Point", + "coordinates": [101.617, 56.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bratsk", + "city": "Bratsk" + }, + "id": "Bratsk" + }, { + "geometry": { + "type": "Point", + "coordinates": [101.683, 3.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kuala_Lumpur", + "city": "Kuala Lumpur" + }, + "id": "Kuala Lumpur" + }, { + "geometry": { + "type": "Point", + "coordinates": [101.767, 36.633] + }, + "type": "Feature", + "properties": { + "wikipedia": "Xining", + "city": "Xining" + }, + "id": "Xining" + }, { + "geometry": { + "type": "Point", + "coordinates": [102.1, 14.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nakhon_Ratchasima", + "city": "Nakhon Ratchasima" + }, + "id": "Nakhon Ratchasima" + }, { + "geometry": { + "type": "Point", + "coordinates": [102.25, 6.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kota_Bharu", + "city": "Kota Bharu" + }, + "id": "Kota Bharu" + }, { + "geometry": { + "type": "Point", + "coordinates": [102.383, 2.183] + }, + "type": "Feature", + "properties": { + "wikipedia": "Malacca_Town", + "city": "Malacca Town" + }, + "id": "Malacca Town" + }, { + "geometry": { + "type": "Point", + "coordinates": [102.617, 17.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Vientiane", + "city": "Vientiane" + }, + "id": "Vientiane" + }, { + "geometry": { + "type": "Point", + "coordinates": [102.683, 25.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kunming", + "city": "Kunming" + }, + "id": "Kunming" + }, { + "geometry": { + "type": "Point", + "coordinates": [102.75, 17.417] + }, + "type": "Feature", + "properties": { + "wikipedia": "Udon_Thani", + "city": "Udon Thani" + }, + "id": "Udon Thani" + }, { + "geometry": { + "type": "Point", + "coordinates": [103.733, 1.483] + }, + "type": "Feature", + "properties": { + "wikipedia": "Johor_Bahru", + "city": "Johor Bahru" + }, + "id": "Johor Bahru" + }, { + "geometry": { + "type": "Point", + "coordinates": [103.8, 36.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Lanzhou", + "city": "Lanzhou" + }, + "id": "Lanzhou" + }, { + "geometry": { + "type": "Point", + "coordinates": [103.8, 1.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Singapore", + "city": "Singapore" + }, + "id": "Singapore" + }, { + "geometry": { + "type": "Point", + "coordinates": [103.85, 13.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Siem_Reap", + "city": "Siem Reap" + }, + "id": "Siem Reap" + }, { + "geometry": { + "type": "Point", + "coordinates": [104.067, 30.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chengdu", + "city": "Chengdu" + }, + "id": "Chengdu" + }, { + "geometry": { + "type": "Point", + "coordinates": [104.75, -2.983] + }, + "type": "Feature", + "properties": { + "wikipedia": "Palembang", + "city": "Palembang" + }, + "id": "Palembang" + }, { + "geometry": { + "type": "Point", + "coordinates": [104.917, 11.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Phnom_Penh", + "city": "Phnom Penh" + }, + "id": "Phnom Penh" + }, { + "geometry": { + "type": "Point", + "coordinates": [105.85, 21.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hanoi", + "city": "Hanoi" + }, + "id": "Hanoi" + }, { + "geometry": { + "type": "Point", + "coordinates": [106.5, 29.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chongqing", + "city": "Chongqing" + }, + "id": "Chongqing" + }, { + "geometry": { + "type": "Point", + "coordinates": [106.683, 20.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hai_Phong", + "city": "Hai Phong" + }, + "id": "Hai Phong" + }, { + "geometry": { + "type": "Point", + "coordinates": [106.683, 10.767] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ho_Chi_Minh_City", + "city": "Ho Chi Minh City" + }, + "id": "Ho Chi Minh City" + }, { + "geometry": { + "type": "Point", + "coordinates": [106.75, -6.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Jakarta", + "city": "Jakarta" + }, + "id": "Jakarta" + }, { + "geometry": { + "type": "Point", + "coordinates": [106.8, -6.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bogor", + "city": "Bogor" + }, + "id": "Bogor" + }, { + "geometry": { + "type": "Point", + "coordinates": [106.917, 47.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ulan_Bator", + "city": "Ulan Bator" + }, + "id": "Ulan Bator" + }, { + "geometry": { + "type": "Point", + "coordinates": [107.567, -6.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bandung", + "city": "Bandung" + }, + "id": "Bandung" + }, { + "geometry": { + "type": "Point", + "coordinates": [107.6, 16.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hu%E1%BA%BF", + "city": "Hu%E1%BA%BF" + }, + "id": "Hu%E1%BA%BF" + }, { + "geometry": { + "type": "Point", + "coordinates": [108.233, 16.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Da_Nang", + "city": "Da Nang" + }, + "id": "Da Nang" + }, { + "geometry": { + "type": "Point", + "coordinates": [108.317, 22.817] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nanning", + "city": "Nanning" + }, + "id": "Nanning" + }, { + "geometry": { + "type": "Point", + "coordinates": [108.9, 34.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Xi%27an", + "city": "Xi%27an" + }, + "id": "Xi%27an" + }, { + "geometry": { + "type": "Point", + "coordinates": [109.333, 0] + }, + "type": "Feature", + "properties": { + "wikipedia": "Pontianak,_Indonesia", + "city": "Pontianak" + }, + "id": "Pontianak" + }, { + "geometry": { + "type": "Point", + "coordinates": [110.35, 1.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kuching", + "city": "Kuching" + }, + "id": "Kuching" + }, { + "geometry": { + "type": "Point", + "coordinates": [110.367, -7.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Yogyakarta_(city)", + "city": "Yogyakarta (city)" + }, + "id": "Yogyakarta (city)" + }, { + "geometry": { + "type": "Point", + "coordinates": [110.417, -6.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Semarang", + "city": "Semarang" + }, + "id": "Semarang" + }, { + "geometry": { + "type": "Point", + "coordinates": [112.55, 37.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Taiyuan", + "city": "Taiyuan" + }, + "id": "Taiyuan" + }, { + "geometry": { + "type": "Point", + "coordinates": [112.617, -7.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Malang", + "city": "Malang" + }, + "id": "Malang" + }, { + "geometry": { + "type": "Point", + "coordinates": [112.733, -7.233] + }, + "type": "Feature", + "properties": { + "wikipedia": "Surabaya", + "city": "Surabaya" + }, + "id": "Surabaya" + }, { + "geometry": { + "type": "Point", + "coordinates": [113.267, 23.1] + }, + "type": "Feature", + "properties": { + "wikipedia": "Guangzhou", + "city": "Guangzhou" + }, + "id": "Guangzhou" + }, { + "geometry": { + "type": "Point", + "coordinates": [113.55, 22.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Macau", + "city": "Macau" + }, + "id": "Macau" + }, { + "geometry": { + "type": "Point", + "coordinates": [113.633, 34.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Zhengzhou", + "city": "Zhengzhou" + }, + "id": "Zhengzhou" + }, { + "geometry": { + "type": "Point", + "coordinates": [113.717, 23.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dongguan", + "city": "Dongguan" + }, + "id": "Dongguan" + }, { + "geometry": { + "type": "Point", + "coordinates": [113.967, 4.383] + }, + "type": "Feature", + "properties": { + "wikipedia": "Miri", + "city": "Miri" + }, + "id": "Miri" + }, { + "geometry": { + "type": "Point", + "coordinates": [114.1, 22.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Shenzhen", + "city": "Shenzhen" + }, + "id": "Shenzhen" + }, { + "geometry": { + "type": "Point", + "coordinates": [114.2, 22.3] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hong Kong", + "city": "Hong Kong" + }, + "id": "Hong Kong" + }, { + "geometry": { + "type": "Point", + "coordinates": [114.267, 30.567] + }, + "type": "Feature", + "properties": { + "wikipedia": "Wuhan", + "city": "Wuhan" + }, + "id": "Wuhan" + }, { + "geometry": { + "type": "Point", + "coordinates": [114.483, 36.6] + }, + "type": "Feature", + "properties": { + "wikipedia": "Handan", + "city": "Handan" + }, + "id": "Handan" + }, { + "geometry": { + "type": "Point", + "coordinates": [114.5, 38.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Shijiazhuang", + "city": "Shijiazhuang" + }, + "id": "Shijiazhuang" + }, { + "geometry": { + "type": "Point", + "coordinates": [114.933, 4.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Bandar_Seri_Begawan", + "city": "Bandar Seri Begawan" + }, + "id": "Bandar Seri Begawan" + }, { + "geometry": { + "type": "Point", + "coordinates": [115.217, -8.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Denpasar", + "city": "Denpasar" + }, + "id": "Denpasar" + }, { + "geometry": { + "type": "Point", + "coordinates": [115.717, -32.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mandurah", + "city": "Mandurah" + }, + "id": "Mandurah" + }, { + "geometry": { + "type": "Point", + "coordinates": [115.85, -31.95] + }, + "type": "Feature", + "properties": { + "wikipedia": "Perth,_Western_Australia", + "city": "Perth" + }, + "id": "Perth" + }, { + "geometry": { + "type": "Point", + "coordinates": [116.083, 5.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kota_Kinabalu", + "city": "Kota Kinabalu" + }, + "id": "Kota Kinabalu" + }, { + "geometry": { + "type": "Point", + "coordinates": [116.4, 39.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Beijing", + "city": "Beijing" + }, + "id": "Beijing" + }, { + "geometry": { + "type": "Point", + "coordinates": [116.817, -1.25] + }, + "type": "Feature", + "properties": { + "wikipedia": "Balikpapan", + "city": "Balikpapan" + }, + "id": "Balikpapan" + }, { + "geometry": { + "type": "Point", + "coordinates": [116.983, 36.667] + }, + "type": "Feature", + "properties": { + "wikipedia": "Jinan", + "city": "Jinan" + }, + "id": "Jinan" + }, { + "geometry": { + "type": "Point", + "coordinates": [117.183, 39.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tianjin", + "city": "Tianjin" + }, + "id": "Tianjin" + }, { + "geometry": { + "type": "Point", + "coordinates": [118.6, -20.3] + }, + "type": "Feature", + "properties": { + "wikipedia": "Port_Hedland,_Western_Australia", + "city": "Port Hedland" + }, + "id": "Port Hedland" + }, { + "geometry": { + "type": "Point", + "coordinates": [118.767, 32.05] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nanjing", + "city": "Nanjing" + }, + "id": "Nanjing" + }, { + "geometry": { + "type": "Point", + "coordinates": [119.417, -5.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Makassar", + "city": "Makassar" + }, + "id": "Makassar" + }, { + "geometry": { + "type": "Point", + "coordinates": [120.167, 30.25] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hangzhou", + "city": "Hangzhou" + }, + "id": "Hangzhou" + }, { + "geometry": { + "type": "Point", + "coordinates": [120.267, 22.633] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kaohsiung", + "city": "Kaohsiung" + }, + "id": "Kaohsiung" + }, { + "geometry": { + "type": "Point", + "coordinates": [120.333, 36.083] + }, + "type": "Feature", + "properties": { + "wikipedia": "Qingdao", + "city": "Qingdao" + }, + "id": "Qingdao" + }, { + "geometry": { + "type": "Point", + "coordinates": [120.667, 24.15] + }, + "type": "Feature", + "properties": { + "wikipedia": "Taichung", + "city": "Taichung" + }, + "id": "Taichung" + }, { + "geometry": { + "type": "Point", + "coordinates": [120.967, 14.583] + }, + "type": "Feature", + "properties": { + "wikipedia": "Manila", + "city": "Manila" + }, + "id": "Manila" + }, { + "geometry": { + "type": "Point", + "coordinates": [121.033, 14.633] + }, + "type": "Feature", + "properties": { + "wikipedia": "Quezon_City", + "city": "Quezon City" + }, + "id": "Quezon City" + }, { + "geometry": { + "type": "Point", + "coordinates": [121.033, 14.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Makati_City", + "city": "Makati City" + }, + "id": "Makati City" + }, { + "geometry": { + "type": "Point", + "coordinates": [121.5, 31.2] + }, + "type": "Feature", + "properties": { + "wikipedia": "Shanghai", + "city": "Shanghai" + }, + "id": "Shanghai" + }, { + "geometry": { + "type": "Point", + "coordinates": [121.633, 25.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Taipei", + "city": "Taipei" + }, + "id": "Taipei" + }, { + "geometry": { + "type": "Point", + "coordinates": [121.767, 39.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dalian", + "city": "Dalian" + }, + "id": "Dalian" + }, { + "geometry": { + "type": "Point", + "coordinates": [122.55, 10.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Iloilo_City", + "city": "Iloilo City" + }, + "id": "Iloilo City" + }, { + "geometry": { + "type": "Point", + "coordinates": [122.067, 6.9] + }, + "type": "Feature", + "properties": { + "wikipedia": "Zamboanga_City", + "city": "Zamboanga City" + }, + "id": "Zamboanga City" + }, { + "geometry": { + "type": "Point", + "coordinates": [123.45, 41.783] + }, + "type": "Feature", + "properties": { + "wikipedia": "Shenyang", + "city": "Shenyang" + }, + "id": "Shenyang" + }, { + "geometry": { + "type": "Point", + "coordinates": [123.85, 9.65] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tagbilaran", + "city": "Tagbilaran" + }, + "id": "Tagbilaran" + }, { + "geometry": { + "type": "Point", + "coordinates": [123.9, 10.283] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cebu_City", + "city": "Cebu City" + }, + "id": "Cebu City" + }, { + "geometry": { + "type": "Point", + "coordinates": [125.317, 43.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Changchun", + "city": "Changchun" + }, + "id": "Changchun" + }, { + "geometry": { + "type": "Point", + "coordinates": [125.583, -8.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dili", + "city": "Dili" + }, + "id": "Dili" + }, { + "geometry": { + "type": "Point", + "coordinates": [125.75, 39.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Pyongyang", + "city": "Pyongyang" + }, + "id": "Pyongyang" + }, { + "geometry": { + "type": "Point", + "coordinates": [126, 7.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Davao_City", + "city": "Davao City" + }, + "id": "Davao City" + }, { + "geometry": { + "type": "Point", + "coordinates": [126.55, 37.967] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kaesong", + "city": "Kaesong" + }, + "id": "Kaesong" + }, { + "geometry": { + "type": "Point", + "coordinates": [126.633, 45.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Harbin", + "city": "Harbin" + }, + "id": "Harbin" + }, { + "geometry": { + "type": "Point", + "coordinates": [126.633, 37.483] + }, + "type": "Feature", + "properties": { + "wikipedia": "Incheon", + "city": "Incheon" + }, + "id": "Incheon" + }, { + "geometry": { + "type": "Point", + "coordinates": [126.983, 37.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Seoul", + "city": "Seoul" + }, + "id": "Seoul" + }, { + "geometry": { + "type": "Point", + "coordinates": [127.433, 39.15] + }, + "type": "Feature", + "properties": { + "wikipedia": "Wonsan", + "city": "Wonsan" + }, + "id": "Wonsan" + }, { + "geometry": { + "type": "Point", + "coordinates": [127.8, 26.333] + }, + "type": "Feature", + "properties": { + "wikipedia": "Okinawa,_Okinawa", + "city": "Okinawa" + }, + "id": "Okinawa" + }, { + "geometry": { + "type": "Point", + "coordinates": [128.167, -3.7] + }, + "type": "Feature", + "properties": { + "wikipedia": "Ambon,_Maluku", + "city": "Ambon" + }, + "id": "Ambon" + }, { + "geometry": { + "type": "Point", + "coordinates": [128.6, 35.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Daegu", + "city": "Daegu" + }, + "id": "Daegu" + }, { + "geometry": { + "type": "Point", + "coordinates": [129.033, 35.1] + }, + "type": "Feature", + "properties": { + "wikipedia": "Busan", + "city": "Busan" + }, + "id": "Busan" + }, { + "geometry": { + "type": "Point", + "coordinates": [129.733, 62.033] + }, + "type": "Feature", + "properties": { + "wikipedia": "Yakutsk", + "city": "Yakutsk" + }, + "id": "Yakutsk" + }, { + "geometry": { + "type": "Point", + "coordinates": [129.783, 41.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Chongjin", + "city": "Chongjin" + }, + "id": "Chongjin" + }, { + "geometry": { + "type": "Point", + "coordinates": [130.4, 33.583] + }, + "type": "Feature", + "properties": { + "wikipedia": "Fukuoka", + "city": "Fukuoka" + }, + "id": "Fukuoka" + }, { + "geometry": { + "type": "Point", + "coordinates": [130.833, -12.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Darwin,_Northern_Territory", + "city": "Darwin" + }, + "id": "Darwin" + }, { + "geometry": { + "type": "Point", + "coordinates": [131.9, 43.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Vladivostok", + "city": "Vladivostok" + }, + "id": "Vladivostok" + }, { + "geometry": { + "type": "Point", + "coordinates": [132.45, 34.383] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hiroshima", + "city": "Hiroshima" + }, + "id": "Hiroshima" + }, { + "geometry": { + "type": "Point", + "coordinates": [134.467, 7.35] + }, + "type": "Feature", + "properties": { + "wikipedia": "Koror", + "city": "Koror" + }, + "id": "Koror" + }, { + "geometry": { + "type": "Point", + "coordinates": [134.617, 7.5] + }, + "type": "Feature", + "properties": { + "wikipedia": "Melekeok", + "city": "Melekeok" + }, + "id": "Melekeok" + }, { + "geometry": { + "type": "Point", + "coordinates": [135.2, 34.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kobe", + "city": "Kobe" + }, + "id": "Kobe" + }, { + "geometry": { + "type": "Point", + "coordinates": [135.5, 34.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Osaka", + "city": "Osaka" + }, + "id": "Osaka" + }, { + "geometry": { + "type": "Point", + "coordinates": [135.767, 35.017] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kyoto", + "city": "Kyoto" + }, + "id": "Kyoto" + }, { + "geometry": { + "type": "Point", + "coordinates": [136.9, 35.183] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nagoya", + "city": "Nagoya" + }, + "id": "Nagoya" + }, { + "geometry": { + "type": "Point", + "coordinates": [138.6, -34.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Adelaide", + "city": "Adelaide" + }, + "id": "Adelaide" + }, { + "geometry": { + "type": "Point", + "coordinates": [139.633, 35.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Yokohama", + "city": "Yokohama" + }, + "id": "Yokohama" + }, { + "geometry": { + "type": "Point", + "coordinates": [139.7, 35.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Kawasaki,_Kanagawa", + "city": "Kawasaki" + }, + "id": "Kawasaki" + }, { + "geometry": { + "type": "Point", + "coordinates": [139.767, 35.683] + }, + "type": "Feature", + "properties": { + "wikipedia": "Tokyo", + "city": "Tokyo" + }, + "id": "Tokyo" + }, { + "geometry": { + "type": "Point", + "coordinates": [140.717, -2.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "Jayapura", + "city": "Jayapura" + }, + "id": "Jayapura" + }, { + "geometry": { + "type": "Point", + "coordinates": [141.35, 43.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sapporo", + "city": "Sapporo" + }, + "id": "Sapporo" + }, { + "geometry": { + "type": "Point", + "coordinates": [144.35, -38.15] + }, + "type": "Feature", + "properties": { + "wikipedia": "Geelong", + "city": "Geelong" + }, + "id": "Geelong" + }, { + "geometry": { + "type": "Point", + "coordinates": [144.75, 13.483] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hag%C3%A5t%C3%B1a,_Guam", + "city": "Hag%C3%A5t%C3%B1a" + }, + "id": "Hag%C3%A5t%C3%B1a" + }, { + "geometry": { + "type": "Point", + "coordinates": [144.833, 13.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dededo,_Guam", + "city": "Dededo" + }, + "id": "Dededo" + }, { + "geometry": { + "type": "Point", + "coordinates": [144.95, -37.8] + }, + "type": "Feature", + "properties": { + "wikipedia": "Melbourne", + "city": "Melbourne" + }, + "id": "Melbourne" + }, { + "geometry": { + "type": "Point", + "coordinates": [145.75, 15.183] + }, + "type": "Feature", + "properties": { + "wikipedia": "Saipan", + "city": "Saipan" + }, + "id": "Saipan" + }, { + "geometry": { + "type": "Point", + "coordinates": [145.767, -16.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Cairns", + "city": "Cairns" + }, + "id": "Cairns" + }, { + "geometry": { + "type": "Point", + "coordinates": [146.817, -19.25] + }, + "type": "Feature", + "properties": { + "wikipedia": "Townsville", + "city": "Townsville" + }, + "id": "Townsville" + }, { + "geometry": { + "type": "Point", + "coordinates": [147.167, -9.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Port_Moresby", + "city": "Port Moresby" + }, + "id": "Port Moresby" + }, { + "geometry": { + "type": "Point", + "coordinates": [147.317, -42.883] + }, + "type": "Feature", + "properties": { + "wikipedia": "Hobart", + "city": "Hobart" + }, + "id": "Hobart" + }, { + "geometry": { + "type": "Point", + "coordinates": [149.117, -35.3] + }, + "type": "Feature", + "properties": { + "wikipedia": "Canberra", + "city": "Canberra" + }, + "id": "Canberra" + }, { + "geometry": { + "type": "Point", + "coordinates": [150.5, -23.367] + }, + "type": "Feature", + "properties": { + "wikipedia": "Rockhampton", + "city": "Rockhampton" + }, + "id": "Rockhampton" + }, { + "geometry": { + "type": "Point", + "coordinates": [150.8, 59.567] + }, + "type": "Feature", + "properties": { + "wikipedia": "Magadan", + "city": "Magadan" + }, + "id": "Magadan" + }, { + "geometry": { + "type": "Point", + "coordinates": [150.883, -34.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Wollongong", + "city": "Wollongong" + }, + "id": "Wollongong" + }, { + "geometry": { + "type": "Point", + "coordinates": [151.2, -33.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Sydney", + "city": "Sydney" + }, + "id": "Sydney" + }, { + "geometry": { + "type": "Point", + "coordinates": [151.75, -32.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Newcastle,_New_South_Wales", + "city": "Newcastle" + }, + "id": "Newcastle" + }, { + "geometry": { + "type": "Point", + "coordinates": [151.85, 7.45] + }, + "type": "Feature", + "properties": { + "wikipedia": "Weno", + "city": "Weno" + }, + "id": "Weno" + }, { + "geometry": { + "type": "Point", + "coordinates": [153.017, -27.467] + }, + "type": "Feature", + "properties": { + "wikipedia": "Brisbane", + "city": "Brisbane" + }, + "id": "Brisbane" + }, { + "geometry": { + "type": "Point", + "coordinates": [153.55, -28.167] + }, + "type": "Feature", + "properties": { + "wikipedia": "Gold_Coast,_Queensland", + "city": "Gold Coast" + }, + "id": "Gold Coast" + }, { + "geometry": { + "type": "Point", + "coordinates": [158.183, 6.917] + }, + "type": "Feature", + "properties": { + "wikipedia": "Palikir", + "city": "Palikir" + }, + "id": "Palikir" + }, { + "geometry": { + "type": "Point", + "coordinates": [158.65, 53.017] + }, + "type": "Feature", + "properties": { + "wikipedia": "Petropavlovsk-Kamchatsky", + "city": "Petropavlovsk-Kamchatsky" + }, + "id": "Petropavlovsk-Kamchatsky" + }, { + "geometry": { + "type": "Point", + "coordinates": [159.95, -9.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Honiara", + "city": "Honiara" + }, + "id": "Honiara" + }, { + "geometry": { + "type": "Point", + "coordinates": [166.45, -22.267] + }, + "type": "Feature", + "properties": { + "wikipedia": "Noum%C3%A9a", + "city": "Noum%C3%A9a" + }, + "id": "Noum%C3%A9a" + }, { + "geometry": { + "type": "Point", + "coordinates": [166.917, -0.55] + }, + "type": "Feature", + "properties": { + "wikipedia": "Yaren_District", + "city": "Yaren District" + }, + "id": "Yaren District" + }, { + "geometry": { + "type": "Point", + "coordinates": [168.3, -17.75] + }, + "type": "Feature", + "properties": { + "wikipedia": "Port_Vila", + "city": "Port Vila" + }, + "id": "Port Vila" + }, { + "geometry": { + "type": "Point", + "coordinates": [168.3, -46.417] + }, + "type": "Feature", + "properties": { + "wikipedia": "Invercargill", + "city": "Invercargill" + }, + "id": "Invercargill" + }, { + "geometry": { + "type": "Point", + "coordinates": [170.5, -45.867] + }, + "type": "Feature", + "properties": { + "wikipedia": "Dunedin", + "city": "Dunedin" + }, + "id": "Dunedin" + }, { + "geometry": { + "type": "Point", + "coordinates": [171.267, 7.067] + }, + "type": "Feature", + "properties": { + "wikipedia": "Majuro", + "city": "Majuro" + }, + "id": "Majuro" + }, { + "geometry": { + "type": "Point", + "coordinates": [172.617, -43.533] + }, + "type": "Feature", + "properties": { + "wikipedia": "Christchurch", + "city": "Christchurch" + }, + "id": "Christchurch" + }, { + "geometry": { + "type": "Point", + "coordinates": [172.983, 1.317] + }, + "type": "Feature", + "properties": { + "wikipedia": "South_Tarawa", + "city": "South Tarawa" + }, + "id": "South Tarawa" + }, { + "geometry": { + "type": "Point", + "coordinates": [174.767, -41.283] + }, + "type": "Feature", + "properties": { + "wikipedia": "Wellington", + "city": "Wellington" + }, + "id": "Wellington" + }, { + "geometry": { + "type": "Point", + "coordinates": [174.783, -36.85] + }, + "type": "Feature", + "properties": { + "wikipedia": "Auckland", + "city": "Auckland" + }, + "id": "Auckland" + }, { + "geometry": { + "type": "Point", + "coordinates": [176.183, -13.283] + }, + "type": "Feature", + "properties": { + "wikipedia": "Mata-Utu", + "city": "Mata-Utu" + }, + "id": "Mata-Utu" + }, { + "geometry": { + "type": "Point", + "coordinates": [177.5, 64.733] + }, + "type": "Feature", + "properties": { + "wikipedia": "Anadyr_(town)", + "city": "Anadyr (town)" + }, + "id": "Anadyr (town)" + }, { + "geometry": { + "type": "Point", + "coordinates": [178.433, -18.133] + }, + "type": "Feature", + "properties": { + "wikipedia": "Suva", + "city": "Suva" + }, + "id": "Suva" + }, { + "geometry": { + "type": "Point", + "coordinates": [179.217, -8.517] + }, + "type": "Feature", + "properties": { + "wikipedia": "Funafuti", + "city": "Funafuti" + }, + "id": "Funafuti" + }, { + "geometry": { + "type": "Point", + "coordinates": [179.367, -16.433] + }, + "type": "Feature", + "properties": { + "wikipedia": "Labasa", + "city": "Labasa" + }, + "id": "Labasa" + }, { + "geometry": { + "type": "Point", + "coordinates": [179.85, -9.383] + }, + "type": "Feature", + "properties": { + "wikipedia": "Nukulaelae", + "city": "Nukulaelae" + }, + "id": "Nukulaelae" + }] +} \ No newline at end of file diff --git a/examples/0755-markers-cluster-issue.html b/examples/markers-cluster-issue.html similarity index 100% rename from examples/0755-markers-cluster-issue.html rename to examples/markers-cluster-issue.html diff --git a/examples/805-markers-updates.html b/examples/markers-updates.html similarity index 95% rename from examples/805-markers-updates.html rename to examples/markers-updates.html index 00e0c04e..1811b868 100644 --- a/examples/805-markers-updates.html +++ b/examples/markers-updates.html @@ -143,10 +143,10 @@
            - +
            - +
            diff --git a/grunt/aliases.yaml b/grunt/aliases.yaml index 2326e023..2f2f633a 100644 --- a/grunt/aliases.yaml +++ b/grunt/aliases.yaml @@ -1,115 +1,52 @@ test: - - 'jshint' - - 'test-unit' - - 'test-e2e' + - 'jshint' + - 'test-unit' + - 'test-e2e' test-unit: - - 'karma:unit' - -test-unit-chrome: - - 'karma:unit-chrome' + - 'karma:unit' test-e2e: - - 'shell:protractor_update' - - 'connect:testserver' - - 'protractor:run' + - 'shell:protractor_update' + - 'connect:testserver' + - 'protractor:run' test-e2e-firefox: - - 'shell:protractor_update' - - 'connect:testserver' - - 'protractor:firefox' - -test-coverage: - - 'karma:unit_coverage' + - 'shell:protractor_update' + - 'connect:testserver' + - 'protractor:firefox' coverage: - - 'karma:unit_coverage' - - 'open:coverage' - - 'connect:coverage' + - 'karma:unit_coverage' install: - - 'shell:npm_install' - - 'bower:install' - - 'shell:protractor_update' + - 'shell:npm_install' + - 'bower:install' + - 'shell:protractor_update' default: - - 'build' - -# cause zsh always puts me in grunt folder -d: -- 'default' - -dev: - - 'connect:devserver' - - 'open:devserver' - - 'watch:source' - -dev-chrome: - - 'connect:devserver' - - 'open:devserver' - - 'watch:chrome' - -spec: #continuos running specs - - 'fast-build' - - 'concurrent:unit-mocha' - -spec-chrome: - - 'fast-build' - - 'concurrent:chrome' - -serve: - - 'concurrent:watchServe' - -s: - - 'serve' + - 'build' fast-build: - - 'clean:dist' - - 'jshint' - - 'concat:dist' - - 'concat:distMapped' - - 'ngAnnotate' - -d-watch: - - 'fast-build' - - 'concurrent:unit' + - 'clean:dist' + - 'jshint' + - 'jscs' + - 'concat:dist' + - 'ngAnnotate' + - 'uglify' + - 'concat:license' + - 'concat:license-minified' build: - - 'fast-build' - - 'uglify' - - 'test-unit' - - 'concat:license' - - 'clean:pre' + - 'fast-build' + - 'test-unit' + - 'clean:pre' travis: - - 'fast-build' - - 'bower:install' - - 'test-unit' - -bump-@: - - 'changelog' - - 'bump-only' - - 'default' - - 'graph' - - 'bump-commit' - -bump-@-minor: - - 'changelog' - - 'bump-only:minor' - - 'default' - - 'graph' - - 'bump-commit' - -bump-@-major: - - 'changelog' - - 'bump-only:major' - - 'default' - - 'graph' - - 'bump-commit' + - 'fast-build' + - 'bower:install' + - 'test-unit' examples: - - 'shell:examples' - - 'concat:examples' - -graph: - - 'angular_architecture_graph' + - 'shell:examples' + - 'concat:examples' diff --git a/grunt/angular_architecture_graph.js b/grunt/angular_architecture_graph.js deleted file mode 100644 index fac65467..00000000 --- a/grunt/angular_architecture_graph.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -module.exports = function (grunt, options) { - return { - diagram: { - files: { - "dist/architecture": ["dist/<%= pkg.name %>.js"] - } - } - }; -}; diff --git a/grunt/bower.js b/grunt/bower.js deleted file mode 100644 index a23e3483..00000000 --- a/grunt/bower.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -module.exports = function (grunt, options) { - return { - install: { - // options: { - // targetDir: './bower_components', - // cleanup: true - // } - } - }; -}; diff --git a/grunt/bower.json b/grunt/bower.json new file mode 100644 index 00000000..7e97da18 --- /dev/null +++ b/grunt/bower.json @@ -0,0 +1,4 @@ + { + "install": { + } +} diff --git a/grunt/bump.js b/grunt/bump.js deleted file mode 100644 index 95ee70b8..00000000 --- a/grunt/bump.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict'; - -module.exports = function (grunt, options) { - return { - options: { - files: ['package.json', 'bower.json'], - updateConfigs: [], - commit: true, - commitMessage: 'Release v%VERSION%', - commitFiles: [ - 'CHANGELOG.md', - 'package.json', - 'bower.json', - 'dist/angular-leaflet-directive.js', - 'dist/angular-leaflet-directive.min.js', - 'dist/angular-leaflet-directive_dev_mapped.js', - 'dist/angular-leaflet-directive_dev_mapped.js.map', - 'dist/architecture/**/*' - ], - createTag: true, - tagName: 'v%VERSION%', - tagMessage: 'Version %VERSION%', - push: false, - pushTo: 'origin', - gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d' - } - }; -}; diff --git a/grunt/changelog.js b/grunt/changelog.js deleted file mode 100644 index a4bf1203..00000000 --- a/grunt/changelog.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict'; -var _ = require('lodash'), - _pkg = require('../package.json'), - last = _.last(_pkg.version.split('.')), - next = Number(last) + 1; - -// note this will fail on new minor or major releases.. oh well manually fix it -// for now as this is mainly for changelog -_pkg.nextVersion = _pkg.version.replace(last, String(next)); - -module.exports = function (grunt, options) { - return { - options:{ - version: _pkg.nextVersion - } - }; -}; diff --git a/grunt/clean.js b/grunt/clean.js deleted file mode 100644 index 95c8ab4e..00000000 --- a/grunt/clean.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; -var pkg = require('./pkg'); - -module.exports = function (grunt, options) { - return { - dist: ["dist/"], - pre: ['dist/*.pre.js'] - }; -}; diff --git a/grunt/clean.json b/grunt/clean.json new file mode 100644 index 00000000..acaec860 --- /dev/null +++ b/grunt/clean.json @@ -0,0 +1,4 @@ +{ + "dist": ["dist"], + "pre": ["dist/*.pre.js"] +} diff --git a/grunt/concat.js b/grunt/concat.js deleted file mode 100644 index 2f374dd6..00000000 --- a/grunt/concat.js +++ /dev/null @@ -1,46 +0,0 @@ -'use strict'; - -var concatDist, concatDistMapped = null; - -concatDist = { - options: { - banner: require('./utils/banner') + "(function(angular){\n" + "'use strict';\n", - footer: '\n}(angular));' - }, - src: [ - 'src/directives/leaflet.js', - 'src/services/*.js', - 'src/**/*.js' - - ], - dest: 'dist/angular-leaflet-directive.pre.js' -}; - -concatDistMapped = _.clone(concatDist, true); -concatDistMapped.options.sourceMap = true; -concatDistMapped.options.sourceMapName = "dist/<%= pkg.name %>_dev_mapped.js.map"; -concatDistMapped.dest = "dist/<%= pkg.name %>_dev_mapped.js"; - - - -module.exports = function(grunt, options) { - return { - dist: concatDist, - distMapped: concatDistMapped, - license: { - src: [ - 'src/header-MIT-license.txt', - 'dist/angular-leaflet-directive.min.no-header.js' - ], - dest: 'dist/angular-leaflet-directive.min.js' - }, - examples: { - options: { - banner: '(function(angular){ \nvar app = angular.module(\'webapp\');\n', - footer: '}(angular));' - }, - src: ['examples/js/controllers/*.js'], - dest: 'examples/js/controllers.js' - } - }; -}; diff --git a/grunt/concat.json b/grunt/concat.json new file mode 100644 index 00000000..cbb62244 --- /dev/null +++ b/grunt/concat.json @@ -0,0 +1,36 @@ +{ + "dist": { + "options": { + "banner": "/*!\n* <%= pkg.name %> <%= pkg.version %> <%= grunt.template.today(\"yyyy-mm-dd\") %>\n* <%= pkg.description %>\n* <%= pkg.repository.type %>: <%= pkg.repository.url %>\n*/\n(function(angular){\n'use strict';\n", + "footer": "\n}(angular));" + }, + "src": [ + "src/directives/leaflet.js", + "src/services/*.js", + "src/**/*.js" + ], + "dest": "dist/angular-leaflet-directive.pre.js" + }, + "license": { + "src": [ + "src/header-MIT-license.txt", + "dist/angular-leaflet-directive.no-header.js" + ], + "dest": "dist/angular-leaflet-directive.js" + }, + "license-minified": { + "src": [ + "src/header-MIT-license.txt", + "dist/angular-leaflet-directive.min.no-header.js" + ], + "dest": "dist/angular-leaflet-directive.min.js" + }, + "examples": { + "options": { + "banner": "(function(angular){ \nvar app = angular.module('webapp');\n", + "footer": "}(angular));" + }, + "src": ["examples/js/controllers/*.js"], + "dest": "examples/js/controllers.js" + } +} diff --git a/grunt/concurrent.js b/grunt/concurrent.js deleted file mode 100644 index 14c76b5f..00000000 --- a/grunt/concurrent.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -module.exports = function (grunt, options) { - return { - watchServe: { - tasks: ['watch:fast', 'connect:webserver'], - options: { - logConcurrentOutput: true - } - }, - chrome: { - tasks: ['karma:unit-chrome', 'watch:chrome'], - options: { - logConcurrentOutput: true - } - }, - unit: { - tasks: ['karma:unit', 'watch:unit'], - options: { - logConcurrentOutput: true - } - }, - 'unit-mocha': { - tasks: ['karma:unit-mocha', 'watch:unit-mocha'], - options: { - logConcurrentOutput: true - } - } - } -}; diff --git a/grunt/connect.js b/grunt/connect.js deleted file mode 100644 index d6c64aca..00000000 --- a/grunt/connect.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; -var getAvailPort = require('./utils/getAvailPort'); -var port = getAvailPort(8888); - -module.exports = function (grunt, options) { - return { - options: { - base: '' - }, - webserver: { - options: { - port: port, - keepalive: true - } - }, - devserver: { - options: { - port: 8888 - } - }, - testserver: { - options: { - port: 9999 - } - }, - coverage: { - options: { - base: 'coverage/', - directory: 'coverage/', - port: 5555, - keepalive: true - } - } - }; -}; diff --git a/grunt/connect.json b/grunt/connect.json new file mode 100644 index 00000000..c051f8a0 --- /dev/null +++ b/grunt/connect.json @@ -0,0 +1,18 @@ +{ + "options": { + "base": "" + }, + "testserver": { + "options": { + "port": 9999 + } + }, + "coverage": { + "options": { + "base": "coverage/", + "directory": "coverage/", + "port": 5555, + "keepalive": true + } + } +} diff --git a/grunt/conventionalChangelog.json b/grunt/conventionalChangelog.json new file mode 100644 index 00000000..c957f789 --- /dev/null +++ b/grunt/conventionalChangelog.json @@ -0,0 +1,7 @@ +{ + "options": { + "changelogOpts": { + "preset": "angular" + } + } +} diff --git a/grunt/coveralls.js b/grunt/coveralls.js deleted file mode 100644 index ad35b665..00000000 --- a/grunt/coveralls.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -module.exports = function (grunt, options) { - // Options - return { - options: { - debug: true, - coverage_dir: 'coverage' - } - }; -}; diff --git a/grunt/jscs.json b/grunt/jscs.json new file mode 100644 index 00000000..67996e02 --- /dev/null +++ b/grunt/jscs.json @@ -0,0 +1,7 @@ + { + "src": ["src/directives/*.js", "src/services/**/*.js", "test/**/*.js"], + "options": { + "config": ".jscsrc", + "fix": true + } +} diff --git a/grunt/jshint.js b/grunt/jshint.js deleted file mode 100644 index 19da4903..00000000 --- a/grunt/jshint.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -module.exports = function (grunt, options) { - return { - options: { - node: true, - browser: true, - esnext: true, - bitwise: true, - curly: false, - eqeqeq: true, - immed: true, - indent: 4, - latedef: true, - newcap: true, - noarg: true, - regexp: true, - undef: true, - unused: true, - trailing: true, - smarttabs: true, - globals: { - angular: false, - L: false, - lvector: false, - cartodb: false, - // Jasmine - jasmine : false, - isCommonJS : false, - exports : false, - spyOn : false, - it : false, - xit : false, - expect : false, - runs : false, - waits : false, - waitsFor : false, - beforeEach : false, - afterEach : false, - describe : false, - xdescribe : false, - - // Protractor - protractor: false, - browser: false, - by: false, - element: false - } - }, - source: { - src: ['src/directives/*.js', 'src/services/*.js'] - }, - tests: { - src: ['test/unit/*.js', 'test/e2e/*.js'] - }, - grunt: { - src: ['Gruntfile.js'] - } - }; -}; diff --git a/grunt/jshint.json b/grunt/jshint.json new file mode 100644 index 00000000..0ddc818c --- /dev/null +++ b/grunt/jshint.json @@ -0,0 +1,14 @@ + { + "options": { + "jshintrc": true + }, + "source": { + "src": ["src/directives/*.js", "src/services/**/*.js"] + }, + "tests": { + "src": ["test/unit/*.js", "test/e2e/*.js"] + }, + "grunt": { + "src": ["Gruntfile.js"] + } +} diff --git a/grunt/karma.js b/grunt/karma.js deleted file mode 100644 index edfb3ada..00000000 --- a/grunt/karma.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - - -module.exports = function (grunt, options) { - return { - unit: { - configFile: 'test/karma-unit.conf.js', - autoWatch: false, - singleRun: true - }, - 'unit-mocha': { - configFile: 'test/karma-unit.conf.js', - autoWatch: false, - singleRun: true, - reporters: ['mocha'] - }, - 'unit-dots': { - configFile: 'test/karma-unit.conf.js', - autoWatch: false, - singleRun: true, - reporters: ['dots'] - }, - 'unit-chrome': { - configFile: 'test/karma-unit.conf.js', - browsers: ['Chrome'], - autoWatch: true, - singleRun: false - }, - 'unit-chrome-mocha': { - configFile: 'test/karma-unit.conf.js', - browsers: ['Chrome'], - autoWatch: true, - singleRun: false, - reporters: ['mocha'] - }, - 'unit-chrome-once': { - configFile: 'test/karma-unit.conf.js', - browsers: ['Chrome'], - autoWatch: true, - singleRun: true - }, - unit_coverage: { - configFile: 'test/karma-unit.conf.js', - autoWatch: false, - singleRun: true, - //logLevel: 'DEBUG', - reporters: ['progress', 'coverage'], - preprocessors: { - 'test/**/**/*.coffee': ['coffee'], - 'dist/angular-leaflet-directive.js': ['coverage'] - }, - coverageReporter: { - reporters:[ - {type: 'lcov', dir:'coverage/', subdir:'report'}, - {type: 'text-summary', dir:'coverage/', subdir:'report'} - ] - } - } - }; -}; diff --git a/grunt/karma.json b/grunt/karma.json new file mode 100644 index 00000000..ea87cb24 --- /dev/null +++ b/grunt/karma.json @@ -0,0 +1,22 @@ +{ + "unit": { + "configFile": "test/karma-unit.conf.js", + "autoWatch": false, + "singleRun": true + }, + "unit_coverage": { + "configFile": "test/karma-unit.conf.js", + "autoWatch": false, + "singleRun": true, + "reporters": ["progress", "coverage"], + "preprocessors": { + "dist/angular-leaflet-directive.js": ["coverage"] + }, + "coverageReporter": { + "reporters": [ + { "type": "lcov", "dir": "coverage/", "subdir": "report" }, + { "type": "text-summary", "dir": "coverage/", "subdir": "report" } + ] + } + } +} diff --git a/grunt/ngAnnotate.js b/grunt/ngAnnotate.js deleted file mode 100644 index 098a6290..00000000 --- a/grunt/ngAnnotate.js +++ /dev/null @@ -1,12 +0,0 @@ - 'use strict'; - - module.exports = function ngAnnotate(grunt, options) { - return { - options: {}, - dist: { - files: { - 'dist/angular-leaflet-directive.js': [ 'dist/angular-leaflet-directive.pre.js' ] - } - } - }; -}; diff --git a/grunt/ngAnnotate.json b/grunt/ngAnnotate.json new file mode 100644 index 00000000..2522a73d --- /dev/null +++ b/grunt/ngAnnotate.json @@ -0,0 +1,8 @@ +{ + "options": {}, + "dist": { + "files": { + "dist/angular-leaflet-directive.no-header.js": [ "dist/angular-leaflet-directive.pre.js" ] + } + } +} diff --git a/grunt/open.js b/grunt/open.js deleted file mode 100644 index 34583235..00000000 --- a/grunt/open.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict'; - -module.exports = function (grunt, options) { - return { - devserver: { - path: 'http://localhost:8888' - }, - coverage: { - path: 'http://localhost:5555' - } - }; -}; diff --git a/grunt/open.json b/grunt/open.json new file mode 100644 index 00000000..9196e9c9 --- /dev/null +++ b/grunt/open.json @@ -0,0 +1,8 @@ +{ + "devserver": { + "path": "http://localhost:8888" + }, + "coverage": { + "path": "http://localhost:5555" + } +} diff --git a/grunt/pkg.js b/grunt/pkg.js deleted file mode 100644 index 439f310d..00000000 --- a/grunt/pkg.js +++ /dev/null @@ -1,13 +0,0 @@ -'use strict'; - -module.exports = function (grunt, options) { - var pkgFunction = function(){ - return grunt.file.readJSON('package.json') - }; - //THIS extension forces the banner or whatever uses pkgFunction to always get the latest version - //where as pkg is only done once at grunt init. - _.extend(options, { - pkgFunction: pkgFunction - }); - return pkgFunction(); -}; diff --git a/grunt/protractor.js b/grunt/protractor.js deleted file mode 100644 index d48a7b34..00000000 --- a/grunt/protractor.js +++ /dev/null @@ -1,23 +0,0 @@ -'use strict'; - -module.exports = function (grunt, options) { - return { - options: { - keepAlive: false, - configFile: 'test/protractor.conf.js', - args: { - specs: [ 'test/e2e/*.js' ] - } - }, - run: {}, - saucelabs: { - options: { - args: { - baseUrl: "http://tombatossals.github.io/angular-leaflet-directive/examples/", - sauceUser: process.env.SAUCE_USERNAME, - sauceKey: process.env.SAUCE_ACCESS_KEY - } - } - } - }; -}; diff --git a/grunt/protractor.json b/grunt/protractor.json new file mode 100644 index 00000000..7d4c8d5d --- /dev/null +++ b/grunt/protractor.json @@ -0,0 +1,20 @@ +{ + "options": { + "keepAlive": false, + "configFile": "test/protractor.conf.js", + "nocolor": false, + "args": { + "specs": [ "test/e2e/*.js" ] + } + }, + "run": {}, + "saucelabs": { + "options": { + "args": { + "baseUrl": "http://tombatossals.github.io/angular-leaflet-directive/examples/", + "sauceUser": "<%= saucelabs.SAUCE_USERNAME %>", + "sauceKey": "<% saucelabs.SAUCE_ACCESS_KEY %>" + } + } + } +} diff --git a/grunt/shell.js b/grunt/shell.js deleted file mode 100644 index 2f11722f..00000000 --- a/grunt/shell.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; - -module.exports = function(grunt, options) { - return { - options: { - stdout: true - }, - selenium: { - command: 'node node_modules/protractor/bin/webdriver-manager start', - options: { - stdout: false, - async: true - } - }, - protractor_update: { - command: 'node node_modules/protractor/bin/webdriver-manager update' - }, - npm_install: { - command: 'npm install' - }, - examples: { - command: 'node generate-examples.js' - } - }; -}; diff --git a/grunt/shell.json b/grunt/shell.json new file mode 100644 index 00000000..9774b67d --- /dev/null +++ b/grunt/shell.json @@ -0,0 +1,21 @@ + { + "options": { + "stdout": true + }, + "selenium": { + "command": "node node_modules/protractor/bin/webdriver-manager start", + "options": { + "stdout": false, + "async": true + } + }, + "protractor_update": { + "command": "node node_modules/protractor/bin/webdriver-manager update" + }, + "npm_install": { + "command": "npm install" + }, + "examples": { + "command": "node generate-examples.js" + } +} diff --git a/grunt/uglify.js b/grunt/uglify.js deleted file mode 100644 index f8472073..00000000 --- a/grunt/uglify.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -module.exports = function (grunt, options) { - return { - options: { - banner: require('./utils/banner') - }, - dist: { - files: { - 'dist/<%= pkg.name %>.min.no-header.js': ['dist/angular-leaflet-directive.js'] - } - } - }; -}; diff --git a/grunt/uglify.json b/grunt/uglify.json new file mode 100644 index 00000000..f53aa71c --- /dev/null +++ b/grunt/uglify.json @@ -0,0 +1,11 @@ +{ + "dist": { + "options": { + "banner": "/*!\n* <%= pkg.name %> <%= pkg.version %> <%= grunt.template.today(\"yyyy-mm-dd\") %>\n* <%= pkg.description %>\n* <%= pkg.repository.type %>: <%= pkg.repository.url %>\n*/\n(function(angular){\n'use strict';\n", + "footer": "\n}(angular));" + }, + "files": { + "dist/<%= pkg.name %>.min.no-header.js": ["dist/<%= pkg.name %>.no-header.js"] + } + } +} diff --git a/grunt/utils/banner.js b/grunt/utils/banner.js deleted file mode 100644 index dbc3ca7e..00000000 --- a/grunt/utils/banner.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = - '/*!\n' + - '* <%= pkg.name %> <%= pkgFunction().version %> <%= grunt.template.today(\"yyyy-mm-dd\") %>\n' + - '* <%= pkg.description %>\n' + - '* <%= pkg.repository.type %>: <%= pkg.repository.url %>\n' + - '*/\n' diff --git a/grunt/utils/getAvailPort.js b/grunt/utils/getAvailPort.js deleted file mode 100644 index 5c02bd25..00000000 --- a/grunt/utils/getAvailPort.js +++ /dev/null @@ -1,14 +0,0 @@ -var exec = require('shelljs').exec; - -var isPortOpen = function(port){ - var portResponse = exec('lsof -i:' + port + " | tail -n 1 | awk '{print $2}'", {silent:true}).output; - return portResponse? false: true; -} - -module.exports = function(startPort){ - while (!isPortOpen(startPort)){ - startPort += 1; - } - - return startPort; -} diff --git a/grunt/watch.js b/grunt/watch.js deleted file mode 100644 index 1198cff6..00000000 --- a/grunt/watch.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict'; -var getAvailPort = require('./utils/getAvailPort'); -var port = getAvailPort(7777); - -var _files = ['src/**/*.js', 'test/unit/**.js', 'test/unit/**.coffee', 'test/e2e/**.js']; - -module.exports = function(grunt, options) { - return { - options: { - livereload: port - }, - fast: { - files: _files, - tasks: [ - 'fast-build', - 'uglify', - 'concat:license' - ] - }, - source: { - files: _files, - tasks: [ - 'fast-build', - 'uglify', - 'test-unit', - 'concat:license' - ] - }, - unit: { - files: _files, - tasks: [ - 'fast-build', - 'karma:unit' - ] - }, - 'unit-mocha': { - files: _files, - tasks: [ - 'fast-build', - 'karma:unit-mocha' - ] - }, - chrome: { - files: _files, - tasks: [ - 'fast-build', - 'karma:unit-chrome' - ] - }, - examples: { - files: ['examples/*.html'], - tasks: [ - 'examples' - ] - } - }; -}; diff --git a/grunt/watch.json b/grunt/watch.json new file mode 100644 index 00000000..8cadf270 --- /dev/null +++ b/grunt/watch.json @@ -0,0 +1,9 @@ +{ + "options": { + "livereload": 7777 + }, + "fast": { + "files": [ "src/**/*.js", "test/unit/**.js", "test/e2e/**.js" ], + "tasks": [ "fast-build" ] + } +} diff --git a/package.json b/package.json index 26c871e3..86297bca 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "author": "https://github.com/tombatossals/angular-leaflet-directive/graphs/contributors", "name": "angular-leaflet-directive", + "version": "0.10.1", "description": "angular-leaflet-directive - An AngularJS directive to easily interact with Leaflet maps", - "version": "0.8.6", "homepage": "http://tombatossals.github.io/angular-leaflet-directive/", "repository": { "type": "git", @@ -16,53 +16,47 @@ "license": "MIT", "devDependencies": { "grunt": "^0.4.5", - "grunt-angular-architecture-graph": "^0.2.6", "grunt-bower-task": "^0.4.0", - "grunt-bump": "^0.3.0", - "grunt-concurrent": "^1.0.0", "grunt-contrib-clean": "^0.6.0", "grunt-contrib-concat": "^0.5.1", - "grunt-contrib-connect": "^0.10.1", + "grunt-contrib-connect": "^0.11.2", "grunt-contrib-jshint": "^0.11.2", - "grunt-contrib-uglify": "^0.9.1", + "grunt-contrib-uglify": "^0.10.0", "grunt-contrib-watch": "^0.6.1", - "grunt-karma": "^0.10.1", - "grunt-karma-coveralls": "^2.5.3", - "grunt-ng-annotate": "^0.10.0", + "grunt-conventional-changelog": "^5.0.0", + "grunt-graphviz": "^0.1.1", + "grunt-jscs": "^2.3.0", + "grunt-karma": "^0.12.1", + "grunt-ng-annotate": "^1.0.1", "grunt-open": "^0.2.3", "grunt-protractor-runner": "^2.0.0", "grunt-shell": "^1.1.2", "grunt-shell-spawn": "^0.3.2", "jasmine-core": "^2.2.0", - "jsdom": ">= 0.1.23 < 4.0.0", - "karma": "0.12.32", - "karma-chrome-launcher": "^0.1.8", - "karma-coffee-preprocessor": "^0.2.1", - "karma-coverage": "^0.3.1", - "karma-firefox-launcher": "^0.1.4", - "karma-html2js-preprocessor": "^0.1.0", - "karma-jasmine": "^0.3.5", - "karma-mocha-reporter": "1.0.2", - "karma-phantomjs-launcher": "^0.1.4", - "karma-requirejs": "^0.2.2", - "karma-script-launcher": "^0.1.0", - "load-grunt-config": "^0.17.0", - "lodash": "^3.7.0", - "matchdep": "^0.3.0", + "jsdom": "^7.0.2", + "karma": "^0.13.15", + "karma-coverage": "^0.5.3", + "karma-jasmine": "^0.3.6", + "karma-phantomjs-launcher": "^0.2.1", + "load-grunt-config": "^0.19.0", + "matchdep": "^1.0.0", "mkdirp": "^0.5.0", + "phantomjs": "1.9", "protractor": "^2.0.0", "q": "^1.2.0", - "shelljs": "^0.4.0", - "grunt-conventional-changelog": "^1.2.2", - "grunt-graphviz": "^0.1.1", - "karma-jasmine": "^0.3.5" + "requirejs": "^2.1.20", + "semantic-release": "^4.3.5", + "shelljs": "^0.5.3" }, "scripts": { "test": "grunt travis --verbose", "karmaChrome": "grunt test-unit-chrome", - "karmaChromeOnce": "grunt karma:unit-chrome-once" + "karmaChromeOnce": "grunt karma:unit-chrome-once", + "semantic-release": "semantic-release pre && npm publish && semantic-release post" }, "main": "dist/angular-leaflet-directive", "dependencies": { + "angular": "1.x", + "leaflet": "0.7.x" } } diff --git a/src/directives/bounds.js b/src/directives/bounds.js index 0cf74b60..d1b1764f 100644 --- a/src/directives/bounds.js +++ b/src/directives/bounds.js @@ -1,74 +1,86 @@ -angular.module("leaflet-directive").directive('bounds', function ($log, $timeout, $http, leafletHelpers, nominatimService, leafletBoundsHelpers) { - return { - restrict: "A", - scope: false, - replace: false, - require: [ 'leaflet' ], +angular.module('leaflet-directive').directive('bounds', function($log, $timeout, $http, leafletHelpers, nominatimService, leafletBoundsHelpers) { - 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] '; + return { + restrict: 'A', + scope: false, + replace: false, + require: ['leaflet'], - var emptyBounds = function(bounds) { - return (bounds._southWest.lat === 0 && bounds._southWest.lng === 0 && - bounds._northEast.lat === 0 && bounds._northEast.lng === 0); - }; + 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] '; - mapController.getMap().then(function (map) { - leafletScope.$on('boundsChanged', function (event) { - var scope = event.currentScope; - var bounds = map.getBounds(); + var emptyBounds = function(bounds) { + return (bounds._southWest.lat === 0 && bounds._southWest.lng === 0 && + bounds._northEast.lat === 0 && bounds._northEast.lng === 0); + }; - if (emptyBounds(bounds) || scope.settingBoundsFromScope) { - return; - } - 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; - } - }); + mapController.getMap().then(function(map) { + leafletScope.$on('boundsChanged', function(event) { + var scope = event.currentScope; + var bounds = map.getBounds(); - var lastNominatimQuery; - leafletScope.$watch('bounds', function (bounds) { - 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; - } + if (emptyBounds(bounds) || scope.settingBoundsFromScope) { + 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); + 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); + }); + }, + }; }); diff --git a/src/directives/center.js b/src/directives/center.js index 02cb237c..afad58fb 100644 --- a/src/directives/center.js +++ b/src/directives/center.js @@ -1,187 +1,231 @@ -angular.module("leaflet-directive").directive('center', - function ($log, $q, $location, $timeout, leafletMapDefaults, leafletHelpers, leafletBoundsHelpers, leafletEvents) { - - var isDefined = leafletHelpers.isDefined, - isNumber = leafletHelpers.isNumber, - isSameCenterOnMap = leafletHelpers.isSameCenterOnMap, - safeApply = leafletHelpers.safeApply, - isValidCenter = leafletHelpers.isValidCenter, - isValidBounds = leafletBoundsHelpers.isValidBounds, - isUndefinedOrEmpty = leafletHelpers.isUndefinedOrEmpty, - errorHeader = leafletHelpers.errorHeader; - - var shouldInitializeMapWithBounds = function(bounds, center) { +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", + var _leafletCenter; + return { + restrict: 'A', scope: false, replace: false, require: 'leaflet', - controller: function () { - _leafletCenter = $q.defer(); - this.getCenter = function() { - return _leafletCenter.promise; - }; + controller: function() { + _leafletCenter = $q.defer(); + this.getCenter = function() { + return _leafletCenter.promise; + }; }, + link: function(scope, element, attrs, controller) { - var leafletScope = controller.getLeafletScope(), - centerModel = leafletScope.center; - - controller.getMap().then(function(map) { - var defaults = leafletMapDefaults.getDefaults(attrs.id); - - if (attrs.center.search("-") !== -1) { - $log.error(errorHeader + ' The "center" variable can\'t use a "-" on its key name: "' + attrs.center + '".'); - 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.center,{ - 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 leafletScope = controller.getLeafletScope(); + var centerModel = leafletScope[directiveName]; - var urlCenterHash, 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; + 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), }; - 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.center, { - lat: urlCenter.lat, - lng: urlCenter.lng, - zoom: urlCenter.zoom - }); - } - }); + } } - leafletScope.$watch("center", function(center) { - //$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); - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - $timeout(function() { - leafletScope.settingCenterFromScope = false; - //$log.debug("allow center scope updates"); - }); - }, true); - - map.whenReady(function() { - mapReady = true; - }); + return centerParam; + }; - map.on('moveend', function(/* event */) { - // Resolve the center after the first map position - _leafletCenter.resolve(); - leafletEvents.notifyCenterUrlHashChanged(leafletScope, map, attrs, $location.search()); - //$log.debug("updated center on map..."); - if (isSameCenterOnMap(centerModel, map) || scope.settingCenterFromScope) { - //$log.debug("same center in model, no need to update again."); - return; - } - safeApply(leafletScope, function(scope) { - if (!leafletScope.settingCenterFromScope) { - //$log.debug("updating center model...", map.getCenter(), map.getZoom()); - angular.extend(scope.center,{ - lat: map.getCenter().lat, - lng: map.getCenter().lng, - zoom: map.getZoom(), - autoDiscover: false - }); - } - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - }); - }); + urlCenterHash = extractCenterFromUrl(); + + leafletScope.$on('$locationChangeSuccess', function(event) { + var scope = event.currentScope; - 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); - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - } else { - map.setView([defaults.center.lat, defaults.center.lng], defaults.center.zoom); - leafletEvents.notifyCenterChangedToBounds(leafletScope, map); - } - }); + //$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]); }); diff --git a/src/directives/controls.js b/src/directives/controls.js index 36b7ea1b..eeba332c 100644 --- a/src/directives/controls.js +++ b/src/directives/controls.js @@ -1,59 +1,71 @@ -angular.module("leaflet-directive").directive('controls', function ($log, leafletHelpers, leafletControlHelpers) { - return { - restrict: "A", - scope: false, - replace: false, - require: '?^leaflet', - - link: function(scope, element, attrs, controller) { - if(!controller) { - return; - } +angular.module('leaflet-directive').directive('controls', 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 leafletControls = {}; - var errorHeader = leafletHelpers.errorHeader + ' [Controls] '; + 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) { + controller.getMap().then(function(map) { - leafletScope.$watchCollection('controls', function(newControls) { + 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]; - } - } + // Delete controls from the array + for (var name in leafletControls) { + if (!isDefined(newControls[name])) { + if (map.hasControl(leafletControls[name])) { + map.removeControl(leafletControls[name]); + } - for (var newName in newControls) { - var control; + delete leafletControls[name]; + } + } - var controlType = isDefined(newControls[newName].type) ? newControls[newName].type : newName; + for (var newName in newControls) { + var control; - if (!isValidControlType(controlType)) { - $log.error(errorHeader + ' Invalid control type: ' + controlType + '.'); - return; - } + var controlType = isDefined(newControls[newName].type) ? newControls[newName].type : newName; - if (controlType !== 'custom') { - control = createControl(controlType, newControls[newName]); - } else { - control = newControls[newName]; - } - map.addControl(control); + if (!isValidControlType(controlType)) { + $log.error(errorHeader + ' Invalid control type: ' + controlType + '.'); + return; + } - leafletControls[newName] = control; - } + 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; + } + } + } - }); + }); - }); - } - }; + }); + }, + }; }); diff --git a/src/directives/decorations.js b/src/directives/decorations.js index 08d8c608..89ca1c03 100644 --- a/src/directives/decorations.js +++ b/src/directives/decorations.js @@ -1,59 +1,60 @@ -angular.module("leaflet-directive").directive("decorations", function($log, leafletHelpers) { - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', - - link: function(scope, element, attrs, controller) { - var leafletScope = controller.getLeafletScope(), - PolylineDecoratorPlugin = leafletHelpers.PolylineDecoratorPlugin, - isDefined = leafletHelpers.isDefined, - 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], - newDecoration = createDecoration(decorationData); - - if (isDefined(newDecoration)) { - leafletDecorations[newName] = newDecoration; - map.addLayer(newDecoration); - setDecorationOptions(newDecoration, decorationData); - } - } - }, true); - }); - } - }; +angular.module('leaflet-directive').directive('decorations', 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); + }); + }, + }; }); diff --git a/src/directives/eventBroadcast.js b/src/directives/eventBroadcast.js index f179ce71..3b8a80d1 100644 --- a/src/directives/eventBroadcast.js +++ b/src/directives/eventBroadcast.js @@ -1,57 +1,59 @@ -angular.module("leaflet-directive").directive('eventBroadcast', function ($log, $rootScope, leafletHelpers, leafletEvents, leafletIterators) { - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', - - link: function(scope, element, attrs, controller) { - var isObject = leafletHelpers.isObject, - isDefined = leafletHelpers.isDefined, - leafletScope = controller.getLeafletScope(), - eventBroadcast = leafletScope.eventBroadcast, - availableMapEvents = leafletEvents.getAvailableMapEvents(), - addEvents = leafletEvents.addEvents; - - controller.getMap().then(function(map) { - - var mapEvents = [], - 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('eventBroadcast', 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); + }); + }, + }; }); diff --git a/src/directives/geojson.js b/src/directives/geojson.js index 5cd1f8a8..71f71b63 100644 --- a/src/directives/geojson.js +++ b/src/directives/geojson.js @@ -1,126 +1,129 @@ -angular.module("leaflet-directive") -.directive('geojson', function ($log, $rootScope, leafletData, leafletHelpers, - leafletWatchHelpers, leafletDirectiveControlsHelpers,leafletIterators, - leafletGeoJsonEvents) { - - var _maybeWatch = leafletWatchHelpers.maybeWatch, - _watchOptions = leafletHelpers.watchOptions, - _extendDirectiveControls = leafletDirectiveControlsHelpers.extend, - hlp = leafletHelpers, - $it = leafletIterators; - - return { - restrict: "A", - scope: false, - replace: false, - require: 'leaflet', - - link: function(scope, element, attrs, controller) { - var isDefined = leafletHelpers.isDefined, - leafletScope = controller.getLeafletScope(), - leafletGeoJSON = {}, - _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(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('geojson', 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(geojson, maybeName) { + 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); + }); + }); + }, + }; }); diff --git a/src/directives/layercontrol.js b/src/directives/layercontrol.js index c10c3523..0c0d661e 100644 --- a/src/directives/layercontrol.js +++ b/src/directives/layercontrol.js @@ -1,286 +1,313 @@ -angular.module("leaflet-directive").directive('layercontrol', 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: '@' +angular.module('leaflet-directive').directive('layercontrol', 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: 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(); }, - replace: true, - transclude: false, - require: '^leaflet', - controller: function ($scope, $element, $sce) { - $log.debug('[Angular Directive - Layers] layers', $scope, $element); - var safeApply = leafletHelpers.safeApply, - 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; - } + + 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); } + }); } + } }); + }); + }, - 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); + 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; } + } }, - template: - '
            ' + - '

            {{ title }}

            ' + - '
            ' + - '
            {{ baseTitle }}
            ' + - '
            ' + - '