mohsen-angular-leaflet-directive
Version:
angular-leaflet-directive - An AngularJS directive to easily interact with Leaflet maps
157 lines (128 loc) • 5.96 kB
JavaScript
angular.module('leaflet-directive').directive('lfPaths', function(leafletLogger, $q, leafletData, leafletMapDefaults, leafletHelpers, leafletPathsHelpers, leafletPathEvents) {
return {
restrict: 'A',
scope: false,
replace: false,
require: ['leaflet', '?lfLayers'],
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) {
leafletLogger.error('The path name "' + newName + '" is not valid. It must not include "-" and a number.', 'paths');
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)) {
leafletLogger.error('A layername must be a string', 'paths');
continue;
}
if (!isDefined(layers)) {
leafletLogger.error('You must add layers to the directive if the markers are going to use this functionality', 'paths');
continue;
}
if (!isDefined(layers.overlays) || !isDefined(layers.overlays[pathData.layer])) {
leafletLogger.error('A path can only be added to a layer of type "group"', 'paths');
continue;
}
var layerGroup = layers.overlays[pathData.layer];
if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {
leafletLogger.error('Adding a path to an overlay needs a overlay of the type "group" or "featureGroup"', 'paths');
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);
}
}
});
});
});
},
};
});