ui.leaflet.webpack
Version:
Webpack version of ui-leaflet (https://github.com/angular-ui/ui-leaflet)
285 lines (253 loc) • 13.5 kB
JavaScript
//angular.module('ui-leaflet').directive('markers',
/** @ngInject */
module.exports = [
'leafletLogger', '$rootScope', '$q', 'leafletData', 'leafletHelpers', 'leafletMapDefaults',
'leafletMarkersHelpers', 'leafletMarkerEvents', 'leafletIterators', 'leafletWatchHelpers',
'leafletDirectiveControlsHelpers', 'L'
,function (leafletLogger, $rootScope, $q, leafletData, leafletHelpers, leafletMapDefaults,
leafletMarkersHelpers, leafletMarkerEvents, leafletIterators, leafletWatchHelpers,
leafletDirectiveControlsHelpers, L) {
//less terse vars to helpers
var isDefined = leafletHelpers.isDefined,
errorHeader = leafletHelpers.errorHeader,
Helpers = leafletHelpers,
isString = leafletHelpers.isString,
addMarkerWatcher = leafletMarkersHelpers.addMarkerWatcher,
updateMarker = leafletMarkersHelpers.updateMarker,
listenMarkerEvents = leafletMarkersHelpers.listenMarkerEvents,
addMarkerToGroup = leafletMarkersHelpers.addMarkerToGroup,
createMarker = leafletMarkersHelpers.createMarker,
deleteMarker = leafletMarkersHelpers.deleteMarker,
getModelFromModels = leafletMarkersHelpers.getModelFromModels,
getLayerModels = leafletMarkersHelpers.getLayerModels,
resetUnusedMarkerGroups = leafletMarkersHelpers.resetUnusedMarkerGroups,
$it = leafletIterators,
_defaultWatchOptions = leafletHelpers.watchOptions,
maybeWatch = leafletWatchHelpers.maybeWatch,
extendDirectiveControls = leafletDirectiveControlsHelpers.extend,
$log = leafletLogger,
watchTrap = {changeFromDirective: false};
var _getLMarker = function(leafletMarkers, name, maybeLayerName){
if(!Object.keys(leafletMarkers).length) return;
if(maybeLayerName && isString(maybeLayerName)){
if(!leafletMarkers[maybeLayerName] || !Object.keys(leafletMarkers[maybeLayerName]).length)
return;
return leafletMarkers[maybeLayerName][name];
}
return leafletMarkers[name];
};
var _setLMarker = function(lObject, leafletMarkers, name, maybeLayerName){
if(maybeLayerName && isString(maybeLayerName)){
if(!isDefined(leafletMarkers[maybeLayerName]))
leafletMarkers[maybeLayerName] = {};
leafletMarkers[maybeLayerName][name] = lObject;
}
else
leafletMarkers[name] = lObject;
return lObject;
};
var _maybeAddMarkerToLayer = function(layerName, layers, model, marker, watchType, map){
if (!isString(layerName)) {
$log.error(errorHeader + ' A layername must be a string');
return false;
}
if (!isDefined(layers)) {
$log.error(errorHeader + ' You must add layers to the directive if the markers are going to use this functionality.');
return false;
}
if (!isDefined(layers.overlays) || !isDefined(layers.overlays[layerName])) {
$log.error(errorHeader +' A marker can only be added to a layer of type "group"');
return false;
}
var layerGroup = layers.overlays[layerName];
if (!(layerGroup instanceof L.LayerGroup || layerGroup instanceof L.FeatureGroup)) {
$log.error(errorHeader + ' Adding a marker to an overlay needs a overlay of the type "group" or "featureGroup"');
return false;
}
// The marker goes to a correct layer group, so first of all we add it
layerGroup.addLayer(marker);
// The marker is automatically added to the map depending on the visibility
// of the layer, so we only have to open the popup if the marker is in the map
if (watchType === null && map.hasLayer(marker) && model.focus === true) {
marker.openPopup();
}
return true;
};
//TODO: move to leafletMarkersHelpers??? or make a new class/function file (leafletMarkersHelpers is large already)
var _addMarkers = function(mapId, markersToRender, oldModels, map, layers, leafletMarkers, leafletScope,
watchOptions, maybeLayerName, skips){
$it.each(markersToRender, (model, newName) => {
if(skips[newName])
return;
if (newName.search("-") !== -1) {
$log.error('The marker can\'t use a "-" on his key name: "' + newName + '".');
return;
}
var pathToMarker = Helpers.getObjectDotPath(maybeLayerName? [maybeLayerName, newName]: [newName]);
var maybeLMarker = _getLMarker(leafletMarkers,newName, maybeLayerName);
Helpers.modelChangeInDirective(watchTrap, "changeFromDirective", () => {
if (!isDefined(maybeLMarker)) {
var marker = createMarker(model);
var layerName = (model? model.layer : undefined) || maybeLayerName; //original way takes pref
if (!isDefined(marker)) {
$log.error(errorHeader + ' Received invalid data on the marker ' + newName + '.');
return;
}
_setLMarker(marker, leafletMarkers, newName, maybeLayerName);
// Bind message
if (isDefined(model.message)) {
marker.bindPopup(model.message, model.popupOptions);
}
// Add the marker to a cluster group if needed
if (isDefined(model.group)) {
var groupOptions = isDefined(model.groupOption) ? model.groupOption : null;
addMarkerToGroup(marker, model.group, groupOptions, map);
}
// Show label if defined
if (Helpers.LabelPlugin.isLoaded() && isDefined(model.label) && isDefined(model.label.message)) {
marker.bindLabel(model.label.message, model.label.options);
}
// Check if the marker should be added to a layer
if (isDefined(model) && (isDefined(model.layer) || isDefined(maybeLayerName))){
var pass = _maybeAddMarkerToLayer(layerName, layers, model, marker,
watchOptions.individual.type, map);
if(!pass)
return; //something went wrong move on in the loop
} else if (!isDefined(model.group)) {
// We do not have a layer attr, so the marker goes to the map layer
map.addLayer(marker);
if (watchOptions.individual.type === null && model.focus === true) {
marker.openPopup();
}
}
if (watchOptions.individual.type !== null) {
addMarkerWatcher(marker, pathToMarker, leafletScope, layers, map,
watchOptions.individual);
}
listenMarkerEvents(marker, model, leafletScope, watchOptions.individual.type, map);
leafletMarkerEvents.bindEvents(mapId, marker, pathToMarker, model, leafletScope, layerName);
}
else {
var oldModel = getModelFromModels(oldModels, newName, maybeLayerName);
updateMarker(model, oldModel, maybeLMarker, pathToMarker, leafletScope, layers, map);
}
});
});
};
var _seeWhatWeAlreadyHave = function(markerModels, oldMarkerModels, lMarkers, isEqual, cb){
var hasLogged = false,
equals = false,
oldMarker,
newMarker;
var doCheckOldModel = isDefined(oldMarkerModels);
for (var name in lMarkers) {
if(!hasLogged) {
$log.debug(errorHeader + "[markers] destroy: ");
hasLogged = true;
}
if(doCheckOldModel){
//might want to make the option (in watch options) to disable deep checking
//ie the options to only check !== (reference check) instead of angular.equals (slow)
newMarker = markerModels[name];
oldMarker = oldMarkerModels[name];
equals = isEqual && angular.equals(newMarker, oldMarker);
}
if (!isDefined(markerModels) ||
!Object.keys(markerModels).length ||
!isDefined(markerModels[name]) ||
!Object.keys(markerModels[name]).length ||
equals) {
if(cb && Helpers.isFunction(cb))
cb(newMarker, oldMarker, name);
}
}
};
var _destroy = function(markerModels, oldMarkerModels, lMarkers, map, layers){
_seeWhatWeAlreadyHave(markerModels, oldMarkerModels, lMarkers, false,
function(newMarker, oldMarker, lMarkerName){
$log.debug(errorHeader + '[marker] is deleting marker: ' + lMarkerName);
deleteMarker(lMarkers[lMarkerName], map, layers);
delete lMarkers[lMarkerName];
});
};
var _getNewModelsToSkipp = function(newModels, oldModels, lMarkers){
var skips = {};
_seeWhatWeAlreadyHave(newModels, oldModels, lMarkers, true,
function(newMarker, oldMarker, lMarkerName){
$log.debug(errorHeader + '[marker] is already rendered, marker: ' + lMarkerName);
skips[lMarkerName] = newMarker;
});
return skips;
};
return {
restrict: "A",
scope: false,
replace: false,
require: ['leaflet', '?layers'],
link: function(scope, element, attrs, controller) {
var mapController = controller[0],
leafletScope = mapController.getLeafletScope();
mapController.getMap().then(function(map) {
var leafletMarkers = {}, getLayers;
// If the layers attribute is used, we must wait until the layers are created
if (isDefined(controller[1])) {
getLayers = controller[1].getLayers;
} else {
getLayers = function() {
var deferred = $q.defer();
deferred.resolve();
return deferred.promise;
};
}
var watchOptions;
if(leafletScope.watchOptions && leafletScope.watchOptions.markers) {
watchOptions = leafletScope.watchOptions.markers;
}
else {
watchOptions = _defaultWatchOptions;
}
var isNested = (isDefined(attrs.markersNested) && Helpers.isTruthy(attrs.markersNested));
getLayers().then(function(layers) {
var _clean = function(models, oldModels){
resetUnusedMarkerGroups();
if(isNested) {
$it.each(models, function(markerToMaybeDel, layerName) {
var oldLayerModels = getLayerModels(oldModels, layerName);
_destroy(markerToMaybeDel, oldLayerModels, leafletMarkers[layerName], map, layers);
});
return;
}
_destroy(models, oldModels, leafletMarkers, map, layers);
};
var _create = function(models, oldModels){
_clean(models, oldModels);
var skips = null;
if(isNested) {
$it.each(models, function(markersToAdd, layerName) {
var oldLayerModels = getLayerModels(oldModels, layerName);
var newlayerModels = getLayerModels(models, layerName);
skips = _getNewModelsToSkipp(newlayerModels, oldLayerModels, leafletMarkers[layerName]);
_addMarkers(attrs.id, markersToAdd, oldModels, map, layers, leafletMarkers, leafletScope,
watchOptions, layerName, skips);
});
return;
}
skips = _getNewModelsToSkipp(models, oldModels, leafletMarkers);
_addMarkers(attrs.id, models, oldModels, map, layers, leafletMarkers, leafletScope,
watchOptions, undefined, skips);
};
extendDirectiveControls(attrs.id, 'markers', _create, _clean);
leafletData.setMarkers(leafletMarkers, attrs.id);
maybeWatch(leafletScope,'markers', watchOptions, function(newMarkers, oldMarkers){
if(watchTrap.changeFromDirective)
return;
_create(newMarkers, oldMarkers);
});
scope.$on('$destroy', function () {
_destroy(leafletScope.markers, {}, leafletMarkers, map, layers);
});
});
});
}
};
}];