UNPKG

ui.leaflet.webpack

Version:

Webpack version of ui-leaflet (https://github.com/angular-ui/ui-leaflet)

285 lines (253 loc) 13.5 kB
//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); }); }); }); } }; }];