diff --git a/index.html b/index.html
index 94ea82f..ea700a6 100644
--- a/index.html
+++ b/index.html
@@ -121,6 +121,23 @@
+
+
+
+
Customize layers
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/js/Map.js b/js/Map.js
index d1930aa..e20ce9f 100644
--- a/js/Map.js
+++ b/js/Map.js
@@ -120,6 +120,8 @@ BR.Map = {
L.control.scale().addTo(map);
+ new BR.Layers().init(map, layersControl, baseLayers, overlays);
+
// expose map instance for console debugging
BR.debug = BR.debug || {};
BR.debug.map = map;
diff --git a/js/control/Layers.js b/js/control/Layers.js
new file mode 100644
index 0000000..359df0b
--- /dev/null
+++ b/js/control/Layers.js
@@ -0,0 +1,134 @@
+BR.Layers = L.Class.extend({
+
+ _loadLayers: function() {
+ this._customLayers = {};
+
+ if (BR.Util.localStorageAvailable()) {
+ var layers = JSON.parse(localStorage.getItem("map/customLayers"));
+ for (a in layers) {
+ this._addLayer(a, layers[a].layer, layers[a].isOverlay);
+ }
+ }
+ },
+
+ _loadTable: function() {
+ var layersData = [];
+ for (layer in this._customLayers) {
+ layersData.push([layer, this._customLayers[layer].layer._url, this._customLayers[layer].isOverlay ? "Overlay" : "Layer"]);
+ }
+ if (this._layersTable != null) {
+ this._layersTable.destroy();
+ }
+
+ this._layersTable = $('#custom_layers_table').DataTable({
+ data: layersData,
+ info: false,
+ searching: false,
+ paging: false,
+ columns: [
+ { title: "Name" },
+ { title: "URL" },
+ { title: "Type" }
+ ]
+ });
+ },
+
+ init: function(map, layersControl, baseLayers, overlays) {
+ this._layersControl = layersControl;
+ this._map = map;
+ this._layers = {}
+ for (var l in overlays)
+ this._layers[l] = [overlays[l], true];
+ for (var l in baseLayers)
+ this._layers[l] = [baseLayers[l], false];
+
+ L.DomUtil.get('custom_layers_add_base').onclick = L.bind(this._addBaseLayer, this);
+ L.DomUtil.get('custom_layers_add_overlay').onclick = L.bind(this._addOverlay, this);
+ L.DomUtil.get('custom_layers_remove').onclick = L.bind(this._remove, this);
+
+ this._loadLayers();
+ this._loadTable();
+
+ var table = this._layersTable;
+ $('#custom_layers_table tbody').on( 'click', 'tr', function () {
+ if ( $(this).hasClass('selected') ) {
+ $(this).removeClass('selected');
+ } else {
+ table.$('tr.selected').removeClass('selected');
+ $(this).addClass('selected');
+ }
+ });
+
+ addLayer = L.easyButton(
+ 'fa-plus-square',
+ function () {
+ $('#custom_layers').modal();
+ },
+ 'Add or remove custom layers',
+ {
+ position: 'topright'
+ }
+ ).addTo(map);
+ },
+
+ _remove: function(evt) {
+ var row = this._layersTable.row('.selected').data();
+ if (row != null) {
+ var name = row[0];
+ this._layersControl.removeLayer(this._customLayers[name].layer);
+ this._map.removeLayer(this._customLayers[name].layer);
+ delete this._customLayers[name];
+ this._layersTable.row('.selected').remove().draw( false );
+ this._sync();
+ }
+ },
+
+ _addFromInput: function(isOverlay) {
+ var layer_name = L.DomUtil.get('layer_name').value;
+ var layer_url = L.DomUtil.get('layer_url').value;
+ if (layer_name.length > 0 && layer_url.length > 0)
+ this._addLayer(layer_name, layer_url, isOverlay);
+ },
+
+ _addBaseLayer: function(evt) {
+ this._addFromInput(false);
+ },
+ _addOverlay: function(evt) {
+ this._addFromInput(true);
+ },
+
+ _addLayer: function(layerName, layerUrl, isOverlay) {
+ if (layerName in this._layers)
+ return
+
+ if (layerName in this._customLayers)
+ return
+
+ try {
+ var layer = L.tileLayer(layerUrl);
+
+ this._customLayers[layerName] = {layer: layer, isOverlay: isOverlay};
+
+ if (isOverlay) {
+ this._layersControl.addOverlay(layer, layerName);
+ } else {
+ this._layersControl.addBaseLayer(layer, layerName);
+ }
+ this._loadTable();
+ this._sync();
+ return layer;
+ } catch (e) {
+ console.warn("Oops:", e);
+ return
+ }
+ },
+
+ _sync: function() {
+ if (BR.Util.localStorageAvailable()) {
+ localStorage.setItem("map/customLayers", JSON.stringify(this._customLayers, function(k, v) {
+ // dont write Leaflet.Layer in localStorage; simply keep the URL
+ return v._url || v;
+ }));
+ }
+ }
+});
\ No newline at end of file