From 4255de9e3ff6eddc96cddddf5c1f443f9c65e607 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Tue, 12 May 2020 11:43:02 +0200
Subject: [PATCH] maps: factor all geojson layer tracking into a single object
 (#42761)

---
 combo/apps/maps/static/js/combo.map.js       | 85 +++++++++++---------
 combo/apps/maps/templates/maps/map_cell.html |  6 +-
 2 files changed, 52 insertions(+), 39 deletions(-)

diff --git a/combo/apps/maps/static/js/combo.map.js b/combo/apps/maps/static/js/combo.map.js
index bf951445..9851fa4a 100644
--- a/combo/apps/maps/static/js/combo.map.js
+++ b/combo/apps/maps/static/js/combo.map.js
@@ -1,13 +1,33 @@
 $(function() {
     L.Map.include(
       {
-        add_geojson_layer: function(callback, geojson_data) {
+        init_geojson_layers: function(layers) {
+           if (Array.isArray(layers)) { // backward compatibility
+             this.geojson_layers = Object();
+             for (var i=0; i<layers.length; i++) {
+               this.geojson_layers[layers[i].slug] = Object();
+               this.geojson_layers[layers[i].slug].url = layers[i].url;
+             }
+           } else {
+             this.geojson_layers = layers;
+           }
+        },
+
+        load_geojson_layers: function(callback) {
+          var layer_slugs = Object.keys(this.geojson_layers);
+          for (var i=0; i<layer_slugs.length; i++) {
+            var layer = this.geojson_layers[layer_slugs[i]];
+            layer.status = 'loading';
+            this.add_geojson_layer(callback, layer);
+          }
+        },
+
+        add_geojson_layer: function(callback, geojson_layer) {
           var map = this;
           var $map_widget = $(map.getContainer());
           var cell = $map_widget.parents('div.cell')[0];
-          var geojson_url = geojson_data.url;
 
-          $.getJSON(geojson_url).done(
+          $.getJSON(geojson_layer.url).done(
             function(data) {
               var geo_json = L.geoJson(data, {
                   onEachFeature: function(feature, layer) {
@@ -59,28 +79,40 @@ $(function() {
                       return L.marker(latlng, {icon: marker});
                   }
               });
+
+              // track global marker bounds
+              var bounds = geo_json.getBounds();
+              if (bounds.isValid()) {
+                if (!map.bounds) {
+                  map.bounds = L.latLngBounds(bounds);
+                } else {
+                  map.bounds.extend(bounds);
+                }
+              }
+
               if ($map_widget.data('group-markers')) {
-                  if (map.geojson_layers[geojson_data.slug]) {
-                      map.clustered_markers.removeLayer(map.geojson_layers[geojson_data.slug]);
+                  if (geojson_layer.leaflet_layer) {
+                      map.clustered_markers.removeLayer(geojson_layer.leaflet_layer);
                   }
                   map.clustered_markers.addLayer(geo_json);
               } else {
-                  if (map.geojson_layers[geojson_data.slug]) {
-                      map.geojson_layers[geojson_data.slug].remove();
+                  if (geojson_layer.leaflet_layer) {
+                      geojson_layer.leaflet_layer.remove();
                   }
                   geo_json.addTo(map);
               }
-              map.geojson_layers[geojson_data.slug] = geo_json;
+              geojson_layer.leaflet_layer = geo_json;
               if (callback) {
                   callback(geo_json);
               }
-              geojson_data.status = 'loaded';
+              geojson_layer.status = 'loaded';
           }).fail(function(jqxhr, textStatus, error) {
-              geojson_data.status = 'error';
+              geojson_layer.status = 'error';
           }).always(function() {
               map.trigger_markers_if_ready();
           });
         },
+
         trigger_markers_if_ready: function() {
           var map = this;
           var $map_widget = $(map.getContainer());
@@ -153,7 +185,6 @@ $(function() {
             });
             map.addLayer(map.clustered_markers);
         }
-        map.geojson_layers = Object();
         if ($map_widget.data('draggable') === false) {
           map.dragging.disable();
         }
@@ -209,32 +240,14 @@ $(function() {
             ).addTo(map);
         });
         map.bounds = null;
-        map.geojson_layers_loaded = 0;
-        var geojson_layers = window['geojson_'+map_id];
-        if (geojson_layers.length) {
-            $.each(geojson_layers, function(idx, geojson_data) {
-                geojson_data.status = 'loading';
-                map.add_geojson_layer(function(geo_json) {
-                    var bounds = geo_json.getBounds();
-                    if (bounds.isValid()) {
-                        if (!map.bounds) {
-                            map.bounds = L.latLngBounds(bounds);
-                        } else {
-                            map.bounds.extend(bounds);
-                        }
-                        if (init_state == 'fit-markers') {
-                            map.fitBounds(map.bounds);
-                        }
-                    }
-                }, geojson_data);
-                map.geojson_layers_loaded += 1;
-                if (map.geojson_layers_loaded == geojson_layers.length) {
-                    $(cell).trigger('combo:map-ready');
-                }
-            });
-        } else {
-            $(cell).trigger('combo:map-ready');
+        map.init_geojson_layers(window['geojson_'+map_id]);
+        if (init_state == 'fit-markers') {
+          $(cell).on('combo:map-markers-ready', function() {
+            map.fitBounds(map.bounds);
+          });
         }
+        map.load_geojson_layers()
+        $(cell).trigger('combo:map-ready');
     };
     $('div.cell.map').each(function() {
         render_map(this);
diff --git a/combo/apps/maps/templates/maps/map_cell.html b/combo/apps/maps/templates/maps/map_cell.html
index 2328c4a2..ba2288fb 100644
--- a/combo/apps/maps/templates/maps/map_cell.html
+++ b/combo/apps/maps/templates/maps/map_cell.html
@@ -30,12 +30,12 @@
       opacity: {{ layer.opacity|as_json|safe }}
     });
   {% endfor %}
-  var geojson_{{ cell.pk }} = [];
+  var geojson_{{ cell.pk }} = Object();
   {% for layer in geojson_layers %}
-  geojson_{{ cell.pk }}.push({
+  geojson_{{ cell.pk }}["{{ layer.slug }}"] = {
     url: '{{ layer.url }}',
     slug: '{{ layer.slug }}'
-  });
+  };
   {% endfor %}
 </script>
 </div>
-- 
2.26.2

