ffffng/app/bower_components/angular-leaflet-directive/dist/angular-leaflet-directive.js

2876 lines
120 KiB
JavaScript

(function () {
'use strict';
angular.module('leaflet-directive', []).directive('leaflet', [
'$q',
'leafletData',
'leafletMapDefaults',
'leafletHelpers',
'leafletEvents',
function ($q, leafletData, leafletMapDefaults, leafletHelpers, leafletEvents) {
var _leafletMap;
return {
restrict: 'EA',
replace: true,
scope: {
center: '=center',
defaults: '=defaults',
maxbounds: '=maxbounds',
bounds: '=bounds',
markers: '=markers',
legend: '=legend',
geojson: '=geojson',
paths: '=paths',
tiles: '=tiles',
layers: '=layers',
controls: '=controls',
eventBroadcast: '=eventBroadcast'
},
template: '<div class="angular-leaflet-map"></div>',
controller: [
'$scope',
function ($scope) {
_leafletMap = $q.defer();
this.getMap = function () {
return _leafletMap.promise;
};
this.getLeafletScope = function () {
return $scope;
};
}
],
link: function (scope, element, attrs) {
var isDefined = leafletHelpers.isDefined, defaults = leafletMapDefaults.setDefaults(scope.defaults, attrs.id), genDispatchMapEvent = leafletEvents.genDispatchMapEvent, mapEvents = leafletEvents.getAvailableMapEvents();
// Set width and height if they are defined
if (isDefined(attrs.width)) {
if (isNaN(attrs.width)) {
element.css('width', attrs.width);
} else {
element.css('width', attrs.width + 'px');
}
}
if (isDefined(attrs.height)) {
if (isNaN(attrs.height)) {
element.css('height', attrs.height);
} else {
element.css('height', attrs.height + 'px');
}
}
// Create the Leaflet Map Object with the options
var map = new L.Map(element[0], leafletMapDefaults.getMapCreationDefaults(attrs.id));
_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';
for (var i = 0; i < mapEvents.length; i++) {
var eventName = mapEvents[i];
map.on(eventName, genDispatchMapEvent(scope, eventName, logic), { eventName: eventName });
}
}
// Resolve the map object to the promises
map.whenReady(function () {
leafletData.setMap(map, attrs.id);
});
scope.$on('$destroy', function () {
leafletData.unresolveMap(attrs.id);
});
}
};
}
]);
angular.module('leaflet-directive').directive('center', [
'$log',
'$q',
'$location',
'leafletMapDefaults',
'leafletHelpers',
'leafletBoundsHelpers',
'leafletEvents',
function ($log, $q, $location, leafletMapDefaults, leafletHelpers, leafletBoundsHelpers, leafletEvents) {
var isDefined = leafletHelpers.isDefined, isNumber = leafletHelpers.isNumber, isSameCenterOnMap = leafletHelpers.isSameCenterOnMap, safeApply = leafletHelpers.safeApply, isValidCenter = leafletHelpers.isValidCenter, isEmpty = leafletHelpers.isEmpty, isUndefinedOrEmpty = leafletHelpers.isUndefinedOrEmpty;
var shouldInitializeMapWithBounds = function (bounds, center) {
return isDefined(bounds) && !isEmpty(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('The "center" variable can\'t use a "-" on his 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));
centerModel = map.getCenter();
safeApply(leafletScope, function (scope) {
scope.center = {
lat: map.getCenter().lat,
lng: map.getCenter().lng,
zoom: map.getZoom(),
autoDiscover: false
};
});
safeApply(leafletScope, function (scope) {
var mapBounds = map.getBounds();
var newScopeBounds = {
northEast: {
lat: mapBounds._northEast.lat,
lng: mapBounds._northEast.lng
},
southWest: {
lat: mapBounds._southWest.lat,
lng: mapBounds._southWest.lng
}
};
scope.bounds = newScopeBounds;
});
} else if (!isDefined(centerModel)) {
$log.error('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);
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('[AngularJS - Leaflet] 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);
map.setView([
center.lat,
center.lng
], center.zoom);
leafletEvents.notifyCenterChangedToBounds(leafletScope, map);
}, true);
map.whenReady(function () {
mapReady = true;
});
map.on('moveend', function () {
// 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)) {
//$log.debug("same center in model, no need to update again.");
return;
}
safeApply(leafletScope, function (scope) {
//$log.debug("updating center model...", map.getCenter(), map.getZoom());
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('[AngularJS - Leaflet] 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('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, 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);
});
}
};
}
]);
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, isDefined = leafletHelpers.isDefined, isFunction = leafletHelpers.isFunction, leafletScope = controller.getLeafletScope(), legend = leafletScope.legend;
var legendClass = legend.legendClass ? legend.legendClass : 'legend';
var position = legend.position || 'bottomright';
var leafletLegend;
controller.getMap().then(function (map) {
if (!isDefined(legend.url) && (!isArray(legend.colors) || !isArray(legend.labels) || legend.colors.length !== legend.labels.length)) {
$log.warn('[AngularJS - Leaflet] legend.colors and legend.labels must be set.');
} else if (isDefined(legend.url)) {
$log.info('[AngularJS - Leaflet] loading arcgis legend service.');
} else {
// TODO: Watch array legend.
leafletLegend = L.control({ position: position });
leafletLegend.onAdd = leafletLegendHelpers.getOnAddArrayLegend(legend, legendClass);
leafletLegend.addTo(map);
}
leafletScope.$watch('legend.url', function (newURL) {
if (!isDefined(newURL)) {
return;
}
$http.get(newURL).success(function (legendData) {
if (isDefined(leafletLegend)) {
leafletLegendHelpers.updateArcGISLegend(leafletLegend.getContainer(), legendData);
} else {
leafletLegend = L.control({ position: position });
leafletLegend.onAdd = leafletLegendHelpers.getOnAddArcGISLegend(legendData, legendClass);
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('geojson', [
'$log',
'$rootScope',
'leafletData',
'leafletHelpers',
function ($log, $rootScope, leafletData, leafletHelpers) {
return {
restrict: 'A',
scope: false,
replace: false,
require: 'leaflet',
link: function (scope, element, attrs, controller) {
var safeApply = leafletHelpers.safeApply, isDefined = leafletHelpers.isDefined, leafletScope = controller.getLeafletScope(), leafletGeoJSON = {};
controller.getMap().then(function (map) {
leafletScope.$watch('geojson', function (geojson) {
if (isDefined(leafletGeoJSON) && map.hasLayer(leafletGeoJSON)) {
map.removeLayer(leafletGeoJSON);
}
if (!(isDefined(geojson) && isDefined(geojson.data))) {
return;
}
var resetStyleOnMouseout = geojson.resetStyleOnMouseout, onEachFeature = geojson.onEachFeature;
if (!onEachFeature) {
onEachFeature = function (feature, layer) {
if (leafletHelpers.LabelPlugin.isLoaded() && isDefined(geojson.label)) {
layer.bindLabel(feature.properties.description);
}
layer.on({
mouseover: function (e) {
safeApply(leafletScope, function () {
geojson.selected = feature;
$rootScope.$broadcast('leafletDirectiveMap.geojsonMouseover', e);
});
},
mouseout: function (e) {
if (resetStyleOnMouseout) {
leafletGeoJSON.resetStyle(e.target);
}
safeApply(leafletScope, function () {
geojson.selected = undefined;
$rootScope.$broadcast('leafletDirectiveMap.geojsonMouseout', e);
});
},
click: function (e) {
safeApply(leafletScope, function () {
geojson.selected = feature;
$rootScope.$broadcast('leafletDirectiveMap.geojsonClick', geojson.selected, e);
});
}
});
};
}
geojson.options = {
style: geojson.style,
filter: geojson.filter,
onEachFeature: onEachFeature,
pointToLayer: geojson.pointToLayer
};
leafletGeoJSON = L.geoJson(geojson.data, geojson.options);
leafletData.setGeoJSON(leafletGeoJSON);
leafletGeoJSON.addTo(map);
});
});
}
};
}
]);
angular.module('leaflet-directive').directive('layers', [
'$log',
'$q',
'leafletData',
'leafletHelpers',
'leafletLayerHelpers',
'leafletControlHelpers',
function ($log, $q, leafletData, leafletHelpers, leafletLayerHelpers, leafletControlHelpers) {
var _leafletLayers;
return {
restrict: 'A',
scope: false,
replace: false,
require: 'leaflet',
controller: function () {
_leafletLayers = $q.defer();
this.getLayers = function () {
return _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) {
// Do we have a baselayers property?
if (!isDefined(layers) || !isDefined(layers.baselayers) || Object.keys(layers.baselayers).length === 0) {
// No baselayers property
$log.error('[AngularJS - Leaflet] At least one baselayer has to be defined');
return;
}
// We have baselayers to add to the map
_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) {
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) {
// Delete layers from the array
for (var name in leafletLayers.baselayers) {
if (!isDefined(newBaseLayers[name])) {
// Remove from the map if it's on it
if (map.hasLayer(leafletLayers.baselayers[name])) {
map.removeLayer(leafletLayers.baselayers[name]);
}
delete leafletLayers.baselayers[name];
}
}
// 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]);
}
}
}
}
if (Object.keys(leafletLayers.baselayers).length === 0) {
$log.error('[AngularJS - Leaflet] At least one baselayer has to be defined');
return;
}
//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) {
map.addLayer(leafletLayers.baselayers[Object.keys(layers.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) {
// Delete layers from the array
for (var name in leafletLayers.overlays) {
if (!isDefined(newOverlayLayers[name])) {
// 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];
}
}
// add new overlays
for (var newName in newOverlayLayers) {
if (!isDefined(leafletLayers.overlays[newName])) {
var testOverlayLayer = createLayer(newOverlayLayers[newName]);
if (isDefined(testOverlayLayer)) {
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]);
}
}
// 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('bounds', [
'$log',
'$timeout',
'leafletHelpers',
'leafletBoundsHelpers',
function ($log, $timeout, leafletHelpers, leafletBoundsHelpers) {
return {
restrict: 'A',
scope: false,
replace: false,
require: [
'leaflet',
'center'
],
link: function (scope, element, attrs, controller) {
var isDefined = leafletHelpers.isDefined, createLeafletBounds = leafletBoundsHelpers.createLeafletBounds, leafletScope = controller[0].getLeafletScope(), mapController = controller[0];
var emptyBounds = function (bounds) {
if (bounds._southWest.lat === 0 && bounds._southWest.lng === 0 && bounds._northEast.lat === 0 && bounds._northEast.lng === 0) {
return true;
}
return false;
};
mapController.getMap().then(function (map) {
leafletScope.$on('boundsChanged', function (event) {
var scope = event.currentScope;
var bounds = map.getBounds();
//$log.debug('updated map bounds...', bounds);
if (emptyBounds(bounds)) {
return;
}
var newScopeBounds = {
northEast: {
lat: bounds._northEast.lat,
lng: bounds._northEast.lng
},
southWest: {
lat: bounds._southWest.lat,
lng: bounds._southWest.lng
}
};
if (!angular.equals(scope.bounds, newScopeBounds)) {
//$log.debug('Need to update scope bounds.');
scope.bounds = newScopeBounds;
}
});
leafletScope.$watch('bounds', function (bounds) {
//$log.debug('updated bounds...', bounds);
if (!isDefined(bounds)) {
$log.error('[AngularJS - Leaflet] Invalid bounds');
return;
}
var leafletBounds = createLeafletBounds(bounds);
if (leafletBounds && !map.getBounds().equals(leafletBounds)) {
//$log.debug('Need to update map bounds.');
map.fitBounds(leafletBounds);
}
}, true);
});
}
};
}
]);
angular.module('leaflet-directive').directive('markers', [
'$log',
'$rootScope',
'$q',
'leafletData',
'leafletHelpers',
'leafletMapDefaults',
'leafletMarkersHelpers',
'leafletEvents',
function ($log, $rootScope, $q, leafletData, leafletHelpers, leafletMapDefaults, leafletMarkersHelpers, leafletEvents) {
return {
restrict: 'A',
scope: false,
replace: false,
require: [
'leaflet',
'?layers'
],
link: function (scope, element, attrs, controller) {
var mapController = controller[0], Helpers = leafletHelpers, isDefined = leafletHelpers.isDefined, isString = leafletHelpers.isString, leafletScope = mapController.getLeafletScope(), markers = leafletScope.markers, deleteMarker = leafletMarkersHelpers.deleteMarker, addMarkerWatcher = leafletMarkersHelpers.addMarkerWatcher, listenMarkerEvents = leafletMarkersHelpers.listenMarkerEvents, addMarkerToGroup = leafletMarkersHelpers.addMarkerToGroup, bindMarkerEvents = leafletEvents.bindMarkerEvents, createMarker = leafletMarkersHelpers.createMarker;
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;
};
}
if (!isDefined(markers)) {
return;
}
getLayers().then(function (layers) {
leafletData.setMarkers(leafletMarkers, attrs.id);
leafletScope.$watch('markers', function (newMarkers) {
// Delete markers from the array
for (var name in leafletMarkers) {
if (!isDefined(newMarkers) || !isDefined(newMarkers[name])) {
deleteMarker(leafletMarkers[name], map, layers);
delete leafletMarkers[name];
}
}
// add new markers
for (var newName in newMarkers) {
if (newName.search('-') !== -1) {
$log.error('The marker can\'t use a "-" on his key name: "' + newName + '".');
continue;
}
if (!isDefined(leafletMarkers[newName])) {
var markerData = newMarkers[newName];
var marker = createMarker(markerData);
if (!isDefined(marker)) {
$log.error('[AngularJS - Leaflet] Received invalid data on the marker ' + newName + '.');
continue;
}
leafletMarkers[newName] = marker;
// Bind message
if (isDefined(markerData.message)) {
marker.bindPopup(markerData.message, markerData.popupOptions);
}
// Add the marker to a cluster group if needed
if (isDefined(markerData.group)) {
addMarkerToGroup(marker, markerData.group, map);
}
// Show label if defined
if (Helpers.LabelPlugin.isLoaded() && isDefined(markerData.label) && isDefined(markerData.label.message)) {
marker.bindLabel(markerData.label.message, markerData.label.options);
}
// Check if the marker should be added to a layer
if (isDefined(markerData) && isDefined(markerData.layer)) {
if (!isString(markerData.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[markerData.layer])) {
$log.error('[AngularJS - Leaflet] A marker can only be added to a layer of type "group"');
continue;
}
var layerGroup = layers.overlays[markerData.layer];
if (!(layerGroup instanceof L.LayerGroup)) {
$log.error('[AngularJS - Leaflet] Adding a marker to an overlay needs a overlay of the type "group"');
continue;
}
// 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();
} // Add the marker to the map if it hasn't been added to a layer or to a group
} else if (!isDefined(markerData.group)) {
// We do not have a layer attr, so the marker goes to the map layer
map.addLayer(marker);
if (markerData.focus === true) {
marker.openPopup();
}
if (Helpers.LabelPlugin.isLoaded() && isDefined(markerData.label) && isDefined(markerData.label.options) && markerData.label.options.noHide === true) {
marker.showLabel();
}
}
// Should we watch for every specific marker on the map?
var shouldWatch = !isDefined(attrs.watchMarkers) || attrs.watchMarkers === 'true';
if (shouldWatch) {
addMarkerWatcher(marker, newName, leafletScope, layers, map);
listenMarkerEvents(marker, markerData, leafletScope);
}
bindMarkerEvents(marker, newName, markerData, leafletScope);
}
}
}, true);
});
});
}
};
}
]);
angular.module('leaflet-directive').directive('paths', [
'$log',
'leafletData',
'leafletMapDefaults',
'leafletHelpers',
'leafletPathsHelpers',
'leafletEvents',
function ($log, leafletData, leafletMapDefaults, leafletHelpers, leafletPathsHelpers, leafletEvents) {
return {
restrict: 'A',
scope: false,
replace: false,
require: 'leaflet',
link: function (scope, element, attrs, controller) {
var isDefined = leafletHelpers.isDefined, leafletScope = controller.getLeafletScope(), paths = leafletScope.paths, createPath = leafletPathsHelpers.createPath, bindPathEvents = leafletEvents.bindPathEvents, setPathOptions = leafletPathsHelpers.setPathOptions;
controller.getMap().then(function (map) {
var defaults = leafletMapDefaults.getDefaults(attrs.id);
if (!isDefined(paths)) {
return;
}
var leafletPaths = {};
leafletData.setPaths(leafletPaths, attrs.id);
// Function for listening every single path once created
var watchPathFn = function (leafletPath, name) {
var clearWatch = leafletScope.$watch('paths.' + name, function (pathData) {
if (!isDefined(pathData)) {
map.removeLayer(leafletPath);
clearWatch();
return;
}
setPathOptions(leafletPath, pathData.type, pathData);
}, true);
};
leafletScope.$watch('paths', function (newPaths) {
// Create the new paths
for (var newName in newPaths) {
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);
}
// Show label if defined
if (leafletHelpers.LabelPlugin.isLoaded() && isDefined(pathData.label) && isDefined(pathData.label.message)) {
newPath.bindLabel(pathData.label.message, pathData.label.options);
}
// Listen for changes on the new path
if (isDefined(newPath)) {
leafletPaths[newName] = newPath;
map.addLayer(newPath);
watchPathFn(newPath, newName);
}
bindPathEvents(newPath, newName, pathData, leafletScope);
}
}
// Delete paths (by name) from the array
for (var name in leafletPaths) {
if (!isDefined(newPaths[name])) {
delete leafletPaths[name];
}
}
}, true);
});
}
};
}
]);
angular.module('leaflet-directive').directive('controls', [
'$log',
'leafletHelpers',
function ($log, leafletHelpers) {
return {
restrict: 'A',
scope: false,
replace: false,
require: '?^leaflet',
link: function (scope, element, attrs, controller) {
if (!controller) {
return;
}
var isDefined = leafletHelpers.isDefined, leafletScope = controller.getLeafletScope(), controls = leafletScope.controls;
controller.getMap().then(function (map) {
if (isDefined(L.Control.Draw) && isDefined(controls.draw)) {
var drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
var options = { edit: { featureGroup: drawnItems } };
angular.extend(options, controls.draw.options);
var drawControl = new L.Control.Draw(options);
map.addControl(drawControl);
}
if (isDefined(controls.custom)) {
for (var i in controls.custom) {
map.addControl(controls.custom[i]);
}
}
});
}
};
}
]);
angular.module('leaflet-directive').directive('eventBroadcast', [
'$log',
'$rootScope',
'leafletHelpers',
'leafletEvents',
function ($log, $rootScope, leafletHelpers, leafletEvents) {
return {
restrict: 'A',
scope: false,
replace: false,
require: 'leaflet',
link: function (scope, element, attrs, controller) {
var isObject = leafletHelpers.isObject, leafletScope = controller.getLeafletScope(), eventBroadcast = leafletScope.eventBroadcast, availableMapEvents = leafletEvents.getAvailableMapEvents(), genDispatchMapEvent = leafletEvents.genDispatchMapEvent;
controller.getMap().then(function (map) {
var mapEvents = [];
var i;
var eventName;
var logic = 'broadcast';
if (isObject(eventBroadcast)) {
// We have a possible valid object
if (eventBroadcast.map === undefined || eventBroadcast.map === null) {
// We do not have events enable/disable do we do nothing (all enabled by default)
mapEvents = availableMapEvents;
} else if (typeof eventBroadcast.map !== 'object') {
// 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 !== undefined && eventBroadcast.map.logic !== null) {
// We take care of possible propagation 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 if (eventBroadcast.map.logic === 'emit') {
logic = 'emit';
}
}
// Enable / Disable
var mapEventsEnable = false, mapEventsDisable = false;
if (eventBroadcast.map.enable !== undefined && eventBroadcast.map.enable !== null) {
if (typeof eventBroadcast.map.enable === 'object') {
mapEventsEnable = true;
}
}
if (eventBroadcast.map.disable !== undefined && eventBroadcast.map.disable !== null) {
if (typeof eventBroadcast.map.disable === 'object') {
mapEventsDisable = true;
}
}
if (mapEventsEnable && mapEventsDisable) {
// Both are active, this is an error
$log.warn('[AngularJS - Leaflet] can not enable and disable events at the time');
} else if (!mapEventsEnable && !mapEventsDisable) {
// Both are inactive, this is an error
$log.warn('[AngularJS - Leaflet] must enable or disable events');
} else {
// At this point the map object is OK, lets enable or disable events
if (mapEventsEnable) {
// Enable events
for (i = 0; i < eventBroadcast.map.enable.length; i++) {
eventName = eventBroadcast.map.enable[i];
// Do we have already the event enabled?
if (mapEvents.indexOf(eventName) !== -1) {
// Repeated event, this is an error
$log.warn('[AngularJS - Leaflet] This event ' + eventName + ' is already enabled');
} else {
// Does the event exists?
if (availableMapEvents.indexOf(eventName) === -1) {
// The event does not exists, this is an error
$log.warn('[AngularJS - Leaflet] This event ' + eventName + ' does not exist');
} else {
// All ok enable the event
mapEvents.push(eventName);
}
}
}
} else {
// Disable events
mapEvents = availableMapEvents;
for (i = 0; i < eventBroadcast.map.disable.length; i++) {
eventName = eventBroadcast.map.disable[i];
var index = mapEvents.indexOf(eventName);
if (index === -1) {
// The event does not exist
$log.warn('[AngularJS - Leaflet] This event ' + eventName + ' does not exist or has been already disabled');
} else {
mapEvents.splice(index, 1);
}
}
}
}
}
for (i = 0; i < mapEvents.length; i++) {
eventName = mapEvents[i];
map.on(eventName, genDispatchMapEvent(leafletScope, eventName, logic), { eventName: eventName });
}
} else {
// Not a valid object
$log.warn('[AngularJS - Leaflet] event-broadcast must be an object, check your model.');
}
});
}
};
}
]);
angular.module('leaflet-directive').directive('maxbounds', [
'$log',
'leafletMapDefaults',
'leafletBoundsHelpers',
function ($log, leafletMapDefaults, leafletBoundsHelpers) {
return {
restrict: 'A',
scope: false,
replace: false,
require: 'leaflet',
link: function (scope, element, attrs, controller) {
var leafletScope = controller.getLeafletScope(), isValidBounds = leafletBoundsHelpers.isValidBounds;
controller.getMap().then(function (map) {
leafletScope.$watch('maxbounds', function (maxbounds) {
if (!isValidBounds(maxbounds)) {
// Unset any previous maxbounds
map.setMaxBounds();
return;
}
var bounds = [
[
maxbounds.southWest.lat,
maxbounds.southWest.lng
],
[
maxbounds.northEast.lat,
maxbounds.northEast.lng
]
];
map.setMaxBounds(bounds);
map.fitBounds(bounds);
});
});
}
};
}
]);
angular.module('leaflet-directive').service('leafletData', [
'$log',
'$q',
'leafletHelpers',
function ($log, $q, leafletHelpers) {
var getDefer = leafletHelpers.getDefer, getUnresolvedDefer = leafletHelpers.getUnresolvedDefer, setResolvedDefer = leafletHelpers.setResolvedDefer;
var maps = {};
var tiles = {};
var layers = {};
var paths = {};
var markers = {};
var geoJSON = {};
this.setMap = function (leafletMap, scopeId) {
var defer = getUnresolvedDefer(maps, scopeId);
defer.resolve(leafletMap);
setResolvedDefer(maps, scopeId);
};
this.getMap = function (scopeId) {
var defer = getDefer(maps, scopeId);
return defer.promise;
};
this.unresolveMap = function (scopeId) {
var id = leafletHelpers.obtainEffectiveMapId(maps, scopeId);
maps[id] = undefined;
};
this.getPaths = function (scopeId) {
var defer = getDefer(paths, scopeId);
return defer.promise;
};
this.setPaths = function (leafletPaths, scopeId) {
var defer = getUnresolvedDefer(paths, scopeId);
defer.resolve(leafletPaths);
setResolvedDefer(paths, scopeId);
};
this.getMarkers = function (scopeId) {
var defer = getDefer(markers, scopeId);
return defer.promise;
};
this.setMarkers = function (leafletMarkers, scopeId) {
var defer = getUnresolvedDefer(markers, scopeId);
defer.resolve(leafletMarkers);
setResolvedDefer(markers, scopeId);
};
this.getLayers = function (scopeId) {
var defer = getDefer(layers, scopeId);
return defer.promise;
};
this.setLayers = function (leafletLayers, scopeId) {
var defer = getUnresolvedDefer(layers, scopeId);
defer.resolve(leafletLayers);
setResolvedDefer(layers, scopeId);
};
this.setTiles = function (leafletTiles, scopeId) {
var defer = getUnresolvedDefer(tiles, scopeId);
defer.resolve(leafletTiles);
setResolvedDefer(tiles, scopeId);
};
this.getTiles = function (scopeId) {
var defer = getDefer(tiles, scopeId);
return defer.promise;
};
this.setGeoJSON = function (leafletGeoJSON, scopeId) {
var defer = getUnresolvedDefer(geoJSON, scopeId);
defer.resolve(leafletGeoJSON);
setResolvedDefer(geoJSON, scopeId);
};
this.getGeoJSON = function (scopeId) {
var defer = getDefer(geoJSON, scopeId);
return defer.promise;
};
}
]);
angular.module('leaflet-directive').factory('leafletMapDefaults', [
'$q',
'leafletHelpers',
function ($q, leafletHelpers) {
function _getDefaults() {
return {
keyboard: true,
dragging: true,
worldCopyJump: false,
doubleClickZoom: true,
scrollWheelZoom: true,
zoomControl: true,
zoomsliderControl: false,
zoomControlPosition: 'topleft',
attributionControl: true,
controls: {
layers: {
visible: true,
position: 'topright',
collapsed: true
}
},
crs: L.CRS.EPSG3857,
tileLayer: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
tileLayerOptions: { attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' },
path: {
weight: 10,
opacity: 1,
color: '#0000ff'
},
center: {
lat: 0,
lng: 0,
zoom: 1
}
};
}
var isDefined = leafletHelpers.isDefined, obtainEffectiveMapId = leafletHelpers.obtainEffectiveMapId, defaults = {};
// Get the _defaults dictionary, and override the properties defined by the user
return {
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,
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.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 (isDefined(userDefaults.crs) && isDefined(L.CRS[userDefaults.crs])) {
newDefaults.crs = L.CRS[userDefaults.crs];
}
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;
}
}
var mapId = obtainEffectiveMapId(defaults, scopeId);
defaults[mapId] = newDefaults;
return newDefaults;
}
};
}
]);
angular.module('leaflet-directive').factory('leafletEvents', [
'$rootScope',
'$q',
'$log',
'leafletHelpers',
function ($rootScope, $q, $log, leafletHelpers) {
var safeApply = leafletHelpers.safeApply, isDefined = leafletHelpers.isDefined, isObject = leafletHelpers.isObject, Helpers = leafletHelpers;
var _getAvailableLabelEvents = function () {
return [
'click',
'dblclick',
'mousedown',
'mouseover',
'mouseout',
'contextmenu'
];
};
var genLabelEvents = function (leafletScope, logic, marker, name) {
var labelEvents = _getAvailableLabelEvents();
var scopeWatchName = 'markers.' + name;
for (var i = 0; i < labelEvents.length; i++) {
var eventName = labelEvents[i];
marker.label.on(eventName, genDispatchLabelEvent(leafletScope, eventName, logic, marker.label, scopeWatchName));
}
};
var genDispatchMarkerEvent = function (eventName, logic, leafletScope, marker, name, markerData) {
return function (e) {
var broadcastName = 'leafletDirectiveMarker.' + eventName;
// 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 () {
markerData.lat = marker.getLatLng().lat;
markerData.lng = marker.getLatLng().lng;
});
if (markerData.message && markerData.focus === true) {
marker.openPopup();
}
}
safeApply(leafletScope, function (scope) {
if (logic === 'emit') {
scope.$emit(broadcastName, {
markerName: name,
leafletEvent: e
});
} else {
$rootScope.$broadcast(broadcastName, {
markerName: name,
leafletEvent: e
});
}
});
};
};
var genDispatchPathEvent = function (eventName, logic, leafletScope, marker, name) {
return function (e) {
var broadcastName = 'leafletDirectivePath.' + eventName;
safeApply(leafletScope, function (scope) {
if (logic === 'emit') {
scope.$emit(broadcastName, {
pathName: name,
leafletEvent: e
});
} else {
$rootScope.$broadcast(broadcastName, {
pathName: name,
leafletEvent: e
});
}
});
};
};
var genDispatchLabelEvent = function (scope, eventName, logic, label, scope_watch_name) {
return function (e) {
// Put together broadcast name
var broadcastName = 'leafletDirectiveLabel.' + eventName;
var markerName = scope_watch_name.replace('markers.', '');
// Safely broadcast the event
safeApply(scope, function (scope) {
if (logic === 'emit') {
scope.$emit(broadcastName, {
leafletEvent: e,
label: label,
markerName: markerName
});
} else if (logic === 'broadcast') {
$rootScope.$broadcast(broadcastName, {
leafletEvent: e,
label: label,
markerName: markerName
});
}
});
};
};
var _getAvailableMarkerEvents = function () {
return [
'click',
'dblclick',
'mousedown',
'mouseover',
'mouseout',
'contextmenu',
'dragstart',
'drag',
'dragend',
'move',
'remove',
'popupopen',
'popupclose'
];
};
var _getAvailablePathEvents = function () {
return [
'click',
'dblclick',
'mousedown',
'mouseover',
'mouseout',
'contextmenu',
'add',
'remove',
'popupopen',
'popupclose'
];
};
return {
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'
];
},
genDispatchMapEvent: function (scope, eventName, logic) {
return function (e) {
// Put together broadcast name
var broadcastName = 'leafletDirectiveMap.' + eventName;
// Safely broadcast the event
safeApply(scope, function (scope) {
if (logic === 'emit') {
scope.$emit(broadcastName, { leafletEvent: e });
} else if (logic === 'broadcast') {
$rootScope.$broadcast(broadcastName, { leafletEvent: e });
}
});
};
},
getAvailableMarkerEvents: _getAvailableMarkerEvents,
getAvailablePathEvents: _getAvailablePathEvents,
notifyCenterChangedToBounds: function (scope) {
scope.$broadcast('boundsChanged');
},
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);
}
},
bindMarkerEvents: function (marker, name, markerData, leafletScope) {
var markerEvents = [];
var i;
var eventName;
var logic = 'broadcast';
if (!isDefined(leafletScope.eventBroadcast)) {
// Backward compatibility, if no event-broadcast attribute, all events are broadcasted
markerEvents = _getAvailableMarkerEvents();
} else if (!isObject(leafletScope.eventBroadcast)) {
// Not a valid object
$log.error('[AngularJS - Leaflet] event-broadcast must be an object check your model.');
} else {
// We have a possible valid object
if (!isDefined(leafletScope.eventBroadcast.marker)) {
// We do not have events enable/disable do we do nothing (all enabled by default)
markerEvents = _getAvailableMarkerEvents();
} else if (!isObject(leafletScope.eventBroadcast.marker)) {
// Not a valid object
$log.warn('[AngularJS - Leaflet] event-broadcast.marker must be an object check your model.');
} else {
// We have a possible valid map object
// Event propadation logic
if (leafletScope.eventBroadcast.marker.logic !== undefined && leafletScope.eventBroadcast.marker.logic !== null) {
// We take care of possible propagation logic
if (leafletScope.eventBroadcast.marker.logic !== 'emit' && leafletScope.eventBroadcast.marker.logic !== 'broadcast') {
// This is an error
$log.warn('[AngularJS - Leaflet] Available event propagation logic are: \'emit\' or \'broadcast\'.');
} else if (leafletScope.eventBroadcast.marker.logic === 'emit') {
logic = 'emit';
}
}
// Enable / Disable
var markerEventsEnable = false, markerEventsDisable = false;
if (leafletScope.eventBroadcast.marker.enable !== undefined && leafletScope.eventBroadcast.marker.enable !== null) {
if (typeof leafletScope.eventBroadcast.marker.enable === 'object') {
markerEventsEnable = true;
}
}
if (leafletScope.eventBroadcast.marker.disable !== undefined && leafletScope.eventBroadcast.marker.disable !== null) {
if (typeof leafletScope.eventBroadcast.marker.disable === 'object') {
markerEventsDisable = true;
}
}
if (markerEventsEnable && markerEventsDisable) {
// Both are active, this is an error
$log.warn('[AngularJS - Leaflet] can not enable and disable events at the same time');
} else if (!markerEventsEnable && !markerEventsDisable) {
// Both are inactive, this is an error
$log.warn('[AngularJS - Leaflet] must enable or disable events');
} else {
// At this point the marker object is OK, lets enable or disable events
if (markerEventsEnable) {
// Enable events
for (i = 0; i < leafletScope.eventBroadcast.marker.enable.length; i++) {
eventName = leafletScope.eventBroadcast.marker.enable[i];
// Do we have already the event enabled?
if (markerEvents.indexOf(eventName) !== -1) {
// Repeated event, this is an error
$log.warn('[AngularJS - Leaflet] This event ' + eventName + ' is already enabled');
} else {
// Does the event exists?
if (_getAvailableMarkerEvents().indexOf(eventName) === -1) {
// The event does not exists, this is an error
$log.warn('[AngularJS - Leaflet] This event ' + eventName + ' does not exist');
} else {
// All ok enable the event
markerEvents.push(eventName);
}
}
}
} else {
// Disable events
markerEvents = _getAvailableMarkerEvents();
for (i = 0; i < leafletScope.eventBroadcast.marker.disable.length; i++) {
eventName = leafletScope.eventBroadcast.marker.disable[i];
var index = markerEvents.indexOf(eventName);
if (index === -1) {
// The event does not exist
$log.warn('[AngularJS - Leaflet] This event ' + eventName + ' does not exist or has been already disabled');
} else {
markerEvents.splice(index, 1);
}
}
}
}
}
}
for (i = 0; i < markerEvents.length; i++) {
eventName = markerEvents[i];
marker.on(eventName, genDispatchMarkerEvent(eventName, logic, leafletScope, marker, name, markerData));
}
if (Helpers.LabelPlugin.isLoaded() && isDefined(marker.label)) {
genLabelEvents(leafletScope, logic, marker, name);
}
},
bindPathEvents: function (path, name, pathData, leafletScope) {
var pathEvents = [];
var i;
var eventName;
var logic = 'broadcast';
window.lls = leafletScope;
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('[AngularJS - Leaflet] 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('[AngularJS - Leaflet] 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('[AngularJS - Leaflet] 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('[AngularJS - Leaflet] can not enable and disable events at the same time');
} else if (!pathEventsEnable && !pathEventsDisable) {
// Both are inactive, this is an error
$log.warn('[AngularJS - Leaflet] 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('[AngularJS - Leaflet] 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('[AngularJS - Leaflet] 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('[AngularJS - Leaflet] 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];
path.on(eventName, genDispatchPathEvent(eventName, logic, leafletScope, pathEvents, name));
}
if (Helpers.LabelPlugin.isLoaded() && isDefined(path.label)) {
genLabelEvents(leafletScope, logic, path, name);
}
}
};
}
]);
angular.module('leaflet-directive').factory('leafletLayerHelpers', [
'$rootScope',
'$log',
'leafletHelpers',
function ($rootScope, $log, leafletHelpers) {
var Helpers = leafletHelpers, isString = leafletHelpers.isString, isObject = leafletHelpers.isObject, isDefined = leafletHelpers.isDefined;
var layerTypes = {
xyz: {
mustHaveUrl: true,
createLayer: function (params) {
return L.tileLayer(params.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);
}
},
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 () {
return L.layerGroup();
}
},
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);
}
},
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;
}
},
dynamic: {
mustHaveUrl: true,
createLayer: function (params) {
if (!Helpers.DynamicMapLayerPlugin.isLoaded()) {
return;
}
return L.esri.dynamicMapLayer(params.url, params.options);
}
},
markercluster: {
mustHaveUrl: false,
createLayer: function (params) {
if (!Helpers.MarkerClusterPlugin.isLoaded()) {
$log.error('[AngularJS - Leaflet] 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);
}
},
heatmap: {
mustHaveUrl: false,
mustHaveData: true,
createLayer: function (params) {
if (!Helpers.HeatMapLayerPlugin.isLoaded()) {
return;
}
var layer = new L.TileLayer.WebGLHeatMap(params.options);
if (isDefined(params.data)) {
layer.setData(params.data);
}
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);
}
}
};
function isValidLayerType(layerDefinition) {
// Check if the baselayer has a valid type
if (!isString(layerDefinition.type)) {
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;
}
return true;
}
return {
createLayer: function (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,
pluginOptions: layerDefinition.pluginOptions
};
//TODO Add $watch to the layer properties
return layerTypes[layerDefinition.type].createLayer(params);
}
};
}
]);
angular.module('leaflet-directive').factory('leafletControlHelpers', [
'$rootScope',
'$log',
'leafletHelpers',
'leafletMapDefaults',
function ($rootScope, $log, leafletHelpers, leafletMapDefaults) {
var isObject = leafletHelpers.isObject, isDefined = leafletHelpers.isDefined;
var _layersControl;
var _controlLayersMustBeVisible = function (baselayers, overlays) {
var numberOfLayers = 0;
if (isObject(baselayers)) {
numberOfLayers += Object.keys(baselayers).length;
}
if (isObject(overlays)) {
numberOfLayers += Object.keys(overlays).length;
}
return numberOfLayers > 1;
};
var _createLayersControl = function (mapId) {
var defaults = leafletMapDefaults.getDefaults(mapId);
var controlOptions = {
collapsed: defaults.controls.layers.collapsed,
position: defaults.controls.layers.position
};
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;
};
return {
layersControlMustBeVisible: _controlLayersMustBeVisible,
updateLayersControl: function (map, mapId, loaded, baselayers, overlays, leafletLayers) {
var i;
var mustBeLoaded = _controlLayersMustBeVisible(baselayers, overlays);
if (isDefined(_layersControl) && loaded) {
for (i in leafletLayers.baselayers) {
_layersControl.removeLayer(leafletLayers.baselayers[i]);
}
for (i in leafletLayers.overlays) {
_layersControl.removeLayer(leafletLayers.overlays[i]);
}
_layersControl.removeFrom(map);
}
if (mustBeLoaded) {
_layersControl = _createLayersControl(mapId);
for (i in baselayers) {
if (isDefined(leafletLayers.baselayers[i])) {
_layersControl.addBaseLayer(leafletLayers.baselayers[i], baselayers[i].name);
}
}
for (i in overlays) {
if (isDefined(leafletLayers.overlays[i])) {
_layersControl.addOverlay(leafletLayers.overlays[i], overlays[i].name);
}
}
_layersControl.addTo(map);
}
return mustBeLoaded;
}
};
}
]);
angular.module('leaflet-directive').factory('leafletLegendHelpers', function () {
var _updateArcGISLegend = function (div, legendData) {
div.innerHTML = '';
if (legendData.error) {
div.innerHTML += '<div class="info-title alert alert-danger">' + legendData.error.message + '</div>';
} else {
for (var i = 0; i < legendData.layers.length; i++) {
var layer = legendData.layers[i];
div.innerHTML += '<div class="info-title">' + layer.layerName + '</div>';
for (var j = 0; j < layer.legend.length; j++) {
var leg = layer.legend[j];
div.innerHTML += '<div class="inline"><img src="data:' + leg.contentType + ';base64,' + leg.imageData + '" /></div>' + '<div class="info-label">' + leg.label + '</div>';
}
}
}
};
var _getOnAddArcGISLegend = function (legendData, legendClass) {
return function () {
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);
}
_updateArcGISLegend(div, legendData);
return div;
};
};
var _getOnAddArrayLegend = function (legend, legendClass) {
return function () {
var div = L.DomUtil.create('div', legendClass);
for (var i = 0; i < legend.colors.length; i++) {
div.innerHTML += '<div class="outline"><i style="background:' + legend.colors[i] + '"></i></div>' + '<div class="info-label">' + legend.labels[i] + '</div>';
}
if (!L.Browser.touch) {
L.DomEvent.disableClickPropagation(div);
L.DomEvent.on(div, 'mousewheel', L.DomEvent.stopPropagation);
} else {
L.DomEvent.on(div, 'click', L.DomEvent.stopPropagation);
}
return div;
};
};
return {
getOnAddArcGISLegend: _getOnAddArcGISLegend,
getOnAddArrayLegend: _getOnAddArrayLegend,
updateArcGISLegend: _updateArcGISLegend
};
});
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;
function _convertToLeafletLatLngs(latlngs) {
return latlngs.filter(function (latlng) {
return isValidPoint(latlng);
}).map(function (latlng) {
return new L.LatLng(latlng.lat, latlng.lng);
});
}
function _convertToLeafletLatLng(latlng) {
return new L.LatLng(latlng.lat, latlng.lng);
}
function _convertToLeafletMultiLatLngs(paths) {
return paths.map(function (latlngs) {
return _convertToLeafletLatLngs(latlngs);
});
}
function _getOptions(path, defaults) {
var availableOptions = [
'stroke',
'weight',
'color',
'opacity',
'fill',
'fillColor',
'fillOpacity',
'dashArray',
'lineCap',
'lineJoin',
'clickable',
'pointerEvents',
'className',
'smoothFactor',
'noClip'
];
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) {
if (isDefined(data.weight)) {
path.setStyle({ weight: data.weight });
}
if (isDefined(data.color)) {
path.setStyle({ color: data.color });
}
if (isDefined(data.opacity)) {
path.setStyle({ opacity: data.opacity });
}
};
var _isValidPolyline = function (latlngs) {
if (!isArray(latlngs)) {
return false;
}
for (var i in latlngs) {
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').factory('leafletBoundsHelpers', [
'$log',
'leafletHelpers',
function ($log, leafletHelpers) {
var isArray = leafletHelpers.isArray, isNumber = leafletHelpers.isNumber;
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]
}
};
}
};
}
]);
angular.module('leaflet-directive').factory('leafletMarkersHelpers', [
'$rootScope',
'leafletHelpers',
'$log',
function ($rootScope, leafletHelpers, $log) {
var isDefined = leafletHelpers.isDefined, MarkerClusterPlugin = leafletHelpers.MarkerClusterPlugin, AwesomeMarkersPlugin = leafletHelpers.AwesomeMarkersPlugin, safeApply = leafletHelpers.safeApply, Helpers = leafletHelpers, isString = leafletHelpers.isString, isNumber = leafletHelpers.isNumber, isObject = leafletHelpers.isObject, groups = {};
var createLeafletIcon = function (iconData) {
if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'awesomeMarker') {
if (!AwesomeMarkersPlugin.isLoaded()) {
$log.error('[AngularJS - Leaflet] The AwesomeMarkers Plugin is not loaded.');
}
return new L.AwesomeMarkers.icon(iconData);
}
if (isDefined(iconData) && isDefined(iconData.type) && iconData.type === 'div') {
return new L.divIcon(iconData);
}
var base64icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAGmklEQVRYw7VXeUyTZxjvNnfELFuyIzOabermMZEeQC/OclkO49CpOHXOLJl/CAURuYbQi3KLgEhbrhZ1aDwmaoGqKII6odATmH/scDFbdC7LvFqOCc+e95s2VG50X/LLm/f4/Z7neY/ne18aANCmAr5E/xZf1uDOkTcGcWR6hl9247tT5U7Y6SNvWsKT63P58qbfeLJG8M5qcgTknrvvrdDbsT7Ml+tv82X6vVxJE33aRmgSyYtcWVMqX97Yv2JvW39UhRE2HuyBL+t+gK1116ly06EeWFNlAmHxlQE0OMiV6mQCScusKRlhS3QLeVJdl1+23h5dY4FNB3thrbYboqptEFlphTC1hSpJnbRvxP4NWgsE5Jyz86QNNi/5qSUTGuFk1gu54tN9wuK2wc3o+Wc13RCmsoBwEqzGcZsxsvCSy/9wJKf7UWf1mEY8JWfewc67UUoDbDjQC+FqK4QqLVMGGR9d2wurKzqBk3nqIT/9zLxRRjgZ9bqQgub+DdoeCC03Q8j+0QhFhBHR/eP3U/zCln7Uu+hihJ1+bBNffLIvmkyP0gpBZWYXhKussK6mBz5HT6M1Nqpcp+mBCPXosYQfrekGvrjewd59/GvKCE7TbK/04/ZV5QZYVWmDwH1mF3xa2Q3ra3DBC5vBT1oP7PTj4C0+CcL8c7C2CtejqhuCnuIQHaKHzvcRfZpnylFfXsYJx3pNLwhKzRAwAhEqG0SpusBHfAKkxw3w4627MPhoCH798z7s0ZnBJ/MEJbZSbXPhER2ih7p2ok/zSj2cEJDd4CAe+5WYnBCgR2uruyEw6zRoW6/DWJ/OeAP8pd/BGtzOZKpG8oke0SX6GMmRk6GFlyAc59K32OTEinILRJRchah8HQwND8N435Z9Z0FY1EqtxUg+0SO6RJ/mmXz4VuS+DpxXC3gXmZwIL7dBSH4zKE50wESf8qwVgrP1EIlTO5JP9Igu0aexdh28F1lmAEGJGfh7jE6ElyM5Rw/FDcYJjWhbeiBYoYNIpc2FT/SILivp0F1ipDWk4BIEo2VuodEJUifhbiltnNBIXPUFCMpthtAyqws/BPlEF/VbaIxErdxPphsU7rcCp8DohC+GvBIPJS/tW2jtvTmmAeuNO8BNOYQeG8G/2OzCJ3q+soYB5i6NhMaKr17FSal7GIHheuV3uSCY8qYVuEm1cOzqdWr7ku/R0BDoTT+DT+ohCM6/CCvKLKO4RI+dXPeAuaMqksaKrZ7L3FE5FIFbkIceeOZ2OcHO6wIhTkNo0ffgjRGxEqogXHYUPHfWAC/lADpwGcLRY3aeK4/oRGCKYcZXPVoeX/kelVYY8dUGf8V5EBRbgJXT5QIPhP9ePJi428JKOiEYhYXFBqou2Guh+p/mEB1/RfMw6rY7cxcjTrneI1FrDyuzUSRm9miwEJx8E/gUmqlyvHGkneiwErR21F3tNOK5Tf0yXaT+O7DgCvALTUBXdM4YhC/IawPU+2PduqMvuaR6eoxSwUk75ggqsYJ7VicsnwGIkZBSXKOUww73WGXyqP+J2/b9c+gi1YAg/xpwck3gJuucNrh5JvDPvQr0WFXf0piyt8f8/WI0hV4pRxxkQZdJDfDJNOAmM0Ag8jyT6hz0WGXWuP94Yh2jcfjmXAGvHCMslRimDHYuHuDsy2QtHuIavznhbYURq5R57KpzBBRZKPJi8eQg48h4j8SDdowifdIrEVdU+gbO6QNvRRt4ZBthUaZhUnjlYObNagV3keoeru3rU7rcuceqU1mJBxy+BWZYlNEBH+0eH4vRiB+OYybU2hnblYlTvkHinM4m54YnxSyaZYSF6R3jwgP7udKLGIX6r/lbNa9N6y5MFynjWDtrHd75ZvTYAPO/6RgF0k76mQla3FGq7dO+cH8sKn0Vo7nDllwAhqwLPkxrHwWmHJOo+AKJ4rab5OgrM7rVu8eWb2Pu0Dh4eDgXoOfvp7Y7QeqknRmvcTBEyq9m/HQQSCSz6LHq3z0yzsNySRfMS253wl2KyRDbcZPcfJKjZmSEOjcxyi+Y8dUOtsIEH6R2wNykdqrkYJ0RV92H0W58pkfQk7cKevsLK10Py8SdMGfXNXATY+pPbyJR/ET6n9nIfztNtZYRV9XniQu9IA2vOVgy4ir7GCLVmmd+zjkH0eAF9Po6K61pmCXHxU5rHMYd1ftc3owjwRSVRzLjKvqZEty6cRUD7jGqiOdu5HG6MdHjNcNYGqfDm5YRzLBBCCDl/2bk8a8gdbqcfwECu62Fg/HrggAAAABJRU5ErkJggg==';
var base64shadow = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAApCAYAAACoYAD2AAAC5ElEQVRYw+2YW4/TMBCF45S0S1luXZCABy5CgLQgwf//S4BYBLTdJLax0fFqmB07nnQfEGqkIydpVH85M+NLjPe++dcPc4Q8Qh4hj5D/AaQJx6H/4TMwB0PeBNwU7EGQAmAtsNfAzoZkgIa0ZgLMa4Aj6CxIAsjhjOCoL5z7Glg1JAOkaicgvQBXuncwJAWjksLtBTWZe04CnYRktUGdilALppZBOgHGZcBzL6OClABvMSVIzyBjazOgrvACf1ydC5mguqAVg6RhdkSWQFj2uxfaq/BrIZOLEWgZdALIDvcMcZLD8ZbLC9de4yR1sYMi4G20S4Q/PWeJYxTOZn5zJXANZHIxAd4JWhPIloTJZhzMQduM89WQ3MUVAE/RnhAXpTycqys3NZALOBbB7kFrgLesQl2h45Fcj8L1tTSohUwuxhy8H/Qg6K7gIs+3kkaigQCOcyEXCHN07wyQazhrmIulvKMQAwMcmLNqyCVyMAI+BuxSMeTk3OPikLY2J1uE+VHQk6ANrhds+tNARqBeaGc72cK550FP4WhXmFmcMGhTwAR1ifOe3EvPqIegFmF+C8gVy0OfAaWQPMR7gF1OQKqGoBjq90HPMP01BUjPOqGFksC4emE48tWQAH0YmvOgF3DST6xieJgHAWxPAHMuNhrImIdvoNOKNWIOcE+UXE0pYAnkX6uhWsgVXDxHdTfCmrEEmMB2zMFimLVOtiiajxiGWrbU52EeCdyOwPEQD8LqyPH9Ti2kgYMf4OhSKB7qYILbBv3CuVTJ11Y80oaseiMWOONc/Y7kJYe0xL2f0BaiFTxknHO5HaMGMublKwxFGzYdWsBF174H/QDknhTHmHHN39iWFnkZx8lPyM8WHfYELmlLKtgWNmFNzQcC1b47gJ4hL19i7o65dhH0Negbca8vONZoP7doIeOC9zXm8RjuL0Gf4d4OYaU5ljo3GYiqzrWQHfJxA6ALhDpVKv9qYeZA8eM3EhfPSCmpuD0AAAAASUVORK5CYII=';
if (!isDefined(iconData)) {
return new L.Icon.Default({
iconUrl: base64icon,
shadowUrl: base64shadow
});
}
if (!isDefined(iconData.iconUrl)) {
iconData.iconUrl = base64icon;
iconData.shadowUrl = base64shadow;
}
return new L.Icon.Default(iconData);
};
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) {
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);
}
};
return {
deleteMarker: _deleteMarker,
createMarker: function (markerData) {
if (!isDefined(markerData)) {
$log.error('[AngularJS - Leaflet] The marker definition is not valid.');
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
};
return new L.marker(markerData, markerOptions);
},
addMarkerToGroup: function (marker, groupName, map) {
if (!isString(groupName)) {
$log.error('[AngularJS - Leaflet] The marker group you have specified is invalid.');
return;
}
if (!MarkerClusterPlugin.isLoaded()) {
$log.error('[AngularJS - Leaflet] The MarkerCluster plugin is not loaded.');
return;
}
if (!isDefined(groups[groupName])) {
groups[groupName] = new L.MarkerClusterGroup();
map.addLayer(groups[groupName]);
}
groups[groupName].addLayer(marker);
},
listenMarkerEvents: function (marker, markerData, leafletScope) {
marker.on('popupopen', function () {
safeApply(leafletScope, function () {
markerData.focus = true;
});
});
marker.on('popupclose', function () {
safeApply(leafletScope, function () {
markerData.focus = false;
});
});
},
addMarkerWatcher: function (marker, name, leafletScope, layers, map) {
var clearWatch = leafletScope.$watch('markers.' + name, function (markerData, oldMarkerData) {
if (!isDefined(markerData)) {
_deleteMarker(marker, map, layers);
clearWatch();
return;
}
if (!isDefined(oldMarkerData)) {
return;
}
// Update the lat-lng property (always present in marker properties)
if (!(isNumber(markerData.lat) && isNumber(markerData.lng))) {
$log.warn('There are problems with lat-lng data, please verify your marker model');
_deleteMarker(marker, map, layers);
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();
}
// Test if it is not on the map and add it
if (!map.hasLayer(marker)) {
map.addLayer(marker);
}
}
}
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('[AngularJS - Leaflet] 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)) {
$log.error('[AngularJS - Leaflet] A marker can only be added to a layer of type "group"');
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);
}
}
}
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);
}
}
// Update the Popup message property
if (!isString(markerData.message) && isString(oldMarkerData.message)) {
marker.closePopup();
marker.unbindPopup();
}
// Update the label content
if (Helpers.LabelPlugin.isLoaded() && isDefined(markerData.label) && isDefined(markerData.label.message) && !angular.equals(markerData.label.message, oldMarkerData.label.message)) {
marker.updateLabelContent(markerData.label.message);
}
// 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);
if (markerData.focus === true) {
// If the focus is set, we must open the popup, because we do not know if it was opened before
marker.openPopup();
}
}
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 && oldMarkerData.focus !== true) {
marker.openPopup();
updatedFocus = true;
}
if (oldMarkerData.focus === true && markerData.focus === true) {
// Reopen the popup when focus is still true
marker.openPopup();
updatedFocus = true;
}
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 (markerLatLng.lat !== markerData.lat || markerLatLng.lng !== markerData.lng) {
marker.setLatLng([
markerData.lat,
markerData.lng
]);
}
}, true);
}
};
}
]);
angular.module('leaflet-directive').factory('leafletHelpers', [
'$q',
'$log',
function ($q, $log) {
function _obtainEffectiveMapId(d, mapId) {
var id, i;
if (!angular.isDefined(mapId)) {
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('[AngularJS - Leaflet] - 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;
}
return {
isEmpty: function (value) {
return Object.keys(value).length === 0;
},
isUndefinedOrEmpty: function (value) {
return angular.isUndefined(value) || value === null || Object.keys(value).length === 0;
},
isDefined: function (value) {
return angular.isDefined(value) && value !== null;
},
isNumber: function (value) {
return angular.isNumber(value);
},
isString: function (value) {
return angular.isString(value);
},
isArray: function (value) {
return angular.isArray(value);
},
isObject: function (value) {
return angular.isObject(value);
},
isFunction: function (value) {
return angular.isFunction(value);
},
equals: function (o1, o2) {
return angular.equals(o1, o2);
},
isValidCenter: function (center) {
return angular.isDefined(center) && angular.isNumber(center.lat) && angular.isNumber(center.lng) && angular.isNumber(center.zoom);
},
isValidPoint: function (point) {
return angular.isDefined(point) && angular.isNumber(point.lat) && angular.isNumber(point.lng);
},
isSameCenterOnMap: function (centerModel, map) {
var mapCenter = map.getCenter();
var zoom = map.getZoom();
if (mapCenter.lat === centerModel.lat && mapCenter.lng === centerModel.lng && 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.$apply(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;
},
AwesomeMarkersPlugin: {
isLoaded: function () {
if (angular.isDefined(L.AwesomeMarkers) && angular.isDefined(L.AwesomeMarkers.Icon)) {
return true;
} else {
return false;
}
},
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;
}
}
},
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);
}
},
HeatMapLayerPlugin: {
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;
}
}
},
AGSLayerPlugin: {
isLoaded: function () {
return lvector !== undefined && lvector.AGS !== undefined;
},
is: function (layer) {
if (this.isLoaded()) {
return layer instanceof lvector.AGS;
} 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;
}
}
},
DynamicMapLayerPlugin: {
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;
}
}
},
GeoJSONPlugin: {
isLoaded: function () {
return angular.isDefined(L.TileLayer.GeoJSON);
},
is: function (layer) {
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;
}
}
}
}
};
}
]);
}());