@asymmetrik/angular2-leaflet
Advanced tools
Comparing version 2.1.5 to 2.2.0
@@ -1,2 +0,2 @@ | ||
/*! @asymmetrik/angular2-leaflet - 2.1.5 - Copyright Asymmetrik, Ltd. 2007-2017 - All Rights Reserved. + */ | ||
/*! @asymmetrik/angular2-leaflet - 2.2.0 - Copyright Asymmetrik, Ltd. 2007-2017 - All Rights Reserved. + */ | ||
(function (global, factory) { | ||
@@ -158,67 +158,63 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('leaflet')) : | ||
var LeafletLayerDiff = (function () { | ||
function LeafletLayerDiff(remove, add) { | ||
this.remove = remove; | ||
this.add = add; | ||
} | ||
return LeafletLayerDiff; | ||
}()); | ||
var LeafletLayersUtil = (function () { | ||
function LeafletLayersUtil() { | ||
} | ||
LeafletLayersUtil.diffLayers = function (newLayers, prevLayers) { | ||
var toRemove; | ||
var toAdd; | ||
if (null == newLayers) { | ||
newLayers = []; | ||
} | ||
if (null == prevLayers) { | ||
prevLayers = []; | ||
} | ||
// Figure out which layers need to be removed (prev - new) | ||
toRemove = prevLayers | ||
.filter(function (pl) { | ||
return !(newLayers.find(function (nl) { return (pl === nl); })); | ||
}); | ||
// Figure out which layers need to be added (new - prev) | ||
toAdd = newLayers | ||
.filter(function (pl) { | ||
return !(prevLayers.find(function (nl) { return (pl === nl); })); | ||
}); | ||
return new LeafletLayerDiff(toRemove, toAdd); | ||
}; | ||
return LeafletLayersUtil; | ||
}()); | ||
/** | ||
* Layers directive | ||
* | ||
* This directive is used to directly control map layers. As changed are made to the input array of | ||
* layers, the map is synched to the array. As layers are added or removed from the input array, they | ||
* are also added or removed from the map. The input array is treated as immutable. To detect changes, | ||
* you must change the array instance. | ||
* | ||
* Important Note: The input layers array is assumed to be immutable. This means you need to use an | ||
* immutable array implementation or create a new copy of your array when you make changes, otherwise | ||
* this directive won't detect the change. This is by design. It's for performance reasons. Change | ||
* detection of mutable arrays requires diffing the state of the array on every DoCheck cycle, which | ||
* is extremely expensive from a time complexity perspective. | ||
* | ||
*/ | ||
var LeafletLayersDirective = (function () { | ||
function LeafletLayersDirective(leafletDirective) { | ||
function LeafletLayersDirective(leafletDirective, differs) { | ||
this.differs = differs; | ||
this.leafletDirective = new LeafletDirectiveWrapper(leafletDirective); | ||
this.layersDiffer = this.differs.find([]).create(); | ||
} | ||
Object.defineProperty(LeafletLayersDirective.prototype, "layers", { | ||
get: function () { | ||
return this.layersValue; | ||
}, | ||
// Set/get the layers | ||
set: function (v) { | ||
this.layersValue = v; | ||
// Now that we have a differ, do an immediate layer update | ||
this.updateLayers(); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
LeafletLayersDirective.prototype.ngDoCheck = function () { | ||
this.updateLayers(); | ||
}; | ||
LeafletLayersDirective.prototype.ngOnInit = function () { | ||
// Init the map | ||
this.leafletDirective.init(); | ||
// The way we've set this up, map isn't set until after the first round of changes has gone through | ||
this.setLayers(this.layers, []); | ||
// Update layers once the map is ready | ||
this.updateLayers(); | ||
}; | ||
LeafletLayersDirective.prototype.ngOnChanges = function (changes) { | ||
// Set the layers | ||
if (changes['layers']) { | ||
var c = changes['layers'].currentValue; | ||
var p = (changes['layers'].isFirstChange()) ? [] : changes['layers'].previousValue; | ||
this.setLayers(c, p); | ||
} | ||
}; | ||
/** | ||
* Replace the current layers in the map with the provided array | ||
* @param layers The new complete array of layers for the map | ||
* Update the state of the layers. | ||
* We use an iterable differ to synchronize the map layers with the state of the bound layers array. | ||
* This is important because it allows us to react to changes to the contents of the array as well | ||
* as changes to the actual array instance. | ||
*/ | ||
LeafletLayersDirective.prototype.setLayers = function (newLayers, prevLayers) { | ||
LeafletLayersDirective.prototype.updateLayers = function () { | ||
var map$$1 = this.leafletDirective.getMap(); | ||
if (null != map$$1) { | ||
var diff = LeafletLayersUtil.diffLayers(newLayers, prevLayers); | ||
// Remove the layers | ||
diff.remove.forEach(function (l) { map$$1.removeLayer(l); }); | ||
// Add the new layers | ||
diff.add.forEach(function (l) { map$$1.addLayer(l); }); | ||
if (null != map$$1 && null != this.layersDiffer) { | ||
var changes = this.layersDiffer.diff(this.layersValue); | ||
if (null != changes) { | ||
changes.forEachRemovedItem(function (c) { | ||
map$$1.removeLayer(c.item); | ||
}); | ||
changes.forEachAddedItem(function (c) { | ||
map$$1.addLayer(c.item); | ||
}); | ||
} | ||
} | ||
@@ -236,2 +232,3 @@ }; | ||
{ type: LeafletDirective, }, | ||
{ type: _angular_core.IterableDiffers, }, | ||
]; }; | ||
@@ -242,80 +239,14 @@ LeafletLayersDirective.propDecorators = { | ||
var LeafletUtil = (function () { | ||
function LeafletUtil() { | ||
var LeafletControlLayersChanges = (function () { | ||
function LeafletControlLayersChanges() { | ||
this.layersRemoved = 0; | ||
this.layersChanged = 0; | ||
this.layersAdded = 0; | ||
} | ||
/** | ||
* Combine two associative arrays in a shallow manner. Where there are duplicate properties, | ||
* the value in the second object will overwrite the value of the first object | ||
* | ||
* @param aMap The first object | ||
* @param bMap The second object | ||
* @returns {{}} The aggregate of both objects | ||
*/ | ||
LeafletUtil.mergeMaps = function (aMap, bMap) { | ||
var toReturn = {}; | ||
if (null != aMap) { | ||
for (var k in aMap) { | ||
if (aMap.hasOwnProperty(k)) { | ||
toReturn[k] = aMap[k]; | ||
} | ||
} | ||
} | ||
if (null != bMap) { | ||
for (var k in bMap) { | ||
if (bMap.hasOwnProperty(k)) { | ||
toReturn[k] = bMap[k]; | ||
} | ||
} | ||
} | ||
return toReturn; | ||
LeafletControlLayersChanges.prototype.changed = function () { | ||
return !(this.layersRemoved === 0 && this.layersChanged === 0 && this.layersAdded === 0); | ||
}; | ||
/** | ||
* Subtracts the properties of an associative array in a shallow manner. | ||
* Where there are duplicate properties, the properties will be removed | ||
* from the first object. | ||
* | ||
* @param aMap The object from which to subtract properties | ||
* @param bMap The object containing properties to subtract | ||
* @returns {{}} | ||
*/ | ||
LeafletUtil.mapSubtract = function (aMap, bMap) { | ||
var toReturn = {}; | ||
if (null != aMap) { | ||
// Copy all of aMap into toReturn | ||
for (var k in aMap) { | ||
if (aMap.hasOwnProperty(k)) { | ||
toReturn[k] = aMap[k]; | ||
} | ||
} | ||
// If there's a bMap, delete all bMap keys from aMap | ||
if (null != bMap) { | ||
for (var k in bMap) { | ||
if (bMap.hasOwnProperty(k)) { | ||
delete toReturn[k]; | ||
} | ||
} | ||
} | ||
} | ||
return toReturn; | ||
}; | ||
LeafletUtil.mapToArray = function (map$$1) { | ||
var toReturn = []; | ||
for (var k in map$$1) { | ||
if (map$$1.hasOwnProperty(k)) { | ||
toReturn.push(map$$1[k]); | ||
} | ||
} | ||
return toReturn; | ||
}; | ||
return LeafletUtil; | ||
return LeafletControlLayersChanges; | ||
}()); | ||
var LeafletLayersObjectDiff = (function () { | ||
function LeafletLayersObjectDiff(remove, add) { | ||
this.remove = remove; | ||
this.add = add; | ||
} | ||
return LeafletLayersObjectDiff; | ||
}()); | ||
var LeafletControlLayersWrapper = (function () { | ||
@@ -333,34 +264,35 @@ function LeafletControlLayersWrapper() { | ||
}; | ||
LeafletControlLayersWrapper.prototype.setLayersControlConfig = function (newConfig, prevConfig) { | ||
if (null == this.layersControl) { | ||
return new LeafletLayersObjectDiff({}, {}); | ||
LeafletControlLayersWrapper.prototype.applyBaseLayerChanges = function (changes) { | ||
var results = new LeafletControlLayersChanges(); | ||
if (null != this.layersControl) { | ||
results = this.applyChanges(changes, this.layersControl.addBaseLayer); | ||
} | ||
var toRemove; | ||
var baseLayers; | ||
var overlays; | ||
// Figure out which layers need to be removed (prev - new) | ||
toRemove = LeafletUtil.mergeMaps(LeafletUtil.mapSubtract(prevConfig.baseLayers, newConfig.baseLayers), LeafletUtil.mapSubtract(prevConfig.overlays, newConfig.overlays)); | ||
// Figure out which layers need to be added (new - prev) | ||
baseLayers = LeafletUtil.mapSubtract(newConfig.baseLayers, prevConfig.baseLayers); | ||
overlays = LeafletUtil.mapSubtract(newConfig.overlays, prevConfig.overlays); | ||
// Do the actual removal and addition | ||
for (var k in toRemove) { | ||
if (toRemove.hasOwnProperty(k)) { | ||
var l = toRemove[k]; | ||
this.layersControl.removeLayer(l); | ||
} | ||
return results; | ||
}; | ||
LeafletControlLayersWrapper.prototype.applyOverlayChanges = function (changes) { | ||
var results = new LeafletControlLayersChanges(); | ||
if (null != this.layersControl) { | ||
results = this.applyChanges(changes, this.layersControl.addOverlay); | ||
} | ||
for (var k in baseLayers) { | ||
if (baseLayers.hasOwnProperty(k)) { | ||
var l = baseLayers[k]; | ||
this.layersControl.addBaseLayer(l, k); | ||
} | ||
return results; | ||
}; | ||
LeafletControlLayersWrapper.prototype.applyChanges = function (changes, addFn) { | ||
var _this = this; | ||
var results = new LeafletControlLayersChanges(); | ||
if (null != changes) { | ||
changes.forEachChangedItem(function (c) { | ||
_this.layersControl.removeLayer(c.previousValue); | ||
addFn.call(_this.layersControl, c.currentValue, c.key); | ||
results.layersChanged++; | ||
}); | ||
changes.forEachRemovedItem(function (c) { | ||
_this.layersControl.removeLayer(c.currentValue); | ||
results.layersRemoved++; | ||
}); | ||
changes.forEachAddedItem(function (c) { | ||
addFn.call(_this.layersControl, c.currentValue, c.key); | ||
results.layersAdded++; | ||
}); | ||
} | ||
for (var k in overlays) { | ||
if (overlays.hasOwnProperty(k)) { | ||
var l = overlays[k]; | ||
this.layersControl.addOverlay(l, k); | ||
} | ||
} | ||
return new LeafletLayersObjectDiff(toRemove, LeafletUtil.mergeMaps(baseLayers, overlays)); | ||
return results; | ||
}; | ||
@@ -370,7 +302,52 @@ return LeafletControlLayersWrapper; | ||
var LeafletControlLayersConfig = (function () { | ||
function LeafletControlLayersConfig() { | ||
this.baseLayers = {}; | ||
this.overlays = {}; | ||
} | ||
return LeafletControlLayersConfig; | ||
}()); | ||
/** | ||
* Layers Control | ||
* | ||
* This directive is used to configure the layers control. The input accepts an object with two | ||
* key-value maps of layer name -> layer. Mutable changes are detected. On changes, a differ is | ||
* used to determine what changed so that layers are appropriately added or removed. | ||
* | ||
* To specify which layer to show as the 'active' baselayer, you will want to add it to the map | ||
* using the layers directive. Otherwise, the last one it sees will be used. | ||
*/ | ||
var LeafletLayersControlDirective = (function () { | ||
function LeafletLayersControlDirective(leafletDirective) { | ||
function LeafletLayersControlDirective(leafletDirective, differs) { | ||
this.differs = differs; | ||
this.leafletDirective = new LeafletDirectiveWrapper(leafletDirective); | ||
this.controlLayers = new LeafletControlLayersWrapper(); | ||
// Generate differs | ||
this.baseLayersDiffer = this.differs.find({}).create(); | ||
this.overlaysDiffer = this.differs.find({}).create(); | ||
} | ||
Object.defineProperty(LeafletLayersControlDirective.prototype, "layersControlConfig", { | ||
get: function () { | ||
return this.layersControlConfigValue; | ||
}, | ||
set: function (v) { | ||
// Validation/init stuff | ||
if (null == v) { | ||
v = new LeafletControlLayersConfig(); | ||
} | ||
if (null == v.baseLayers) { | ||
v.baseLayers = {}; | ||
} | ||
if (null == v.overlays) { | ||
v.overlays = {}; | ||
} | ||
// Store the value | ||
this.layersControlConfigValue = v; | ||
// Update the map | ||
this.updateLayers(); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
LeafletLayersControlDirective.prototype.ngOnInit = function () { | ||
@@ -381,9 +358,23 @@ // Init the map | ||
this.controlLayers | ||
.init(this.layersControlConfig, this.layersControlOptions) | ||
.init({}, this.layersControlOptions) | ||
.addTo(this.leafletDirective.getMap()); | ||
this.updateLayers(); | ||
}; | ||
LeafletLayersControlDirective.prototype.ngOnChanges = function (changes) { | ||
// Set the layers | ||
if (changes['layersControlCfg']) { | ||
this.controlLayers.setLayersControlConfig(changes['layersControlCfg'].currentValue, changes['layersControlCfg'].previousValue); | ||
LeafletLayersControlDirective.prototype.ngDoCheck = function () { | ||
this.updateLayers(); | ||
}; | ||
LeafletLayersControlDirective.prototype.updateLayers = function () { | ||
var map$$1 = this.leafletDirective.getMap(); | ||
var layersControl = this.controlLayers.getLayersControl(); | ||
if (null != map$$1 && null != layersControl) { | ||
// Run the baselayers differ | ||
if (null != this.baseLayersDiffer && null != this.layersControlConfigValue.baseLayers) { | ||
var changes = this.baseLayersDiffer.diff(this.layersControlConfigValue.baseLayers); | ||
this.controlLayers.applyBaseLayerChanges(changes); | ||
} | ||
// Run the overlays differ | ||
if (null != this.overlaysDiffer && null != this.layersControlConfigValue.overlays) { | ||
var changes = this.overlaysDiffer.diff(this.layersControlConfigValue.overlays); | ||
this.controlLayers.applyOverlayChanges(changes); | ||
} | ||
} | ||
@@ -401,2 +392,3 @@ }; | ||
{ type: LeafletDirective, }, | ||
{ type: _angular_core.KeyValueDiffers, }, | ||
]; }; | ||
@@ -408,15 +400,47 @@ LeafletLayersControlDirective.propDecorators = { | ||
var LeafletControlLayersConfig = (function () { | ||
function LeafletControlLayersConfig(baseLayers, overlays) { | ||
this.baseLayers = baseLayers; | ||
this.overlays = overlays; | ||
var LeafletUtil = (function () { | ||
function LeafletUtil() { | ||
} | ||
return LeafletControlLayersConfig; | ||
LeafletUtil.mapToArray = function (map$$1) { | ||
var toReturn = []; | ||
for (var k in map$$1) { | ||
if (map$$1.hasOwnProperty(k)) { | ||
toReturn.push(map$$1[k]); | ||
} | ||
} | ||
return toReturn; | ||
}; | ||
return LeafletUtil; | ||
}()); | ||
/** | ||
* Baselayers directive | ||
* | ||
* This directive is provided as a convenient way to add baselayers to the map. The input accepts | ||
* a key-value map of layer name -> layer. Mutable changed are detected. On changes, a differ is | ||
* used to determine what changed so that layers are appropriately added or removed. This directive | ||
* will also add the layers control so users can switch between available base layers. | ||
* | ||
* To specify which layer to show as the 'active' baselayer, you will want to add it to the map | ||
* using the layers directive. Otherwise, the plugin will use the last one it sees. | ||
*/ | ||
var LeafletBaseLayersDirective = (function () { | ||
function LeafletBaseLayersDirective(leafletDirective) { | ||
function LeafletBaseLayersDirective(leafletDirective, differs) { | ||
this.differs = differs; | ||
this.leafletDirective = new LeafletDirectiveWrapper(leafletDirective); | ||
this.controlLayers = new LeafletControlLayersWrapper(); | ||
this.baseLayersDiffer = this.differs.find({}).create(); | ||
} | ||
Object.defineProperty(LeafletBaseLayersDirective.prototype, "baseLayers", { | ||
get: function () { | ||
return this.baseLayersValue; | ||
}, | ||
// Set/get baseLayers | ||
set: function (v) { | ||
this.baseLayersValue = v; | ||
this.updateBaseLayers(); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
LeafletBaseLayersDirective.prototype.ngOnInit = function () { | ||
@@ -427,19 +451,20 @@ // Init the map | ||
this.controlLayers | ||
.init({ baseLayers: this.baseLayers }, this.layersControlOptions) | ||
.init({}, this.layersControlOptions) | ||
.addTo(this.leafletDirective.getMap()); | ||
// Sync the baselayer (will default to the first layer in the map) | ||
this.syncBaseLayer(); | ||
this.updateBaseLayers(); | ||
}; | ||
LeafletBaseLayersDirective.prototype.ngOnChanges = function (changes) { | ||
// Set the new baseLayers | ||
if (changes['baseLayers']) { | ||
this.setBaseLayers(changes['baseLayers'].currentValue, changes['baseLayers'].previousValue); | ||
LeafletBaseLayersDirective.prototype.ngDoCheck = function () { | ||
this.updateBaseLayers(); | ||
}; | ||
LeafletBaseLayersDirective.prototype.updateBaseLayers = function () { | ||
var map$$1 = this.leafletDirective.getMap(); | ||
var layersControl = this.controlLayers.getLayersControl(); | ||
if (null != map$$1 && null != layersControl && null != this.baseLayersDiffer) { | ||
var changes = this.baseLayersDiffer.diff(this.baseLayersValue); | ||
var results = this.controlLayers.applyBaseLayerChanges(changes); | ||
if (results.changed()) { | ||
this.syncBaseLayer(); | ||
} | ||
} | ||
}; | ||
LeafletBaseLayersDirective.prototype.setBaseLayers = function (newBaseLayers, prevBaseLayers) { | ||
// Update the layers control | ||
this.controlLayers.setLayersControlConfig(new LeafletControlLayersConfig(newBaseLayers), new LeafletControlLayersConfig(prevBaseLayers)); | ||
// Sync the new baseLayer | ||
this.syncBaseLayer(); | ||
}; | ||
/** | ||
@@ -479,2 +504,3 @@ * Check the current base layer and change it to the new one if necessary | ||
{ type: LeafletDirective, }, | ||
{ type: _angular_core.KeyValueDiffers, }, | ||
]; }; | ||
@@ -513,17 +539,2 @@ LeafletBaseLayersDirective.propDecorators = { | ||
var LeafletControlLayersUtil = (function () { | ||
function LeafletControlLayersUtil() { | ||
} | ||
LeafletControlLayersUtil.prototype.diffLayers = function (newLayers, prevLayers) { | ||
var toRemove; | ||
var toAdd; | ||
// Figure out which layers need to be removed (prev - new) | ||
toRemove = LeafletUtil.mapSubtract(prevLayers, newLayers); | ||
// Figure out which layers need to be added (new - prev) | ||
toAdd = LeafletUtil.mapSubtract(newLayers, prevLayers); | ||
return new LeafletLayersObjectDiff(toRemove, toAdd); | ||
}; | ||
return LeafletControlLayersUtil; | ||
}()); | ||
var LeafletTileLayerDefinition = (function () { | ||
@@ -585,4 +596,2 @@ function LeafletTileLayerDefinition(type, url, options) { | ||
exports.LeafletDirectiveWrapper = LeafletDirectiveWrapper; | ||
exports.LeafletControlLayersUtil = LeafletControlLayersUtil; | ||
exports.LeafletLayersUtil = LeafletLayersUtil; | ||
exports.LeafletTileLayerDefinition = LeafletTileLayerDefinition; | ||
@@ -589,0 +598,0 @@ |
@@ -1,2 +0,2 @@ | ||
/*! @asymmetrik/angular2-leaflet - 2.1.5 - Copyright Asymmetrik, Ltd. 2007-2017 - All Rights Reserved. + */ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@angular/core"),require("leaflet")):"function"==typeof define&&define.amd?define(["exports","@angular/core","leaflet"],e):e(t.angular2Leaflet=t.angular2Leaflet||{},t.ng.core,t.L)}(this,function(t,e,r){"use strict";var n=function(){function t(t){this.DEFAULT_ZOOM=1,this.DEFAULT_CENTER=r.latLng([38.907192,-77.036871]),this.DEFAULT_FPZ_OPTIONS={},this.fitBoundsOptions=this.DEFAULT_FPZ_OPTIONS,this.panOptions=this.DEFAULT_FPZ_OPTIONS,this.zoomOptions=this.DEFAULT_FPZ_OPTIONS,this.zoomPanOptions=this.DEFAULT_FPZ_OPTIONS,this.options={},this.mapReady=new e.EventEmitter,this.element=t}return t.prototype.ngOnInit=function(){this.map=r.map(this.element.nativeElement,this.options),null!=this.center&&null!=this.zoom&&this.setView(this.center,this.zoom),null!=this.fitBounds&&this.setFitBounds(this.fitBounds),this.doResize(),this.mapReady.emit(this.map)},t.prototype.ngOnChanges=function(t){t.zoom&&t.center&&null!=this.zoom&&null!=this.center?this.setView(t.center.currentValue,t.zoom.currentValue):t.zoom?this.setZoom(t.zoom.currentValue):t.center&&this.setCenter(t.center.currentValue),t.fitBounds&&this.setFitBounds(t.fitBounds.currentValue)},t.prototype.getMap=function(){return this.map},t.prototype.onResize=function(){this.delayResize()},t.prototype.doResize=function(){this.map.invalidateSize({})},t.prototype.delayResize=function(){null!=this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(this.doResize.bind(this),200)},t.prototype.setView=function(t,e){this.map&&null!=t&&null!=e&&this.map.setView(t,e,this.zoomPanOptions)},t.prototype.setZoom=function(t){this.map&&null!=t&&this.map.setZoom(t,this.zoomOptions)},t.prototype.setCenter=function(t){this.map&&null!=t&&this.map.panTo(t,this.panOptions)},t.prototype.setFitBounds=function(t){this.map&&null!=t&&this.map.fitBounds(t,this.fitBoundsOptions)},t}();n.decorators=[{type:e.Directive,args:[{selector:"[leaflet]"}]}],n.ctorParameters=function(){return[{type:e.ElementRef}]},n.propDecorators={fitBoundsOptions:[{type:e.Input,args:["leafletFitBoundsOptions"]}],panOptions:[{type:e.Input,args:["leafletPanOptions"]}],zoomOptions:[{type:e.Input,args:["leafletZoomOptions"]}],zoomPanOptions:[{type:e.Input,args:["leafletZoomPanOptions"]}],options:[{type:e.Input,args:["leafletOptions"]}],mapReady:[{type:e.Output,args:["leafletMapReady"]}],zoom:[{type:e.Input,args:["leafletZoom"]}],center:[{type:e.Input,args:["leafletCenter"]}],fitBounds:[{type:e.Input,args:["leafletFitBounds"]}],onResize:[{type:e.HostListener,args:["window:resize",[]]}]};var o=function(){function t(t){this.leafletDirective=t}return t.prototype.init=function(){},t.prototype.getMap=function(){return this.leafletDirective.getMap()},t}(),i=function(){function t(t,e){this.remove=t,this.add=e}return t}(),s=function(){function t(){}return t.diffLayers=function(t,e){var r,n;return null==t&&(t=[]),null==e&&(e=[]),r=e.filter(function(e){return!t.find(function(t){return e===t})}),n=t.filter(function(t){return!e.find(function(e){return t===e})}),new i(r,n)},t}(),a=function(){function t(t){this.leafletDirective=new o(t)}return t.prototype.ngOnInit=function(){this.leafletDirective.init(),this.setLayers(this.layers,[])},t.prototype.ngOnChanges=function(t){if(t.layers){var e=t.layers.currentValue,r=t.layers.isFirstChange()?[]:t.layers.previousValue;this.setLayers(e,r)}},t.prototype.setLayers=function(t,e){var r=this.leafletDirective.getMap();if(null!=r){var n=s.diffLayers(t,e);n.remove.forEach(function(t){r.removeLayer(t)}),n.add.forEach(function(t){r.addLayer(t)})}},t}();a.decorators=[{type:e.Directive,args:[{selector:"[leafletLayers]"}]}],a.ctorParameters=function(){return[{type:n}]},a.propDecorators={layers:[{type:e.Input,args:["leafletLayers"]}]};var l=function(){function t(){}return t.mergeMaps=function(t,e){var r={};if(null!=t)for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);if(null!=e)for(var n in e)e.hasOwnProperty(n)&&(r[n]=e[n]);return r},t.mapSubtract=function(t,e){var r={};if(null!=t){for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);if(null!=e)for(var n in e)e.hasOwnProperty(n)&&delete r[n]}return r},t.mapToArray=function(t){var e=[];for(var r in t)t.hasOwnProperty(r)&&e.push(t[r]);return e},t}(),u=function(){function t(t,e){this.remove=t,this.add=e}return t}(),p=function(){function t(){}return t.prototype.getLayersControl=function(){return this.layersControl},t.prototype.init=function(t,e){var n=t.baseLayers||{},o=t.overlays||{};return this.layersControl=r.control.layers(n,o,e),this.layersControl},t.prototype.setLayersControlConfig=function(t,e){if(null==this.layersControl)return new u({},{});var r,n,o;r=l.mergeMaps(l.mapSubtract(e.baseLayers,t.baseLayers),l.mapSubtract(e.overlays,t.overlays)),n=l.mapSubtract(t.baseLayers,e.baseLayers),o=l.mapSubtract(t.overlays,e.overlays);for(var i in r)if(r.hasOwnProperty(i)){var s=r[i];this.layersControl.removeLayer(s)}for(var i in n)if(n.hasOwnProperty(i)){var s=n[i];this.layersControl.addBaseLayer(s,i)}for(var i in o)if(o.hasOwnProperty(i)){var s=o[i];this.layersControl.addOverlay(s,i)}return new u(r,l.mergeMaps(n,o))},t}(),f=function(){function t(t){this.leafletDirective=new o(t),this.controlLayers=new p}return t.prototype.ngOnInit=function(){this.leafletDirective.init(),this.controlLayers.init(this.layersControlConfig,this.layersControlOptions).addTo(this.leafletDirective.getMap())},t.prototype.ngOnChanges=function(t){t.layersControlCfg&&this.controlLayers.setLayersControlConfig(t.layersControlCfg.currentValue,t.layersControlCfg.previousValue)},t}();f.decorators=[{type:e.Directive,args:[{selector:"[leafletLayersControl]"}]}],f.ctorParameters=function(){return[{type:n}]},f.propDecorators={layersControlConfig:[{type:e.Input,args:["leafletLayersControl"]}],layersControlOptions:[{type:e.Input,args:["leafletLayersControlOptions"]}]};var y=function(){function t(t,e){this.baseLayers=t,this.overlays=e}return t}(),c=function(){function t(t){this.leafletDirective=new o(t),this.controlLayers=new p}return t.prototype.ngOnInit=function(){this.leafletDirective.init(),this.controlLayers.init({baseLayers:this.baseLayers},this.layersControlOptions).addTo(this.leafletDirective.getMap()),this.syncBaseLayer()},t.prototype.ngOnChanges=function(t){t.baseLayers&&this.setBaseLayers(t.baseLayers.currentValue,t.baseLayers.previousValue)},t.prototype.setBaseLayers=function(t,e){this.controlLayers.setLayersControlConfig(new y(t),new y(e)),this.syncBaseLayer()},t.prototype.syncBaseLayer=function(){var t,e=this.leafletDirective.getMap(),r=l.mapToArray(this.baseLayers);e.eachLayer(function(e){t=r.find(function(t){return e===t})}),null!=t?this.baseLayer=t:r.length>0&&(this.baseLayer=r[0],this.baseLayer.addTo(e))},t}();c.decorators=[{type:e.Directive,args:[{selector:"[leafletBaseLayers]"}]}],c.ctorParameters=function(){return[{type:n}]},c.propDecorators={baseLayers:[{type:e.Input,args:["leafletBaseLayers"]}],layersControlOptions:[{type:e.Input,args:["leafletLayersControlOptions"]}]};var h=function(){function t(){}return t.forRoot=function(){return{ngModule:t,providers:[]}},t}();h.decorators=[{type:e.NgModule,args:[{exports:[n,a,f,c],declarations:[n,a,f,c]}]}],h.ctorParameters=function(){return[]};var m=function(){function t(){}return t.prototype.diffLayers=function(t,e){var r,n;return r=l.mapSubtract(e,t),n=l.mapSubtract(t,e),new u(r,n)},t}(),d=function(){function t(t,e,r){this.type=t,this.url=e,this.options=r}return t.createTileLayer=function(t){var e;switch(t.type){case"xyz":e=L.tileLayer(t.url,t.options);break;case"wms":default:e=L.tileLayer.wms(t.url,t.options)}return e},t.createTileLayers=function(e){var r={};for(var n in e)e.hasOwnProperty(n)&&(r[n]=t.createTileLayer(e[n]));return r},t.prototype.createTileLayer=function(){return t.createTileLayer(this)},t}();t.LeafletModule=h,t.LeafletDirective=n,t.LeafletDirectiveWrapper=o,t.LeafletControlLayersUtil=m,t.LeafletLayersUtil=s,t.LeafletTileLayerDefinition=d,Object.defineProperty(t,"__esModule",{value:!0})}); | ||
/*! @asymmetrik/angular2-leaflet - 2.2.0 - Copyright Asymmetrik, Ltd. 2007-2017 - All Rights Reserved. + */ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@angular/core"),require("leaflet")):"function"==typeof define&&define.amd?define(["exports","@angular/core","leaflet"],t):t(e.angular2Leaflet=e.angular2Leaflet||{},e.ng.core,e.L)}(this,function(e,t,r){"use strict";var n=function(){function e(e){this.DEFAULT_ZOOM=1,this.DEFAULT_CENTER=r.latLng([38.907192,-77.036871]),this.DEFAULT_FPZ_OPTIONS={},this.fitBoundsOptions=this.DEFAULT_FPZ_OPTIONS,this.panOptions=this.DEFAULT_FPZ_OPTIONS,this.zoomOptions=this.DEFAULT_FPZ_OPTIONS,this.zoomPanOptions=this.DEFAULT_FPZ_OPTIONS,this.options={},this.mapReady=new t.EventEmitter,this.element=e}return e.prototype.ngOnInit=function(){this.map=r.map(this.element.nativeElement,this.options),null!=this.center&&null!=this.zoom&&this.setView(this.center,this.zoom),null!=this.fitBounds&&this.setFitBounds(this.fitBounds),this.doResize(),this.mapReady.emit(this.map)},e.prototype.ngOnChanges=function(e){e.zoom&&e.center&&null!=this.zoom&&null!=this.center?this.setView(e.center.currentValue,e.zoom.currentValue):e.zoom?this.setZoom(e.zoom.currentValue):e.center&&this.setCenter(e.center.currentValue),e.fitBounds&&this.setFitBounds(e.fitBounds.currentValue)},e.prototype.getMap=function(){return this.map},e.prototype.onResize=function(){this.delayResize()},e.prototype.doResize=function(){this.map.invalidateSize({})},e.prototype.delayResize=function(){null!=this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(this.doResize.bind(this),200)},e.prototype.setView=function(e,t){this.map&&null!=e&&null!=t&&this.map.setView(e,t,this.zoomPanOptions)},e.prototype.setZoom=function(e){this.map&&null!=e&&this.map.setZoom(e,this.zoomOptions)},e.prototype.setCenter=function(e){this.map&&null!=e&&this.map.panTo(e,this.panOptions)},e.prototype.setFitBounds=function(e){this.map&&null!=e&&this.map.fitBounds(e,this.fitBoundsOptions)},e}();n.decorators=[{type:t.Directive,args:[{selector:"[leaflet]"}]}],n.ctorParameters=function(){return[{type:t.ElementRef}]},n.propDecorators={fitBoundsOptions:[{type:t.Input,args:["leafletFitBoundsOptions"]}],panOptions:[{type:t.Input,args:["leafletPanOptions"]}],zoomOptions:[{type:t.Input,args:["leafletZoomOptions"]}],zoomPanOptions:[{type:t.Input,args:["leafletZoomPanOptions"]}],options:[{type:t.Input,args:["leafletOptions"]}],mapReady:[{type:t.Output,args:["leafletMapReady"]}],zoom:[{type:t.Input,args:["leafletZoom"]}],center:[{type:t.Input,args:["leafletCenter"]}],fitBounds:[{type:t.Input,args:["leafletFitBounds"]}],onResize:[{type:t.HostListener,args:["window:resize",[]]}]};var i=function(){function e(e){this.leafletDirective=e}return e.prototype.init=function(){},e.prototype.getMap=function(){return this.leafletDirective.getMap()},e}(),s=function(){function e(e,t){this.differs=t,this.leafletDirective=new i(e),this.layersDiffer=this.differs.find([]).create()}return Object.defineProperty(e.prototype,"layers",{get:function(){return this.layersValue},set:function(e){this.layersValue=e,this.updateLayers()},enumerable:!0,configurable:!0}),e.prototype.ngDoCheck=function(){this.updateLayers()},e.prototype.ngOnInit=function(){this.leafletDirective.init(),this.updateLayers()},e.prototype.updateLayers=function(){var e=this.leafletDirective.getMap();if(null!=e&&null!=this.layersDiffer){var t=this.layersDiffer.diff(this.layersValue);null!=t&&(t.forEachRemovedItem(function(t){e.removeLayer(t.item)}),t.forEachAddedItem(function(t){e.addLayer(t.item)}))}},e}();s.decorators=[{type:t.Directive,args:[{selector:"[leafletLayers]"}]}],s.ctorParameters=function(){return[{type:n},{type:t.IterableDiffers}]},s.propDecorators={layers:[{type:t.Input,args:["leafletLayers"]}]};var o=function(){function e(){this.layersRemoved=0,this.layersChanged=0,this.layersAdded=0}return e.prototype.changed=function(){return!(0===this.layersRemoved&&0===this.layersChanged&&0===this.layersAdded)},e}(),a=function(){function e(){}return e.prototype.getLayersControl=function(){return this.layersControl},e.prototype.init=function(e,t){var n=e.baseLayers||{},i=e.overlays||{};return this.layersControl=r.control.layers(n,i,t),this.layersControl},e.prototype.applyBaseLayerChanges=function(e){var t=new o;return null!=this.layersControl&&(t=this.applyChanges(e,this.layersControl.addBaseLayer)),t},e.prototype.applyOverlayChanges=function(e){var t=new o;return null!=this.layersControl&&(t=this.applyChanges(e,this.layersControl.addOverlay)),t},e.prototype.applyChanges=function(e,t){var r=this,n=new o;return null!=e&&(e.forEachChangedItem(function(e){r.layersControl.removeLayer(e.previousValue),t.call(r.layersControl,e.currentValue,e.key),n.layersChanged++}),e.forEachRemovedItem(function(e){r.layersControl.removeLayer(e.currentValue),n.layersRemoved++}),e.forEachAddedItem(function(e){t.call(r.layersControl,e.currentValue,e.key),n.layersAdded++})),n},e}(),l=function(){function e(){this.baseLayers={},this.overlays={}}return e}(),u=function(){function e(e,t){this.differs=t,this.leafletDirective=new i(e),this.controlLayers=new a,this.baseLayersDiffer=this.differs.find({}).create(),this.overlaysDiffer=this.differs.find({}).create()}return Object.defineProperty(e.prototype,"layersControlConfig",{get:function(){return this.layersControlConfigValue},set:function(e){null==e&&(e=new l),null==e.baseLayers&&(e.baseLayers={}),null==e.overlays&&(e.overlays={}),this.layersControlConfigValue=e,this.updateLayers()},enumerable:!0,configurable:!0}),e.prototype.ngOnInit=function(){this.leafletDirective.init(),this.controlLayers.init({},this.layersControlOptions).addTo(this.leafletDirective.getMap()),this.updateLayers()},e.prototype.ngDoCheck=function(){this.updateLayers()},e.prototype.updateLayers=function(){var e=this.leafletDirective.getMap(),t=this.controlLayers.getLayersControl();if(null!=e&&null!=t){if(null!=this.baseLayersDiffer&&null!=this.layersControlConfigValue.baseLayers){var r=this.baseLayersDiffer.diff(this.layersControlConfigValue.baseLayers);this.controlLayers.applyBaseLayerChanges(r)}if(null!=this.overlaysDiffer&&null!=this.layersControlConfigValue.overlays){var r=this.overlaysDiffer.diff(this.layersControlConfigValue.overlays);this.controlLayers.applyOverlayChanges(r)}}},e}();u.decorators=[{type:t.Directive,args:[{selector:"[leafletLayersControl]"}]}],u.ctorParameters=function(){return[{type:n},{type:t.KeyValueDiffers}]},u.propDecorators={layersControlConfig:[{type:t.Input,args:["leafletLayersControl"]}],layersControlOptions:[{type:t.Input,args:["leafletLayersControlOptions"]}]};var p=function(){function e(){}return e.mapToArray=function(e){var t=[];for(var r in e)e.hasOwnProperty(r)&&t.push(e[r]);return t},e}(),f=function(){function e(e,t){this.differs=t,this.leafletDirective=new i(e),this.controlLayers=new a,this.baseLayersDiffer=this.differs.find({}).create()}return Object.defineProperty(e.prototype,"baseLayers",{get:function(){return this.baseLayersValue},set:function(e){this.baseLayersValue=e,this.updateBaseLayers()},enumerable:!0,configurable:!0}),e.prototype.ngOnInit=function(){this.leafletDirective.init(),this.controlLayers.init({},this.layersControlOptions).addTo(this.leafletDirective.getMap()),this.updateBaseLayers()},e.prototype.ngDoCheck=function(){this.updateBaseLayers()},e.prototype.updateBaseLayers=function(){var e=this.leafletDirective.getMap(),t=this.controlLayers.getLayersControl();if(null!=e&&null!=t&&null!=this.baseLayersDiffer){var r=this.baseLayersDiffer.diff(this.baseLayersValue);this.controlLayers.applyBaseLayerChanges(r).changed()&&this.syncBaseLayer()}},e.prototype.syncBaseLayer=function(){var e,t=this.leafletDirective.getMap(),r=p.mapToArray(this.baseLayers);t.eachLayer(function(t){e=r.find(function(e){return t===e})}),null!=e?this.baseLayer=e:r.length>0&&(this.baseLayer=r[0],this.baseLayer.addTo(t))},e}();f.decorators=[{type:t.Directive,args:[{selector:"[leafletBaseLayers]"}]}],f.ctorParameters=function(){return[{type:n},{type:t.KeyValueDiffers}]},f.propDecorators={baseLayers:[{type:t.Input,args:["leafletBaseLayers"]}],layersControlOptions:[{type:t.Input,args:["leafletLayersControlOptions"]}]};var y=function(){function e(){}return e.forRoot=function(){return{ngModule:e,providers:[]}},e}();y.decorators=[{type:t.NgModule,args:[{exports:[n,s,u,f],declarations:[n,s,u,f]}]}],y.ctorParameters=function(){return[]};var c=function(){function e(e,t,r){this.type=e,this.url=t,this.options=r}return e.createTileLayer=function(e){var t;switch(e.type){case"xyz":t=L.tileLayer(e.url,e.options);break;case"wms":default:t=L.tileLayer.wms(e.url,e.options)}return t},e.createTileLayers=function(t){var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=e.createTileLayer(t[n]));return r},e.prototype.createTileLayer=function(){return e.createTileLayer(this)},e}();e.LeafletModule=y,e.LeafletDirective=n,e.LeafletDirectiveWrapper=i,e.LeafletTileLayerDefinition=c,Object.defineProperty(e,"__esModule",{value:!0})}); |
export { LeafletModule } from './leaflet/leaflet.module'; | ||
export { LeafletDirective } from './leaflet/core/leaflet.directive'; | ||
export { LeafletDirectiveWrapper } from './leaflet/core/leaflet.directive.wrapper'; | ||
export { LeafletControlLayersUtil } from './leaflet/layers/control/leaflet-control-layers.util'; | ||
export { LeafletLayersUtil } from './leaflet/layers/leaflet-layers.util'; | ||
export { LeafletTileLayerDefinition } from './leaflet/layers/leaflet-tile-layer-definition.model'; |
export { LeafletModule } from './leaflet/leaflet.module'; | ||
export { LeafletDirective } from './leaflet/core/leaflet.directive'; | ||
export { LeafletDirectiveWrapper } from './leaflet/core/leaflet.directive.wrapper'; | ||
export { LeafletControlLayersUtil } from './leaflet/layers/control/leaflet-control-layers.util'; | ||
export { LeafletLayersUtil } from './leaflet/layers/leaflet-layers.util'; | ||
export { LeafletTileLayerDefinition } from './leaflet/layers/leaflet-tile-layer-definition.model'; | ||
//# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
[{"__symbolic":"module","version":3,"metadata":{},"exports":[{"from":"./leaflet/leaflet.module","export":["LeafletModule"]},{"from":"./leaflet/core/leaflet.directive","export":["LeafletDirective"]},{"from":"./leaflet/core/leaflet.directive.wrapper","export":["LeafletDirectiveWrapper"]},{"from":"./leaflet/layers/control/leaflet-control-layers.util","export":["LeafletControlLayersUtil"]},{"from":"./leaflet/layers/leaflet-layers.util","export":["LeafletLayersUtil"]},{"from":"./leaflet/layers/leaflet-tile-layer-definition.model","export":["LeafletTileLayerDefinition"]}]},{"__symbolic":"module","version":1,"metadata":{},"exports":[{"from":"./leaflet/leaflet.module","export":["LeafletModule"]},{"from":"./leaflet/core/leaflet.directive","export":["LeafletDirective"]},{"from":"./leaflet/core/leaflet.directive.wrapper","export":["LeafletDirectiveWrapper"]},{"from":"./leaflet/layers/control/leaflet-control-layers.util","export":["LeafletControlLayersUtil"]},{"from":"./leaflet/layers/leaflet-layers.util","export":["LeafletLayersUtil"]},{"from":"./leaflet/layers/leaflet-tile-layer-definition.model","export":["LeafletTileLayerDefinition"]}]}] | ||
[{"__symbolic":"module","version":3,"metadata":{},"exports":[{"from":"./leaflet/leaflet.module","export":["LeafletModule"]},{"from":"./leaflet/core/leaflet.directive","export":["LeafletDirective"]},{"from":"./leaflet/core/leaflet.directive.wrapper","export":["LeafletDirectiveWrapper"]},{"from":"./leaflet/layers/leaflet-tile-layer-definition.model","export":["LeafletTileLayerDefinition"]}]},{"__symbolic":"module","version":1,"metadata":{},"exports":[{"from":"./leaflet/leaflet.module","export":["LeafletModule"]},{"from":"./leaflet/core/leaflet.directive","export":["LeafletDirective"]},{"from":"./leaflet/core/leaflet.directive.wrapper","export":["LeafletDirectiveWrapper"]},{"from":"./leaflet/layers/leaflet-tile-layer-definition.model","export":["LeafletTileLayerDefinition"]}]}] |
export declare class LeafletUtil { | ||
/** | ||
* Combine two associative arrays in a shallow manner. Where there are duplicate properties, | ||
* the value in the second object will overwrite the value of the first object | ||
* | ||
* @param aMap The first object | ||
* @param bMap The second object | ||
* @returns {{}} The aggregate of both objects | ||
*/ | ||
static mergeMaps<T>(aMap: { | ||
[key: string]: T; | ||
}, bMap: { | ||
[key: string]: T; | ||
}): { | ||
[key: string]: T; | ||
}; | ||
/** | ||
* Subtracts the properties of an associative array in a shallow manner. | ||
* Where there are duplicate properties, the properties will be removed | ||
* from the first object. | ||
* | ||
* @param aMap The object from which to subtract properties | ||
* @param bMap The object containing properties to subtract | ||
* @returns {{}} | ||
*/ | ||
static mapSubtract<T>(aMap: { | ||
[key: string]: T; | ||
}, bMap: { | ||
[key: string]: T; | ||
}): { | ||
[key: string]: T; | ||
}; | ||
static mapToArray<T>(map: { | ||
@@ -34,0 +3,0 @@ [key: string]: T; |
var LeafletUtil = (function () { | ||
function LeafletUtil() { | ||
} | ||
/** | ||
* Combine two associative arrays in a shallow manner. Where there are duplicate properties, | ||
* the value in the second object will overwrite the value of the first object | ||
* | ||
* @param aMap The first object | ||
* @param bMap The second object | ||
* @returns {{}} The aggregate of both objects | ||
*/ | ||
LeafletUtil.mergeMaps = function (aMap, bMap) { | ||
var toReturn = {}; | ||
if (null != aMap) { | ||
for (var k in aMap) { | ||
if (aMap.hasOwnProperty(k)) { | ||
toReturn[k] = aMap[k]; | ||
} | ||
} | ||
} | ||
if (null != bMap) { | ||
for (var k in bMap) { | ||
if (bMap.hasOwnProperty(k)) { | ||
toReturn[k] = bMap[k]; | ||
} | ||
} | ||
} | ||
return toReturn; | ||
}; | ||
/** | ||
* Subtracts the properties of an associative array in a shallow manner. | ||
* Where there are duplicate properties, the properties will be removed | ||
* from the first object. | ||
* | ||
* @param aMap The object from which to subtract properties | ||
* @param bMap The object containing properties to subtract | ||
* @returns {{}} | ||
*/ | ||
LeafletUtil.mapSubtract = function (aMap, bMap) { | ||
var toReturn = {}; | ||
if (null != aMap) { | ||
// Copy all of aMap into toReturn | ||
for (var k in aMap) { | ||
if (aMap.hasOwnProperty(k)) { | ||
toReturn[k] = aMap[k]; | ||
} | ||
} | ||
// If there's a bMap, delete all bMap keys from aMap | ||
if (null != bMap) { | ||
for (var k in bMap) { | ||
if (bMap.hasOwnProperty(k)) { | ||
delete toReturn[k]; | ||
} | ||
} | ||
} | ||
} | ||
return toReturn; | ||
}; | ||
LeafletUtil.mapToArray = function (map) { | ||
@@ -60,0 +5,0 @@ var toReturn = []; |
/// <reference types="leaflet" /> | ||
import { OnChanges, OnInit, SimpleChange } from '@angular/core'; | ||
import { DoCheck, KeyValueDiffer, KeyValueDiffers, OnInit } from '@angular/core'; | ||
import * as L from 'leaflet'; | ||
import { LeafletDirective } from '../../core/leaflet.directive'; | ||
export declare class LeafletBaseLayersDirective implements OnChanges, OnInit { | ||
baseLayers: L.Control.LayersObject; | ||
/** | ||
* Baselayers directive | ||
* | ||
* This directive is provided as a convenient way to add baselayers to the map. The input accepts | ||
* a key-value map of layer name -> layer. Mutable changed are detected. On changes, a differ is | ||
* used to determine what changed so that layers are appropriately added or removed. This directive | ||
* will also add the layers control so users can switch between available base layers. | ||
* | ||
* To specify which layer to show as the 'active' baselayer, you will want to add it to the map | ||
* using the layers directive. Otherwise, the plugin will use the last one it sees. | ||
*/ | ||
export declare class LeafletBaseLayersDirective implements DoCheck, OnInit { | ||
private differs; | ||
baseLayersValue: { | ||
[name: string]: L.Layer; | ||
}; | ||
baseLayersDiffer: KeyValueDiffer<string, L.Layer>; | ||
baseLayers: { | ||
[name: string]: L.Layer; | ||
}; | ||
layersControlOptions: L.Control.LayersOptions; | ||
@@ -11,8 +29,6 @@ baseLayer: L.Layer; | ||
private controlLayers; | ||
constructor(leafletDirective: LeafletDirective); | ||
constructor(leafletDirective: LeafletDirective, differs: KeyValueDiffers); | ||
ngOnInit(): void; | ||
ngOnChanges(changes: { | ||
[key: string]: SimpleChange; | ||
}): void; | ||
protected setBaseLayers(newBaseLayers: L.Control.LayersObject, prevBaseLayers: L.Control.LayersObject): void; | ||
ngDoCheck(): void; | ||
protected updateBaseLayers(): void; | ||
/** | ||
@@ -19,0 +35,0 @@ * Check the current base layer and change it to the new one if necessary |
@@ -1,2 +0,2 @@ | ||
import { Directive, Input } from '@angular/core'; | ||
import { Directive, Input, KeyValueDiffers } from '@angular/core'; | ||
import { LeafletUtil } from '../../core/leaflet.util'; | ||
@@ -6,8 +6,32 @@ import { LeafletDirective } from '../../core/leaflet.directive'; | ||
import { LeafletControlLayersWrapper } from '../control/leaflet-control-layers.wrapper'; | ||
import { LeafletControlLayersConfig } from '../control/leaflet-control-layers-config.model'; | ||
/** | ||
* Baselayers directive | ||
* | ||
* This directive is provided as a convenient way to add baselayers to the map. The input accepts | ||
* a key-value map of layer name -> layer. Mutable changed are detected. On changes, a differ is | ||
* used to determine what changed so that layers are appropriately added or removed. This directive | ||
* will also add the layers control so users can switch between available base layers. | ||
* | ||
* To specify which layer to show as the 'active' baselayer, you will want to add it to the map | ||
* using the layers directive. Otherwise, the plugin will use the last one it sees. | ||
*/ | ||
var LeafletBaseLayersDirective = (function () { | ||
function LeafletBaseLayersDirective(leafletDirective) { | ||
function LeafletBaseLayersDirective(leafletDirective, differs) { | ||
this.differs = differs; | ||
this.leafletDirective = new LeafletDirectiveWrapper(leafletDirective); | ||
this.controlLayers = new LeafletControlLayersWrapper(); | ||
this.baseLayersDiffer = this.differs.find({}).create(); | ||
} | ||
Object.defineProperty(LeafletBaseLayersDirective.prototype, "baseLayers", { | ||
get: function () { | ||
return this.baseLayersValue; | ||
}, | ||
// Set/get baseLayers | ||
set: function (v) { | ||
this.baseLayersValue = v; | ||
this.updateBaseLayers(); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
LeafletBaseLayersDirective.prototype.ngOnInit = function () { | ||
@@ -18,19 +42,20 @@ // Init the map | ||
this.controlLayers | ||
.init({ baseLayers: this.baseLayers }, this.layersControlOptions) | ||
.init({}, this.layersControlOptions) | ||
.addTo(this.leafletDirective.getMap()); | ||
// Sync the baselayer (will default to the first layer in the map) | ||
this.syncBaseLayer(); | ||
this.updateBaseLayers(); | ||
}; | ||
LeafletBaseLayersDirective.prototype.ngOnChanges = function (changes) { | ||
// Set the new baseLayers | ||
if (changes['baseLayers']) { | ||
this.setBaseLayers(changes['baseLayers'].currentValue, changes['baseLayers'].previousValue); | ||
LeafletBaseLayersDirective.prototype.ngDoCheck = function () { | ||
this.updateBaseLayers(); | ||
}; | ||
LeafletBaseLayersDirective.prototype.updateBaseLayers = function () { | ||
var map = this.leafletDirective.getMap(); | ||
var layersControl = this.controlLayers.getLayersControl(); | ||
if (null != map && null != layersControl && null != this.baseLayersDiffer) { | ||
var changes = this.baseLayersDiffer.diff(this.baseLayersValue); | ||
var results = this.controlLayers.applyBaseLayerChanges(changes); | ||
if (results.changed()) { | ||
this.syncBaseLayer(); | ||
} | ||
} | ||
}; | ||
LeafletBaseLayersDirective.prototype.setBaseLayers = function (newBaseLayers, prevBaseLayers) { | ||
// Update the layers control | ||
this.controlLayers.setLayersControlConfig(new LeafletControlLayersConfig(newBaseLayers), new LeafletControlLayersConfig(prevBaseLayers)); | ||
// Sync the new baseLayer | ||
this.syncBaseLayer(); | ||
}; | ||
/** | ||
@@ -71,2 +96,3 @@ * Check the current base layer and change it to the new one if necessary | ||
{ type: LeafletDirective, }, | ||
{ type: KeyValueDiffers, }, | ||
]; }; | ||
@@ -73,0 +99,0 @@ LeafletBaseLayersDirective.propDecorators = { |
@@ -1,1 +0,1 @@ | ||
[{"__symbolic":"module","version":3,"metadata":{"LeafletBaseLayersDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletBaseLayers]"}]}],"members":{"baseLayers":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletBaseLayers"]}]}],"layersControlOptions":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControlOptions"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../core/leaflet.directive","name":"LeafletDirective"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngOnChanges":[{"__symbolic":"method"}],"setBaseLayers":[{"__symbolic":"method"}],"syncBaseLayer":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"LeafletBaseLayersDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletBaseLayers]"}]}],"members":{"baseLayers":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletBaseLayers"]}]}],"layersControlOptions":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControlOptions"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../core/leaflet.directive","name":"LeafletDirective"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngOnChanges":[{"__symbolic":"method"}],"setBaseLayers":[{"__symbolic":"method"}],"syncBaseLayer":[{"__symbolic":"method"}]}}}}] | ||
[{"__symbolic":"module","version":3,"metadata":{"LeafletBaseLayersDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletBaseLayers]"}]}],"members":{"baseLayers":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletBaseLayers"]}]}],"layersControlOptions":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControlOptions"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../core/leaflet.directive","name":"LeafletDirective"},{"__symbolic":"reference","module":"@angular/core","name":"KeyValueDiffers"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngDoCheck":[{"__symbolic":"method"}],"updateBaseLayers":[{"__symbolic":"method"}],"syncBaseLayer":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"LeafletBaseLayersDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletBaseLayers]"}]}],"members":{"baseLayers":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletBaseLayers"]}]}],"layersControlOptions":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControlOptions"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../core/leaflet.directive","name":"LeafletDirective"},{"__symbolic":"reference","module":"@angular/core","name":"KeyValueDiffers"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngDoCheck":[{"__symbolic":"method"}],"updateBaseLayers":[{"__symbolic":"method"}],"syncBaseLayer":[{"__symbolic":"method"}]}}}}] |
/// <reference types="leaflet" /> | ||
import * as L from 'leaflet'; | ||
export declare class LeafletControlLayersConfig { | ||
baseLayers: L.Control.LayersObject; | ||
overlays: L.Control.LayersObject; | ||
constructor(baseLayers?: L.Control.LayersObject, overlays?: L.Control.LayersObject); | ||
baseLayers: { | ||
[name: string]: L.Layer; | ||
}; | ||
overlays: { | ||
[name: string]: L.Layer; | ||
}; | ||
} |
var LeafletControlLayersConfig = (function () { | ||
function LeafletControlLayersConfig(baseLayers, overlays) { | ||
this.baseLayers = baseLayers; | ||
this.overlays = overlays; | ||
function LeafletControlLayersConfig() { | ||
this.baseLayers = {}; | ||
this.overlays = {}; | ||
} | ||
@@ -6,0 +6,0 @@ return LeafletControlLayersConfig; |
@@ -1,1 +0,1 @@ | ||
[{"__symbolic":"module","version":3,"metadata":{"LeafletControlLayersConfig":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"select","expression":{"__symbolic":"error","message":"Expression form not supported","line":4,"character":22},"member":"LayersObject"},{"__symbolic":"select","expression":{"__symbolic":"error","message":"Expression form not supported","line":5,"character":20},"member":"LayersObject"}]}]}}}},{"__symbolic":"module","version":1,"metadata":{"LeafletControlLayersConfig":{"__symbolic":"class","members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"select","expression":{"__symbolic":"error","message":"Expression form not supported","line":4,"character":22},"member":"LayersObject"},{"__symbolic":"select","expression":{"__symbolic":"error","message":"Expression form not supported","line":5,"character":20},"member":"LayersObject"}]}]}}}}] | ||
[{"__symbolic":"module","version":3,"metadata":{"LeafletControlLayersConfig":{"__symbolic":"class"}}},{"__symbolic":"module","version":1,"metadata":{"LeafletControlLayersConfig":{"__symbolic":"class"}}}] |
@@ -1,13 +0,28 @@ | ||
import { OnChanges, OnInit, SimpleChange } from '@angular/core'; | ||
/// <reference types="leaflet" /> | ||
import { DoCheck, KeyValueDiffer, KeyValueDiffers, OnInit } from '@angular/core'; | ||
import { LeafletDirective } from '../../core/leaflet.directive'; | ||
export declare class LeafletLayersControlDirective implements OnChanges, OnInit { | ||
layersControlConfig: any; | ||
import { LeafletControlLayersConfig } from './leaflet-control-layers-config.model'; | ||
/** | ||
* Layers Control | ||
* | ||
* This directive is used to configure the layers control. The input accepts an object with two | ||
* key-value maps of layer name -> layer. Mutable changes are detected. On changes, a differ is | ||
* used to determine what changed so that layers are appropriately added or removed. | ||
* | ||
* To specify which layer to show as the 'active' baselayer, you will want to add it to the map | ||
* using the layers directive. Otherwise, the last one it sees will be used. | ||
*/ | ||
export declare class LeafletLayersControlDirective implements DoCheck, OnInit { | ||
private differs; | ||
layersControlConfigValue: LeafletControlLayersConfig; | ||
baseLayersDiffer: KeyValueDiffer<string, L.Layer>; | ||
overlaysDiffer: KeyValueDiffer<string, L.Layer>; | ||
layersControlConfig: LeafletControlLayersConfig; | ||
layersControlOptions: any; | ||
private controlLayers; | ||
private leafletDirective; | ||
constructor(leafletDirective: LeafletDirective); | ||
constructor(leafletDirective: LeafletDirective, differs: KeyValueDiffers); | ||
ngOnInit(): void; | ||
ngOnChanges(changes: { | ||
[key: string]: SimpleChange; | ||
}): void; | ||
ngDoCheck(): void; | ||
protected updateLayers(): void; | ||
} |
@@ -1,10 +0,48 @@ | ||
import { Directive, Input } from '@angular/core'; | ||
import { Directive, Input, KeyValueDiffers } from '@angular/core'; | ||
import { LeafletDirective } from '../../core/leaflet.directive'; | ||
import { LeafletDirectiveWrapper } from '../../core/leaflet.directive.wrapper'; | ||
import { LeafletControlLayersWrapper } from './leaflet-control-layers.wrapper'; | ||
import { LeafletControlLayersConfig } from './leaflet-control-layers-config.model'; | ||
/** | ||
* Layers Control | ||
* | ||
* This directive is used to configure the layers control. The input accepts an object with two | ||
* key-value maps of layer name -> layer. Mutable changes are detected. On changes, a differ is | ||
* used to determine what changed so that layers are appropriately added or removed. | ||
* | ||
* To specify which layer to show as the 'active' baselayer, you will want to add it to the map | ||
* using the layers directive. Otherwise, the last one it sees will be used. | ||
*/ | ||
var LeafletLayersControlDirective = (function () { | ||
function LeafletLayersControlDirective(leafletDirective) { | ||
function LeafletLayersControlDirective(leafletDirective, differs) { | ||
this.differs = differs; | ||
this.leafletDirective = new LeafletDirectiveWrapper(leafletDirective); | ||
this.controlLayers = new LeafletControlLayersWrapper(); | ||
// Generate differs | ||
this.baseLayersDiffer = this.differs.find({}).create(); | ||
this.overlaysDiffer = this.differs.find({}).create(); | ||
} | ||
Object.defineProperty(LeafletLayersControlDirective.prototype, "layersControlConfig", { | ||
get: function () { | ||
return this.layersControlConfigValue; | ||
}, | ||
set: function (v) { | ||
// Validation/init stuff | ||
if (null == v) { | ||
v = new LeafletControlLayersConfig(); | ||
} | ||
if (null == v.baseLayers) { | ||
v.baseLayers = {}; | ||
} | ||
if (null == v.overlays) { | ||
v.overlays = {}; | ||
} | ||
// Store the value | ||
this.layersControlConfigValue = v; | ||
// Update the map | ||
this.updateLayers(); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
LeafletLayersControlDirective.prototype.ngOnInit = function () { | ||
@@ -15,9 +53,23 @@ // Init the map | ||
this.controlLayers | ||
.init(this.layersControlConfig, this.layersControlOptions) | ||
.init({}, this.layersControlOptions) | ||
.addTo(this.leafletDirective.getMap()); | ||
this.updateLayers(); | ||
}; | ||
LeafletLayersControlDirective.prototype.ngOnChanges = function (changes) { | ||
// Set the layers | ||
if (changes['layersControlCfg']) { | ||
this.controlLayers.setLayersControlConfig(changes['layersControlCfg'].currentValue, changes['layersControlCfg'].previousValue); | ||
LeafletLayersControlDirective.prototype.ngDoCheck = function () { | ||
this.updateLayers(); | ||
}; | ||
LeafletLayersControlDirective.prototype.updateLayers = function () { | ||
var map = this.leafletDirective.getMap(); | ||
var layersControl = this.controlLayers.getLayersControl(); | ||
if (null != map && null != layersControl) { | ||
// Run the baselayers differ | ||
if (null != this.baseLayersDiffer && null != this.layersControlConfigValue.baseLayers) { | ||
var changes = this.baseLayersDiffer.diff(this.layersControlConfigValue.baseLayers); | ||
this.controlLayers.applyBaseLayerChanges(changes); | ||
} | ||
// Run the overlays differ | ||
if (null != this.overlaysDiffer && null != this.layersControlConfigValue.overlays) { | ||
var changes = this.overlaysDiffer.diff(this.layersControlConfigValue.overlays); | ||
this.controlLayers.applyOverlayChanges(changes); | ||
} | ||
} | ||
@@ -36,2 +88,3 @@ }; | ||
{ type: LeafletDirective, }, | ||
{ type: KeyValueDiffers, }, | ||
]; }; | ||
@@ -38,0 +91,0 @@ LeafletLayersControlDirective.propDecorators = { |
@@ -1,1 +0,1 @@ | ||
[{"__symbolic":"module","version":3,"metadata":{"LeafletLayersControlDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletLayersControl]"}]}],"members":{"layersControlConfig":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControl"]}]}],"layersControlOptions":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControlOptions"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../core/leaflet.directive","name":"LeafletDirective"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngOnChanges":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"LeafletLayersControlDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletLayersControl]"}]}],"members":{"layersControlConfig":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControl"]}]}],"layersControlOptions":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControlOptions"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../core/leaflet.directive","name":"LeafletDirective"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngOnChanges":[{"__symbolic":"method"}]}}}}] | ||
[{"__symbolic":"module","version":3,"metadata":{"LeafletLayersControlDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletLayersControl]"}]}],"members":{"layersControlConfig":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControl"]}]}],"layersControlOptions":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControlOptions"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../core/leaflet.directive","name":"LeafletDirective"},{"__symbolic":"reference","module":"@angular/core","name":"KeyValueDiffers"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngDoCheck":[{"__symbolic":"method"}],"updateLayers":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"LeafletLayersControlDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletLayersControl]"}]}],"members":{"layersControlConfig":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControl"]}]}],"layersControlOptions":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayersControlOptions"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../../core/leaflet.directive","name":"LeafletDirective"},{"__symbolic":"reference","module":"@angular/core","name":"KeyValueDiffers"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngDoCheck":[{"__symbolic":"method"}],"updateLayers":[{"__symbolic":"method"}]}}}}] |
/// <reference types="leaflet" /> | ||
import { KeyValueChanges } from '@angular/core'; | ||
import * as L from 'leaflet'; | ||
import { LeafletControlLayersConfig } from './leaflet-control-layers-config.model'; | ||
import { LeafletLayersObjectDiff } from './leaflet-layers-object-diff.model'; | ||
import { LeafletControlLayersChanges } from './leaflet-control-layers-changes.model'; | ||
export declare class LeafletControlLayersWrapper { | ||
@@ -9,3 +9,5 @@ protected layersControl: L.Control.Layers; | ||
init(controlConfig: any, controlOptions: any): L.Control.Layers; | ||
setLayersControlConfig(newConfig: LeafletControlLayersConfig, prevConfig: LeafletControlLayersConfig): LeafletLayersObjectDiff; | ||
applyBaseLayerChanges(changes: KeyValueChanges<string, L.Layer>): LeafletControlLayersChanges; | ||
applyOverlayChanges(changes: KeyValueChanges<string, L.Layer>): LeafletControlLayersChanges; | ||
private applyChanges(changes, addFn); | ||
} |
import * as L from 'leaflet'; | ||
import { LeafletUtil } from '../../core/leaflet.util'; | ||
import { LeafletLayersObjectDiff } from './leaflet-layers-object-diff.model'; | ||
import { LeafletControlLayersChanges } from './leaflet-control-layers-changes.model'; | ||
var LeafletControlLayersWrapper = (function () { | ||
@@ -16,34 +15,35 @@ function LeafletControlLayersWrapper() { | ||
}; | ||
LeafletControlLayersWrapper.prototype.setLayersControlConfig = function (newConfig, prevConfig) { | ||
if (null == this.layersControl) { | ||
return new LeafletLayersObjectDiff({}, {}); | ||
LeafletControlLayersWrapper.prototype.applyBaseLayerChanges = function (changes) { | ||
var results = new LeafletControlLayersChanges(); | ||
if (null != this.layersControl) { | ||
results = this.applyChanges(changes, this.layersControl.addBaseLayer); | ||
} | ||
var toRemove; | ||
var baseLayers; | ||
var overlays; | ||
// Figure out which layers need to be removed (prev - new) | ||
toRemove = LeafletUtil.mergeMaps(LeafletUtil.mapSubtract(prevConfig.baseLayers, newConfig.baseLayers), LeafletUtil.mapSubtract(prevConfig.overlays, newConfig.overlays)); | ||
// Figure out which layers need to be added (new - prev) | ||
baseLayers = LeafletUtil.mapSubtract(newConfig.baseLayers, prevConfig.baseLayers); | ||
overlays = LeafletUtil.mapSubtract(newConfig.overlays, prevConfig.overlays); | ||
// Do the actual removal and addition | ||
for (var k in toRemove) { | ||
if (toRemove.hasOwnProperty(k)) { | ||
var l = toRemove[k]; | ||
this.layersControl.removeLayer(l); | ||
} | ||
return results; | ||
}; | ||
LeafletControlLayersWrapper.prototype.applyOverlayChanges = function (changes) { | ||
var results = new LeafletControlLayersChanges(); | ||
if (null != this.layersControl) { | ||
results = this.applyChanges(changes, this.layersControl.addOverlay); | ||
} | ||
for (var k in baseLayers) { | ||
if (baseLayers.hasOwnProperty(k)) { | ||
var l = baseLayers[k]; | ||
this.layersControl.addBaseLayer(l, k); | ||
} | ||
return results; | ||
}; | ||
LeafletControlLayersWrapper.prototype.applyChanges = function (changes, addFn) { | ||
var _this = this; | ||
var results = new LeafletControlLayersChanges(); | ||
if (null != changes) { | ||
changes.forEachChangedItem(function (c) { | ||
_this.layersControl.removeLayer(c.previousValue); | ||
addFn.call(_this.layersControl, c.currentValue, c.key); | ||
results.layersChanged++; | ||
}); | ||
changes.forEachRemovedItem(function (c) { | ||
_this.layersControl.removeLayer(c.currentValue); | ||
results.layersRemoved++; | ||
}); | ||
changes.forEachAddedItem(function (c) { | ||
addFn.call(_this.layersControl, c.currentValue, c.key); | ||
results.layersAdded++; | ||
}); | ||
} | ||
for (var k in overlays) { | ||
if (overlays.hasOwnProperty(k)) { | ||
var l = overlays[k]; | ||
this.layersControl.addOverlay(l, k); | ||
} | ||
} | ||
return new LeafletLayersObjectDiff(toRemove, LeafletUtil.mergeMaps(baseLayers, overlays)); | ||
return results; | ||
}; | ||
@@ -50,0 +50,0 @@ return LeafletControlLayersWrapper; |
@@ -1,1 +0,1 @@ | ||
[{"__symbolic":"module","version":3,"metadata":{"LeafletControlLayersWrapper":{"__symbolic":"class","members":{"getLayersControl":[{"__symbolic":"method"}],"init":[{"__symbolic":"method"}],"setLayersControlConfig":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"LeafletControlLayersWrapper":{"__symbolic":"class","members":{"getLayersControl":[{"__symbolic":"method"}],"init":[{"__symbolic":"method"}],"setLayersControlConfig":[{"__symbolic":"method"}]}}}}] | ||
[{"__symbolic":"module","version":3,"metadata":{"LeafletControlLayersWrapper":{"__symbolic":"class","members":{"getLayersControl":[{"__symbolic":"method"}],"init":[{"__symbolic":"method"}],"applyBaseLayerChanges":[{"__symbolic":"method"}],"applyOverlayChanges":[{"__symbolic":"method"}],"applyChanges":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"LeafletControlLayersWrapper":{"__symbolic":"class","members":{"getLayersControl":[{"__symbolic":"method"}],"init":[{"__symbolic":"method"}],"applyBaseLayerChanges":[{"__symbolic":"method"}],"applyOverlayChanges":[{"__symbolic":"method"}],"applyChanges":[{"__symbolic":"method"}]}}}}] |
/// <reference types="leaflet" /> | ||
import { OnChanges, OnInit, SimpleChange } from '@angular/core'; | ||
import { DoCheck, IterableDiffer, IterableDiffers, OnInit } from '@angular/core'; | ||
import * as L from 'leaflet'; | ||
import { LeafletDirective } from '../core/leaflet.directive'; | ||
export declare class LeafletLayersDirective implements OnChanges, OnInit { | ||
/** | ||
* Layers directive | ||
* | ||
* This directive is used to directly control map layers. As changed are made to the input array of | ||
* layers, the map is synched to the array. As layers are added or removed from the input array, they | ||
* are also added or removed from the map. The input array is treated as immutable. To detect changes, | ||
* you must change the array instance. | ||
* | ||
* Important Note: The input layers array is assumed to be immutable. This means you need to use an | ||
* immutable array implementation or create a new copy of your array when you make changes, otherwise | ||
* this directive won't detect the change. This is by design. It's for performance reasons. Change | ||
* detection of mutable arrays requires diffing the state of the array on every DoCheck cycle, which | ||
* is extremely expensive from a time complexity perspective. | ||
* | ||
*/ | ||
export declare class LeafletLayersDirective implements DoCheck, OnInit { | ||
private differs; | ||
layersValue: L.Layer[]; | ||
layersDiffer: IterableDiffer<L.Layer>; | ||
layers: L.Layer[]; | ||
private leafletDirective; | ||
constructor(leafletDirective: LeafletDirective); | ||
constructor(leafletDirective: LeafletDirective, differs: IterableDiffers); | ||
ngDoCheck(): void; | ||
ngOnInit(): void; | ||
ngOnChanges(changes: { | ||
[key: string]: SimpleChange; | ||
}): void; | ||
/** | ||
* Replace the current layers in the map with the provided array | ||
* @param layers The new complete array of layers for the map | ||
* Update the state of the layers. | ||
* We use an iterable differ to synchronize the map layers with the state of the bound layers array. | ||
* This is important because it allows us to react to changes to the contents of the array as well | ||
* as changes to the actual array instance. | ||
*/ | ||
private setLayers(newLayers, prevLayers); | ||
private updateLayers(); | ||
} |
@@ -1,35 +0,65 @@ | ||
import { Directive, Input } from '@angular/core'; | ||
import { Directive, Input, IterableDiffers } from '@angular/core'; | ||
import { LeafletDirective } from '../core/leaflet.directive'; | ||
import { LeafletDirectiveWrapper } from '../core/leaflet.directive.wrapper'; | ||
import { LeafletLayersUtil } from './leaflet-layers.util'; | ||
/** | ||
* Layers directive | ||
* | ||
* This directive is used to directly control map layers. As changed are made to the input array of | ||
* layers, the map is synched to the array. As layers are added or removed from the input array, they | ||
* are also added or removed from the map. The input array is treated as immutable. To detect changes, | ||
* you must change the array instance. | ||
* | ||
* Important Note: The input layers array is assumed to be immutable. This means you need to use an | ||
* immutable array implementation or create a new copy of your array when you make changes, otherwise | ||
* this directive won't detect the change. This is by design. It's for performance reasons. Change | ||
* detection of mutable arrays requires diffing the state of the array on every DoCheck cycle, which | ||
* is extremely expensive from a time complexity perspective. | ||
* | ||
*/ | ||
var LeafletLayersDirective = (function () { | ||
function LeafletLayersDirective(leafletDirective) { | ||
function LeafletLayersDirective(leafletDirective, differs) { | ||
this.differs = differs; | ||
this.leafletDirective = new LeafletDirectiveWrapper(leafletDirective); | ||
this.layersDiffer = this.differs.find([]).create(); | ||
} | ||
Object.defineProperty(LeafletLayersDirective.prototype, "layers", { | ||
get: function () { | ||
return this.layersValue; | ||
}, | ||
// Set/get the layers | ||
set: function (v) { | ||
this.layersValue = v; | ||
// Now that we have a differ, do an immediate layer update | ||
this.updateLayers(); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
LeafletLayersDirective.prototype.ngDoCheck = function () { | ||
this.updateLayers(); | ||
}; | ||
LeafletLayersDirective.prototype.ngOnInit = function () { | ||
// Init the map | ||
this.leafletDirective.init(); | ||
// The way we've set this up, map isn't set until after the first round of changes has gone through | ||
this.setLayers(this.layers, []); | ||
// Update layers once the map is ready | ||
this.updateLayers(); | ||
}; | ||
LeafletLayersDirective.prototype.ngOnChanges = function (changes) { | ||
// Set the layers | ||
if (changes['layers']) { | ||
var c = changes['layers'].currentValue; | ||
var p = (changes['layers'].isFirstChange()) ? [] : changes['layers'].previousValue; | ||
this.setLayers(c, p); | ||
} | ||
}; | ||
/** | ||
* Replace the current layers in the map with the provided array | ||
* @param layers The new complete array of layers for the map | ||
* Update the state of the layers. | ||
* We use an iterable differ to synchronize the map layers with the state of the bound layers array. | ||
* This is important because it allows us to react to changes to the contents of the array as well | ||
* as changes to the actual array instance. | ||
*/ | ||
LeafletLayersDirective.prototype.setLayers = function (newLayers, prevLayers) { | ||
LeafletLayersDirective.prototype.updateLayers = function () { | ||
var map = this.leafletDirective.getMap(); | ||
if (null != map) { | ||
var diff = LeafletLayersUtil.diffLayers(newLayers, prevLayers); | ||
// Remove the layers | ||
diff.remove.forEach(function (l) { map.removeLayer(l); }); | ||
// Add the new layers | ||
diff.add.forEach(function (l) { map.addLayer(l); }); | ||
if (null != map && null != this.layersDiffer) { | ||
var changes = this.layersDiffer.diff(this.layersValue); | ||
if (null != changes) { | ||
changes.forEachRemovedItem(function (c) { | ||
map.removeLayer(c.item); | ||
}); | ||
changes.forEachAddedItem(function (c) { | ||
map.addLayer(c.item); | ||
}); | ||
} | ||
} | ||
@@ -48,2 +78,3 @@ }; | ||
{ type: LeafletDirective, }, | ||
{ type: IterableDiffers, }, | ||
]; }; | ||
@@ -50,0 +81,0 @@ LeafletLayersDirective.propDecorators = { |
@@ -1,1 +0,1 @@ | ||
[{"__symbolic":"module","version":3,"metadata":{"LeafletLayersDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletLayers]"}]}],"members":{"layers":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayers"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../core/leaflet.directive","name":"LeafletDirective"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngOnChanges":[{"__symbolic":"method"}],"setLayers":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"LeafletLayersDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletLayers]"}]}],"members":{"layers":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayers"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../core/leaflet.directive","name":"LeafletDirective"}]}],"ngOnInit":[{"__symbolic":"method"}],"ngOnChanges":[{"__symbolic":"method"}],"setLayers":[{"__symbolic":"method"}]}}}}] | ||
[{"__symbolic":"module","version":3,"metadata":{"LeafletLayersDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletLayers]"}]}],"members":{"layers":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayers"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../core/leaflet.directive","name":"LeafletDirective"},{"__symbolic":"reference","module":"@angular/core","name":"IterableDiffers"}]}],"ngDoCheck":[{"__symbolic":"method"}],"ngOnInit":[{"__symbolic":"method"}],"updateLayers":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"LeafletLayersDirective":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Directive"},"arguments":[{"selector":"[leafletLayers]"}]}],"members":{"layers":[{"__symbolic":"property","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Input"},"arguments":["leafletLayers"]}]}],"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"reference","module":"../core/leaflet.directive","name":"LeafletDirective"},{"__symbolic":"reference","module":"@angular/core","name":"IterableDiffers"}]}],"ngDoCheck":[{"__symbolic":"method"}],"ngOnInit":[{"__symbolic":"method"}],"updateLayers":[{"__symbolic":"method"}]}}}}] |
@@ -6,3 +6,3 @@ { | ||
"description": "Angular 2 components for Leaflet", | ||
"version": "2.1.5", | ||
"version": "2.2.0", | ||
@@ -9,0 +9,0 @@ "author": "Asymmetrik, Ltd.", |
152
README.md
@@ -17,2 +17,3 @@ # @asymmetrik/angular2-leaflet | ||
- [API](#api) | ||
- [Changelog](#changelog) | ||
- [Contribute](#contribute) | ||
@@ -24,3 +25,3 @@ - [License](#license) | ||
## Install | ||
Install the package and its peer dependencies via npm: | ||
Install the package and its peer dependencies via npm (or yarn): | ||
``` | ||
@@ -40,3 +41,11 @@ npm install leaflet | ||
## Usage | ||
To use this library, there are a handful of setup steps to go through that vary based on your app environment (e.g., Webpack, ngCli, SystemJS, etc.). | ||
Generally, the steps are: | ||
* Install Leaflet, this library, and potentially the Leaflet typings (see above). | ||
* Import the Leaflet stylesheet | ||
* Import the Leaflet module into your Angular project | ||
* Create and configure a map (see docs below and/or demo) | ||
### Import the Leaflet Stylesheet | ||
@@ -58,3 +67,3 @@ For leaflet to work, you need to have the leaflet stylesheets loaded into your application. | ||
#### Webpack | ||
#### Configuring Webpack Style Loaders | ||
If you are using Webpack, you will need to import the css file and have a style-loader configured. | ||
@@ -84,3 +93,3 @@ You can use the demo included in this application as a reference. | ||
#### Angular CLI | ||
#### Adding Styles in Angular CLI | ||
If you are using Angular CLI, you will need to add the Leaflet CSS file to the styles array contained in ```.angular-cli.json``` | ||
@@ -105,4 +114,10 @@ | ||
#### Typescript and Angular 2+ Module Import | ||
In your ```app.module.ts```, add: | ||
### Import Code Dependencies and Module | ||
This project is exported using UMD and it includes typings. | ||
So, you shouldn't have to do anything special to use it if you're building your project in Typescript. | ||
#### Typescript Angular 2+ Module Import | ||
Before you can use the module in your Angular 2+ app, you'll need to import it in your application. | ||
For example, in your ```app.module.ts```, add: | ||
@@ -115,3 +130,3 @@ ```js | ||
... | ||
LeafletModule | ||
LeafletModule.forRoot() | ||
] | ||
@@ -122,22 +137,24 @@ ... | ||
#### Not Using Typescript? | ||
You brave soul. | ||
The code is exported using UMD (bundles are in the ./dist dir) so you should be able to import is using whatever module system/builder you're using, even if you aren't using Typescript. | ||
### Basic Map Setup | ||
To create a map, use the ```leaflet``` attribute directive. | ||
You must specify an initial zoom/center and set of layers either via ```leafletOptions``` or by binding to ```leafletZoom```, ```leafletCenter```, and ```leafletLayers```. | ||
For an example of the basic map setup, you should check out the *Core* demo. | ||
### Create and Configure a Map | ||
Once the dependencies are installed and you have imported the ```LeafletModule```, you're ready to add a map to your page. | ||
To get a basic map to work, you have to: | ||
* Apply the ```leaflet``` attribute directive (see the example below) to an existing DOM element. | ||
* Style the map DOM element with a height. Otherwise, it'll render with a 0 pixel height. | ||
* Provide an initial zoom/center and set of layers either via ```leafletOptions``` or by binding to ```leafletZoom```, ```leafletCenter```, and ```leafletLayers```. | ||
Template: | ||
```html | ||
<div leaflet style="height: 300px;" | ||
<div style="height: 300px;" | ||
leaflet | ||
[leafletOptions]="options"> | ||
</div> | ||
``` | ||
#### leaflet | ||
This is the attribute directive that activates the plugin and creates the map. | ||
#### leafletOptions | ||
Input binding for the initial leaflet map options (see [Leaflet's](http://leafletjs.com) docs). | ||
These options can only be set initially because they are used to create the map. Later changes are ignored.` | ||
Example: | ||
Example leafletOptions object: | ||
```js | ||
@@ -149,10 +166,86 @@ options = { | ||
zoom: 5, | ||
center: L.latLng({ lat: 38.991709, lng: -76.886109 }) | ||
center: L.latLng([ 46.879966, -121.726909 ]) | ||
}; | ||
``` | ||
See the API section below for details regarding how to bind additional options, dynamically bind baselayers, layers, overlays, and layer controls. | ||
Changes to leafletOptions are ignored after they are initially set. | ||
This is because these options are passed into the map constructor, so they couldn't be updated easily regardless. | ||
So, make sure the object exists before the map is created. | ||
You'll want to create the object in ngOnInit or hide the map DOM element with ngIf until you can create the options object. | ||
### Add a Layers Control | ||
The ```leafletLayersControl``` input bindings give you the ability to add the layers control to the map. | ||
The layers control lets the user toggle layers and overlays on and off. | ||
Template: | ||
```html | ||
<div style="height: 300px;" | ||
leaflet | ||
[leafletOptions]="options" | ||
[leafletLayersControl]="layersControl"> | ||
</div> | ||
``` | ||
Example layersControl object: | ||
```js | ||
layersControl = { | ||
baseLayers: { | ||
'Open Street Map': L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' }), | ||
'Open Cycle Map': L.tileLayer('http://{s}.tile.opencyclemap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' }) | ||
}, | ||
overlays: { | ||
'Big Circle': L.circle([ 46.95, -122 ], { radius: 5000 }), | ||
'Big Square': L.polygon([[ 46.8, -121.55 ], [ 46.9, -121.55 ], [ 46.9, -121.7 ], [ 46.8, -121.7 ]]) | ||
} | ||
} | ||
``` | ||
You can add any kind of Leaflet layer you want to the ```overlays``` map. | ||
This includes markers, shapes, geojson, custom layers from other libraries, etc. | ||
### Add Custom Layers (base layers, markers, shapes, etc.) | ||
You can add layers (baselayers, markers, or custom layers) to the map without showing them in the layer control using the ```leafletLayers``` directive. | ||
Template: | ||
```html | ||
<div style="height: 300px;" | ||
leaflet | ||
[leafletOptions]="options" | ||
[leafletLayers]="layers"> | ||
</div> | ||
``` | ||
Layers array: | ||
```js | ||
layers = [ | ||
L.circle([ 46.95, -122 ], { radius: 5000 }), | ||
L.polygon([[ 46.8, -121.85 ], [ 46.92, -121.92 ], [ 46.87, -121.8 ]]), | ||
L.marker([ 46.879966, -121.726909 ]) | ||
]; | ||
``` | ||
### Dynamically Change Map Layers | ||
> **Layer inputs (arrays and maps) are mutable** | ||
> Previous versions of this plugin treated layers arrays and layer control objects as immutable data structures. | ||
> We've changed that behavior. | ||
> Now, mutable changes to the ```leafletLayers```, ```leafletBaseLayers```, and ```leafletLayersControl``` inputs are detected. | ||
The plugin is now using internal ngx iterable and key/value differs to detect and track changes to mutable data structures. | ||
This approach requires a deep compare of the contents of the data structure (which can be slow when the contents are really big). | ||
For immutable data structures, all that is needed is a top-level instance equality check (which is way faster). | ||
This change is backwards compatible and was motivated by feedback and confusion. | ||
While there is a performance impact for some use cases, this approach is more intuitive. | ||
There are at least two good approaches to improving performance when there are a lot of layers bound to the map. | ||
First, you can use the OnPush change detection strategy. There's an example of this in the demo. | ||
Second, you can wrap a large number of layers into a Leaflet layer group, which will reduce the number of layers the plugin actually has to track during diffs. | ||
## API | ||
This section includes more detailed documentation of the functionality of the directives included in this library. | ||
@@ -226,3 +319,3 @@ ### Advanced Map Configuration | ||
#### leafletFitBounds | ||
Input bind a fitBound operation to the map. | ||
Input bind a fitBounds operation to the map. | ||
@@ -268,7 +361,7 @@ ```js | ||
If you use this directive, you can still manually use the ```leafletLayers``` directive, but you will not be able to use the ```leafletLayersControl``` directive. | ||
This directive will interfere with the ```leafletLayersControl``` directive. | ||
However, because it uses ```L.control.Layers``` under the hood, you can still provide options for the layers control. | ||
This directive internally uses the layers control, so if you add both, they'll interfere with each other. | ||
Because it uses ```L.control.Layers``` under the hood, you can still provide options for the layers control. | ||
### leafletLayersControlOptions | ||
#### leafletLayersControlOptions | ||
Input binding for Control.Layers options (see [Leaflet's](http://leafletjs.com) docs). | ||
@@ -326,3 +419,3 @@ These options are passed into the layers control constructor on creation. | ||
### leafletLayersControlOptions | ||
#### leafletLayersControlOptions | ||
Input binding for Control.Layers options (see [Leaflet's](http://leafletjs.com) docs). | ||
@@ -380,3 +473,3 @@ These options are passed into the constructor on creation. | ||
export class MyCustomDirective { | ||
leafletDriective: LeafletDirective; | ||
leafletDirective: LeafletDirective; | ||
@@ -417,3 +510,3 @@ constructor(leafletDirective: LeafletDirective) { | ||
let layer= L.marker([ 46.879966, -121.726909 ], { | ||
let layer = L.marker([ 46.879966, -121.726909 ], { | ||
icon: L.icon({ | ||
@@ -457,2 +550,5 @@ iconSize: [ 25, 41 ], | ||
## Changelog | ||
## Contribute | ||
@@ -459,0 +555,0 @@ PRs accepted. If you are part of Asymmetrik, please make contributions on feature branches off of the ```develop``` branch. If you are outside of Asymmetrik, please fork our repo to make contributions. |
@@ -24,11 +24,6 @@ import { Component } from '@angular/core'; | ||
{ | ||
url: 'http://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png', | ||
maxZoom: 18, | ||
attribution: 'Open Cycle Map' | ||
}, | ||
{ | ||
url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', | ||
maxZoom: 18, | ||
attribution: 'Open Street Map' | ||
}, | ||
} | ||
], | ||
@@ -35,0 +30,0 @@ zoom: 5, |
@@ -91,3 +91,15 @@ import { Component } from '@angular/core'; | ||
layers: L.Layer[]; | ||
layersControl: any; | ||
layersControl = { | ||
baseLayers: { | ||
'Open Street Map': this.LAYER_OSM.layer, | ||
'Open Cycle Map': this.LAYER_OCM.layer | ||
}, | ||
overlays: { | ||
Circle: this.circle.layer, | ||
Square: this.square.layer, | ||
Polygon: this.polygon.layer, | ||
Marker: this.marker.layer, | ||
GeoJSON: this.geoJSON.layer | ||
} | ||
}; | ||
options = { | ||
@@ -114,15 +126,2 @@ zoom: 10, | ||
this.layers = newLayers; | ||
this.layersControl = { | ||
baseLayers: { | ||
'Open Street Map': this.LAYER_OSM.layer, | ||
'Open Cycle Map': this.LAYER_OCM.layer | ||
}, | ||
overlays: { | ||
Circle: this.circle.layer, | ||
Square: this.square.layer, | ||
Polygon: this.polygon.layer, | ||
Marker: this.marker.layer, | ||
GeoJSON: this.geoJSON.layer | ||
} | ||
}; | ||
@@ -129,0 +128,0 @@ return false; |
@@ -11,2 +11,5 @@ import { NgModule } from '@angular/core'; | ||
import { LeafletBaseLayersDemoComponent } from './layers/baselayers-demo.component'; | ||
import { LeafletMarkersDemoComponent } from './layers/markers-demo.component'; | ||
import { LeafletPerformanceDemoComponent } from './performance/performance-demo.component'; | ||
import { LeafletWrapperComponent } from './performance/leaflet-wrapper.component'; | ||
@@ -19,3 +22,3 @@ | ||
LeafletModule | ||
LeafletModule.forRoot() | ||
], | ||
@@ -26,3 +29,6 @@ declarations: [ | ||
LeafletLayersDemoComponent, | ||
LeafletBaseLayersDemoComponent | ||
LeafletBaseLayersDemoComponent, | ||
LeafletMarkersDemoComponent, | ||
LeafletPerformanceDemoComponent, | ||
LeafletWrapperComponent | ||
], | ||
@@ -29,0 +35,0 @@ exports: [ |
@@ -42,2 +42,3 @@ | ||
import '@angular/core'; | ||
import '@angular/forms'; | ||
import '@angular/platform-browser'; | ||
@@ -44,0 +45,0 @@ import '@angular/platform-browser-dynamic'; |
@@ -6,5 +6,2 @@ export { LeafletModule } from './leaflet/leaflet.module'; | ||
export { LeafletControlLayersUtil } from './leaflet/layers/control/leaflet-control-layers.util'; | ||
export { LeafletLayersUtil } from './leaflet/layers/leaflet-layers.util'; | ||
export { LeafletTileLayerDefinition } from './leaflet/layers/leaflet-tile-layer-definition.model'; |
export class LeafletUtil { | ||
/** | ||
* Combine two associative arrays in a shallow manner. Where there are duplicate properties, | ||
* the value in the second object will overwrite the value of the first object | ||
* | ||
* @param aMap The first object | ||
* @param bMap The second object | ||
* @returns {{}} The aggregate of both objects | ||
*/ | ||
static mergeMaps<T> (aMap: { [ key: string ]: T }, bMap: { [ key: string ]: T }): { [ key: string ]: T } { | ||
let toReturn: { [ key: string ]: T } = {}; | ||
if (null != aMap) { | ||
for (let k in aMap) { | ||
if (aMap.hasOwnProperty(k)) { | ||
toReturn[k] = aMap[k]; | ||
} | ||
} | ||
} | ||
if (null != bMap) { | ||
for (let k in bMap) { | ||
if (bMap.hasOwnProperty(k)) { | ||
toReturn[k] = bMap[k]; | ||
} | ||
} | ||
} | ||
return toReturn; | ||
} | ||
/** | ||
* Subtracts the properties of an associative array in a shallow manner. | ||
* Where there are duplicate properties, the properties will be removed | ||
* from the first object. | ||
* | ||
* @param aMap The object from which to subtract properties | ||
* @param bMap The object containing properties to subtract | ||
* @returns {{}} | ||
*/ | ||
static mapSubtract<T>(aMap: { [key: string]: T }, bMap: { [key: string]: T }): { [ key: string ]: T } { | ||
let toReturn: { [ key: string ]: T } = {}; | ||
if (null != aMap) { | ||
// Copy all of aMap into toReturn | ||
for (let k in aMap) { | ||
if (aMap.hasOwnProperty(k)) { | ||
toReturn[k] = aMap[k]; | ||
} | ||
} | ||
// If there's a bMap, delete all bMap keys from aMap | ||
if (null != bMap) { | ||
for (let k in bMap) { | ||
if (bMap.hasOwnProperty(k)) { | ||
delete toReturn[k]; | ||
} | ||
} | ||
} | ||
} | ||
return toReturn; | ||
} | ||
static mapToArray<T>(map: { [ key: string ]: T }): T[] { | ||
@@ -68,0 +4,0 @@ let toReturn: T[] = []; |
@@ -1,2 +0,2 @@ | ||
import { Directive, Input, OnChanges, OnInit, SimpleChange } from '@angular/core'; | ||
import { Directive, DoCheck, Input, KeyValueDiffer, KeyValueDiffers, OnInit } from '@angular/core'; | ||
@@ -9,5 +9,15 @@ import * as L from 'leaflet'; | ||
import { LeafletControlLayersWrapper } from '../control/leaflet-control-layers.wrapper'; | ||
import { LeafletControlLayersConfig } from '../control/leaflet-control-layers-config.model'; | ||
/** | ||
* Baselayers directive | ||
* | ||
* This directive is provided as a convenient way to add baselayers to the map. The input accepts | ||
* a key-value map of layer name -> layer. Mutable changed are detected. On changes, a differ is | ||
* used to determine what changed so that layers are appropriately added or removed. This directive | ||
* will also add the layers control so users can switch between available base layers. | ||
* | ||
* To specify which layer to show as the 'active' baselayer, you will want to add it to the map | ||
* using the layers directive. Otherwise, the plugin will use the last one it sees. | ||
*/ | ||
@Directive({ | ||
@@ -17,7 +27,21 @@ selector: '[leafletBaseLayers]' | ||
export class LeafletBaseLayersDirective | ||
implements OnChanges, OnInit { | ||
implements DoCheck, OnInit { | ||
// Base Layers | ||
@Input('leafletBaseLayers') baseLayers: L.Control.LayersObject; | ||
baseLayersValue: { [name: string]: L.Layer }; | ||
// Base Layers Map Differ | ||
baseLayersDiffer: KeyValueDiffer<string, L.Layer>; | ||
// Set/get baseLayers | ||
@Input('leafletBaseLayers') | ||
set baseLayers(v: { [name: string]: L.Layer }) { | ||
this.baseLayersValue = v; | ||
this.updateBaseLayers(); | ||
} | ||
get baseLayers(): { [name: string]: L.Layer } { | ||
return this.baseLayersValue; | ||
} | ||
// Control Options | ||
@@ -32,5 +56,6 @@ @Input('leafletLayersControlOptions') layersControlOptions: L.Control.LayersOptions; | ||
constructor(leafletDirective: LeafletDirective) { | ||
constructor(leafletDirective: LeafletDirective, private differs: KeyValueDiffers) { | ||
this.leafletDirective = new LeafletDirectiveWrapper(leafletDirective); | ||
this.controlLayers = new LeafletControlLayersWrapper(); | ||
this.baseLayersDiffer = this.differs.find({}).create<string, L.Layer>(); | ||
} | ||
@@ -45,29 +70,27 @@ | ||
this.controlLayers | ||
.init({ baseLayers: this.baseLayers }, this.layersControlOptions) | ||
.init({}, this.layersControlOptions) | ||
.addTo(this.leafletDirective.getMap()); | ||
// Sync the baselayer (will default to the first layer in the map) | ||
this.syncBaseLayer(); | ||
this.updateBaseLayers(); | ||
} | ||
ngOnChanges(changes: { [key: string]: SimpleChange }) { | ||
ngDoCheck() { | ||
this.updateBaseLayers(); | ||
} | ||
// Set the new baseLayers | ||
if (changes['baseLayers']) { | ||
this.setBaseLayers( | ||
changes['baseLayers'].currentValue, | ||
changes['baseLayers'].previousValue); | ||
} | ||
protected updateBaseLayers() { | ||
} | ||
let map = this.leafletDirective.getMap(); | ||
let layersControl = this.controlLayers.getLayersControl(); | ||
protected setBaseLayers(newBaseLayers: L.Control.LayersObject, prevBaseLayers: L.Control.LayersObject) { | ||
if (null != map && null != layersControl && null != this.baseLayersDiffer) { | ||
const changes = this.baseLayersDiffer.diff(this.baseLayersValue); | ||
const results = this.controlLayers.applyBaseLayerChanges(changes); | ||
// Update the layers control | ||
this.controlLayers.setLayersControlConfig( | ||
new LeafletControlLayersConfig(newBaseLayers), | ||
new LeafletControlLayersConfig(prevBaseLayers)); | ||
if (results.changed()) { | ||
this.syncBaseLayer(); | ||
} | ||
} | ||
// Sync the new baseLayer | ||
this.syncBaseLayer(); | ||
} | ||
@@ -74,0 +97,0 @@ |
import * as L from 'leaflet'; | ||
export class LeafletControlLayersConfig { | ||
constructor( | ||
public baseLayers?: L.Control.LayersObject, | ||
public overlays?: L.Control.LayersObject | ||
) { } | ||
baseLayers: { [name: string]: L.Layer } = {}; | ||
overlays: { [name: string]: L.Layer } = {}; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { Directive, Input, OnChanges, OnInit, SimpleChange } from '@angular/core'; | ||
import { Directive, DoCheck, Input, KeyValueDiffer, KeyValueDiffers, OnInit } from '@angular/core'; | ||
@@ -6,4 +6,14 @@ import { LeafletDirective } from '../../core/leaflet.directive'; | ||
import { LeafletControlLayersWrapper } from './leaflet-control-layers.wrapper'; | ||
import { LeafletControlLayersConfig } from './leaflet-control-layers-config.model'; | ||
/** | ||
* Layers Control | ||
* | ||
* This directive is used to configure the layers control. The input accepts an object with two | ||
* key-value maps of layer name -> layer. Mutable changes are detected. On changes, a differ is | ||
* used to determine what changed so that layers are appropriately added or removed. | ||
* | ||
* To specify which layer to show as the 'active' baselayer, you will want to add it to the map | ||
* using the layers directive. Otherwise, the last one it sees will be used. | ||
*/ | ||
@Directive({ | ||
@@ -13,7 +23,29 @@ selector: '[leafletLayersControl]' | ||
export class LeafletLayersControlDirective | ||
implements OnChanges, OnInit { | ||
implements DoCheck, OnInit { | ||
// Control Layers Configuration | ||
@Input('leafletLayersControl') layersControlConfig: any; | ||
layersControlConfigValue: LeafletControlLayersConfig; | ||
baseLayersDiffer: KeyValueDiffer<string, L.Layer>; | ||
overlaysDiffer: KeyValueDiffer<string, L.Layer>; | ||
@Input('leafletLayersControl') | ||
set layersControlConfig(v: LeafletControlLayersConfig) { | ||
// Validation/init stuff | ||
if (null == v) { v = new LeafletControlLayersConfig(); } | ||
if (null == v.baseLayers) { v.baseLayers = {}; } | ||
if (null == v.overlays) { v.overlays = {}; } | ||
// Store the value | ||
this.layersControlConfigValue = v; | ||
// Update the map | ||
this.updateLayers(); | ||
} | ||
get layersControlConfig(): LeafletControlLayersConfig { | ||
return this.layersControlConfigValue; | ||
} | ||
@Input('leafletLayersControlOptions') layersControlOptions: any; | ||
@@ -24,5 +56,10 @@ | ||
constructor(leafletDirective: LeafletDirective) { | ||
constructor(leafletDirective: LeafletDirective, private differs: KeyValueDiffers) { | ||
this.leafletDirective = new LeafletDirectiveWrapper(leafletDirective); | ||
this.controlLayers = new LeafletControlLayersWrapper(); | ||
// Generate differs | ||
this.baseLayersDiffer = this.differs.find({}).create<string, L.Layer>(); | ||
this.overlaysDiffer = this.differs.find({}).create<string, L.Layer>(); | ||
} | ||
@@ -37,14 +74,30 @@ | ||
this.controlLayers | ||
.init(this.layersControlConfig, this.layersControlOptions) | ||
.init({}, this.layersControlOptions) | ||
.addTo(this.leafletDirective.getMap()); | ||
this.updateLayers(); | ||
} | ||
ngOnChanges(changes: { [key: string]: SimpleChange }) { | ||
ngDoCheck() { | ||
this.updateLayers(); | ||
} | ||
// Set the layers | ||
if (changes['layersControlCfg']) { | ||
this.controlLayers.setLayersControlConfig( | ||
changes['layersControlCfg'].currentValue, | ||
changes['layersControlCfg'].previousValue); | ||
protected updateLayers() { | ||
let map = this.leafletDirective.getMap(); | ||
let layersControl = this.controlLayers.getLayersControl(); | ||
if (null != map && null != layersControl) { | ||
// Run the baselayers differ | ||
if (null != this.baseLayersDiffer && null != this.layersControlConfigValue.baseLayers) { | ||
const changes = this.baseLayersDiffer.diff(this.layersControlConfigValue.baseLayers); | ||
this.controlLayers.applyBaseLayerChanges(changes); | ||
} | ||
// Run the overlays differ | ||
if (null != this.overlaysDiffer && null != this.layersControlConfigValue.overlays) { | ||
const changes = this.overlaysDiffer.diff(this.layersControlConfigValue.overlays); | ||
this.controlLayers.applyOverlayChanges(changes); | ||
} | ||
} | ||
@@ -51,0 +104,0 @@ |
@@ -0,6 +1,6 @@ | ||
import { KeyValueChanges } from '@angular/core'; | ||
import * as L from 'leaflet'; | ||
import { LeafletUtil } from '../../core/leaflet.util'; | ||
import { LeafletControlLayersConfig } from './leaflet-control-layers-config.model'; | ||
import { LeafletLayersObjectDiff } from './leaflet-layers-object-diff.model'; | ||
import { LeafletControlLayersChanges } from './leaflet-control-layers-changes.model'; | ||
@@ -26,46 +26,46 @@ export class LeafletControlLayersWrapper { | ||
setLayersControlConfig( newConfig: LeafletControlLayersConfig, prevConfig: LeafletControlLayersConfig): LeafletLayersObjectDiff { | ||
applyBaseLayerChanges(changes: KeyValueChanges<string, L.Layer>): LeafletControlLayersChanges { | ||
let results: LeafletControlLayersChanges = new LeafletControlLayersChanges(); | ||
if (null == this.layersControl) { | ||
return new LeafletLayersObjectDiff({}, {}); | ||
if (null != this.layersControl) { | ||
results = this.applyChanges(changes, this.layersControl.addBaseLayer); | ||
} | ||
let toRemove: L.Control.LayersObject; | ||
let baseLayers: L.Control.LayersObject; | ||
let overlays: L.Control.LayersObject; | ||
return results; | ||
} | ||
// Figure out which layers need to be removed (prev - new) | ||
toRemove = LeafletUtil.mergeMaps( | ||
LeafletUtil.mapSubtract(prevConfig.baseLayers, newConfig.baseLayers), | ||
LeafletUtil.mapSubtract(prevConfig.overlays, newConfig.overlays)); | ||
applyOverlayChanges(changes: KeyValueChanges<string, L.Layer>): LeafletControlLayersChanges { | ||
let results: LeafletControlLayersChanges = new LeafletControlLayersChanges(); | ||
// Figure out which layers need to be added (new - prev) | ||
baseLayers = LeafletUtil.mapSubtract(newConfig.baseLayers, prevConfig.baseLayers); | ||
overlays = LeafletUtil.mapSubtract(newConfig.overlays, prevConfig.overlays); | ||
// Do the actual removal and addition | ||
for (let k in toRemove) { | ||
if (toRemove.hasOwnProperty(k)) { | ||
let l: L.Layer = toRemove[k]; | ||
this.layersControl.removeLayer(l); | ||
} | ||
if (null != this.layersControl) { | ||
results = this.applyChanges(changes, this.layersControl.addOverlay); | ||
} | ||
for (let k in baseLayers) { | ||
if (baseLayers.hasOwnProperty(k)) { | ||
let l: L.Layer = baseLayers[k]; | ||
this.layersControl.addBaseLayer(l, k); | ||
} | ||
} | ||
return results; | ||
} | ||
for (let k in overlays) { | ||
if (overlays.hasOwnProperty(k)) { | ||
let l: L.Layer = overlays[k]; | ||
this.layersControl.addOverlay(l, k); | ||
} | ||
private applyChanges(changes: KeyValueChanges<string, L.Layer>, addFn: (layer: L.Layer, name: string) => void): LeafletControlLayersChanges { | ||
let results: LeafletControlLayersChanges = new LeafletControlLayersChanges(); | ||
if (null != changes) { | ||
changes.forEachChangedItem((c) => { | ||
this.layersControl.removeLayer(c.previousValue); | ||
addFn.call(this.layersControl, c.currentValue, c.key); | ||
results.layersChanged++; | ||
}); | ||
changes.forEachRemovedItem((c) => { | ||
this.layersControl.removeLayer(c.currentValue); | ||
results.layersRemoved++; | ||
}); | ||
changes.forEachAddedItem((c) => { | ||
addFn.call(this.layersControl, c.currentValue, c.key); | ||
results.layersAdded++; | ||
}); | ||
} | ||
return new LeafletLayersObjectDiff(toRemove, LeafletUtil.mergeMaps(baseLayers, overlays)); | ||
return results; | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
import { Directive, Input, OnChanges, OnInit, SimpleChange } from '@angular/core'; | ||
import { Directive, DoCheck, Input, IterableDiffer, IterableDiffers, OnInit } from '@angular/core'; | ||
@@ -6,7 +6,20 @@ import * as L from 'leaflet'; | ||
import { LeafletDirective } from '../core/leaflet.directive'; | ||
import { LeafletDirectiveWrapper } from '../core/leaflet.directive.wrapper'; | ||
import { LeafletLayersUtil } from './leaflet-layers.util'; | ||
/** | ||
* Layers directive | ||
* | ||
* This directive is used to directly control map layers. As changed are made to the input array of | ||
* layers, the map is synched to the array. As layers are added or removed from the input array, they | ||
* are also added or removed from the map. The input array is treated as immutable. To detect changes, | ||
* you must change the array instance. | ||
* | ||
* Important Note: The input layers array is assumed to be immutable. This means you need to use an | ||
* immutable array implementation or create a new copy of your array when you make changes, otherwise | ||
* this directive won't detect the change. This is by design. It's for performance reasons. Change | ||
* detection of mutable arrays requires diffing the state of the array on every DoCheck cycle, which | ||
* is extremely expensive from a time complexity perspective. | ||
* | ||
*/ | ||
@Directive({ | ||
@@ -16,13 +29,34 @@ selector: '[leafletLayers]' | ||
export class LeafletLayersDirective | ||
implements OnChanges, OnInit { | ||
implements DoCheck, OnInit { | ||
// Array of configured layers | ||
@Input('leafletLayers') layers: L.Layer []; | ||
layersValue: L.Layer[]; | ||
// Differ to do change detection on the array | ||
layersDiffer: IterableDiffer<L.Layer>; | ||
// Set/get the layers | ||
@Input('leafletLayers') | ||
set layers(v: L.Layer[]) { | ||
this.layersValue = v; | ||
// Now that we have a differ, do an immediate layer update | ||
this.updateLayers(); | ||
} | ||
get layers(): L.Layer[] { | ||
return this.layersValue; | ||
} | ||
// Wrapper for the leaflet directive (manages the parent directive) | ||
private leafletDirective: LeafletDirectiveWrapper; | ||
constructor(leafletDirective: LeafletDirective) { | ||
constructor(leafletDirective: LeafletDirective, private differs: IterableDiffers) { | ||
this.leafletDirective = new LeafletDirectiveWrapper(leafletDirective); | ||
this.layersDiffer = this.differs.find([]).create<L.Layer>(); | ||
} | ||
ngDoCheck() { | ||
this.updateLayers(); | ||
} | ||
ngOnInit() { | ||
@@ -33,37 +67,29 @@ | ||
// The way we've set this up, map isn't set until after the first round of changes has gone through | ||
this.setLayers(this.layers, []); | ||
// Update layers once the map is ready | ||
this.updateLayers(); | ||
} | ||
ngOnChanges(changes: { [key: string]: SimpleChange }) { | ||
// Set the layers | ||
if (changes['layers']) { | ||
let c = changes['layers'].currentValue; | ||
let p = (changes['layers'].isFirstChange()) ? [] : changes['layers'].previousValue; | ||
this.setLayers(c, p); | ||
} | ||
} | ||
/** | ||
* Replace the current layers in the map with the provided array | ||
* @param layers The new complete array of layers for the map | ||
* Update the state of the layers. | ||
* We use an iterable differ to synchronize the map layers with the state of the bound layers array. | ||
* This is important because it allows us to react to changes to the contents of the array as well | ||
* as changes to the actual array instance. | ||
*/ | ||
private setLayers(newLayers: L.Layer[], prevLayers: L.Layer[]) { | ||
private updateLayers() { | ||
let map = this.leafletDirective.getMap(); | ||
if (null != map) { | ||
if (null != map && null != this.layersDiffer) { | ||
let diff = LeafletLayersUtil.diffLayers(newLayers, prevLayers); | ||
const changes = this.layersDiffer.diff(this.layersValue); | ||
if (null != changes) { | ||
changes.forEachRemovedItem((c) => { | ||
map.removeLayer(c.item); | ||
}); | ||
changes.forEachAddedItem((c) => { | ||
map.addLayer(c.item); | ||
}); | ||
} | ||
// Remove the layers | ||
diff.remove.forEach((l) => { map.removeLayer(l); }); | ||
// Add the new layers | ||
diff.add.forEach((l) => { map.addLayer(l); }); | ||
} | ||
@@ -70,0 +96,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
222843
114
2807
549
1