[Pkg-javascript-commits] [leaflet-markercluster] 100/219: Moved files to sub-folder and added explanation text and page formatting

Jonas Smedegaard dr at jones.dk
Sat May 7 09:39:20 UTC 2016


This is an automated email from the git hooks/post-receive script.

js pushed a commit to branch master
in repository leaflet-markercluster.

commit 3c3a9aad96855442ffde304ca7061f57d3a0213e
Author: ghybs <ghybs1 at gmail.com>
Date:   Thu Sep 24 12:06:29 2015 +0400

    Moved files to sub-folder and added explanation text and page formatting
---
 clustertest.js                                     | 289 ------------
 .../MarkerCluster.Default.css                      |   0
 .../MarkerCluster.css                              |   0
 hierarchical-tree-of-groups/clustertest.js         | 435 +++++++++++++++++
 .../convert.html                                   |   0
 .../data_usa.js                                    |   6 +-
 .../data_usa_raw.js                                |   4 +-
 .../flags/19px-Flag_of_Idaho.svg.png               | Bin 0 -> 405 bytes
 .../flags/19px-Flag_of_Rhode_Island.svg.png        | Bin 0 -> 539 bytes
 .../flags/20px-Flag_of_Connecticut.svg.png         | Bin 0 -> 631 bytes
 .../flags/21px-Flag_of_Alaska.svg.png              | Bin 0 -> 280 bytes
 .../flags/21px-Flag_of_North_Dakota.svg.png        | Bin 0 -> 693 bytes
 .../flags/22px-Flag_of_Iowa.svg.png                | Bin 0 -> 611 bytes
 .../flags/22px-Flag_of_Virginia.svg.png            | Bin 0 -> 516 bytes
 .../flags/22px-Flag_of_Wyoming.svg.png             | Bin 0 -> 444 bytes
 .../flags/23px-Flag_of_Alabama.svg.png             | Bin 0 -> 636 bytes
 .../flags/23px-Flag_of_Arizona.svg.png             | Bin 0 -> 674 bytes
 .../flags/23px-Flag_of_Arkansas.svg.png            | Bin 0 -> 745 bytes
 .../flags/23px-Flag_of_California.svg.png          | Bin 0 -> 578 bytes
 .../flags/23px-Flag_of_Colorado.svg.png            | Bin 0 -> 416 bytes
 .../flags/23px-Flag_of_Delaware.svg.png            | Bin 0 -> 575 bytes
 .../flags/23px-Flag_of_Florida.svg.png             | Bin 0 -> 800 bytes
 .../23px-Flag_of_Georgia_(U.S._state).svg.png      | Bin 0 -> 411 bytes
 .../flags/23px-Flag_of_Hawaii.svg.png              | Bin 0 -> 364 bytes
 .../flags/23px-Flag_of_Illinois.svg.png            | Bin 0 -> 534 bytes
 .../flags/23px-Flag_of_Indiana.svg.png             | Bin 0 -> 582 bytes
 .../flags/23px-Flag_of_Kansas.svg.png              | Bin 0 -> 482 bytes
 .../flags/23px-Flag_of_Kentucky.svg.png            | Bin 0 -> 413 bytes
 .../flags/23px-Flag_of_Louisiana.svg.png           | Bin 0 -> 546 bytes
 .../flags/23px-Flag_of_Maine.svg.png               | Bin 0 -> 397 bytes
 .../flags/23px-Flag_of_Maryland.svg.png            | Bin 0 -> 996 bytes
 .../flags/23px-Flag_of_Massachusetts.svg.png       | Bin 0 -> 305 bytes
 .../flags/23px-Flag_of_Michigan.svg.png            | Bin 0 -> 618 bytes
 .../flags/23px-Flag_of_Minnesota.svg.png           | Bin 0 -> 542 bytes
 .../flags/23px-Flag_of_Mississippi.svg.png         | Bin 0 -> 436 bytes
 .../flags/23px-Flag_of_Missouri.svg.png            | Bin 0 -> 449 bytes
 .../flags/23px-Flag_of_Montana.svg.png             | Bin 0 -> 518 bytes
 .../flags/23px-Flag_of_Nebraska.svg.png            | Bin 0 -> 605 bytes
 .../flags/23px-Flag_of_Nevada.svg.png              | Bin 0 -> 357 bytes
 .../flags/23px-Flag_of_New_Hampshire.svg.png       | Bin 0 -> 602 bytes
 .../flags/23px-Flag_of_New_Jersey.svg.png          | Bin 0 -> 367 bytes
 .../flags/23px-Flag_of_New_Mexico.svg.png          | Bin 0 -> 261 bytes
 .../flags/23px-Flag_of_New_York.svg.png            | Bin 0 -> 487 bytes
 .../flags/23px-Flag_of_North_Carolina.svg.png      | Bin 0 -> 465 bytes
 .../flags/23px-Flag_of_Ohio.svg.png                | Bin 0 -> 922 bytes
 .../flags/23px-Flag_of_Oklahoma.svg.png            | Bin 0 -> 506 bytes
 .../flags/23px-Flag_of_Oregon.svg.png              | Bin 0 -> 555 bytes
 .../flags/23px-Flag_of_Pennsylvania.svg.png        | Bin 0 -> 569 bytes
 .../flags/23px-Flag_of_South_Carolina.svg.png      | Bin 0 -> 472 bytes
 .../flags/23px-Flag_of_South_Dakota.svg.png        | Bin 0 -> 552 bytes
 .../flags/23px-Flag_of_Tennessee.svg.png           | Bin 0 -> 406 bytes
 .../flags/23px-Flag_of_Texas.svg.png               | Bin 0 -> 247 bytes
 .../flags/23px-Flag_of_Utah.svg.png                | Bin 0 -> 540 bytes
 .../flags/23px-Flag_of_Vermont.svg.png             | Bin 0 -> 353 bytes
 .../flags/23px-Flag_of_Washington.svg.png          | Bin 0 -> 493 bytes
 .../flags/23px-Flag_of_WashingtonDC.svg.png        | Bin 0 -> 215 bytes
 .../flags/23px-Flag_of_West_Virginia.svg.png       | Bin 0 -> 450 bytes
 .../flags/23px-Flag_of_Wisconsin.svg.png           | Bin 0 -> 507 bytes
 .../flags/23px-Flag_of_the_United_States.svg.png   | Bin 0 -> 401 bytes
 .../images}/layers-2x.png                          | Bin
 .../images}/layers.png                             | Bin
 .../images}/marker-icon-2x.png                     | Bin
 .../images}/marker-icon.png                        | Bin
 .../images}/marker-shadow.png                      | Bin
 hierarchical-tree-of-groups/index.html             | 523 +++++++++++++++++++++
 .../leaflet-src.js                                 |   0
 .../leaflet.css                                    |   0
 .../leaflet.label-src.js                           |   0
 .../leaflet.label.css                              |   0
 .../leaflet.markercluster-src-hierarchicalTree.js  |  96 ++--
 .../papaparse.js                                   |   0
 index.html                                         | 185 --------
 72 files changed, 992 insertions(+), 546 deletions(-)

diff --git a/clustertest.js b/clustertest.js
deleted file mode 100644
index b98403e..0000000
--- a/clustertest.js
+++ /dev/null
@@ -1,289 +0,0 @@
-/**
- * Created by boris on 9/14/15.
- */
-
-// See also https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#hsl%28%29
-// and https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#hsla%28%29
-function getRandomHue2() {
-    return Math.floor(Math.random() * 360);
-}
-
-// Try to get a minimum of saturation (colorness) (0% is grey)
-function getRandomSaturation2() {
-    return Math.round(30 + Math.random() * 70);
-}
-
-// Try to stay within average lightness (0% is black, 100% is white)
-function getRandomLightness2() {
-    return Math.round(40 + Math.random() * 40);
-}
-
-function generateHSL(hue) {
-    if (typeof hue === "undefined") {
-        hue = getRandomHue2();
-    }
-
-    return {
-        h: hue,
-        s: getRandomSaturation2(),
-        l: getRandomLightness2()
-    }
-}
-
-function getHSL(hsl) {
-    return "hsl(" + hsl.h + "," + hsl.s + "%," + hsl.l + "%)";
-}
-
-function getHSLA(hsl, alpha) {
-    alpha = alpha || 1;
-
-    return "hsla(" + hsl.h + "," + hsl.s + "%," + hsl.l + "%," + alpha + ")";
-}
-
-var map = L.map(
-    'map',
-    {
-        center: [39.5, -98.35],
-        zoom: 4,
-        layers: [
-            new L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png')
-        ]
-    }
-);
-
-// USA map
-var i,
-    j,
-    k,
-    hue = 1,
-    hsl = {},
-    hsla = "",
-    USA = DATA.USA,
-    link = USA.states,
-    // USA keys: lat,lng,states
-    countryGroup = L.markerClusterGroup({
-        center: L.latLng(USA.lat, USA.lng),
-        data: {
-            name: "USA"
-        },
-        iconCreateFunction: function (cluster) {
-            var alienClustersCount = cluster.getAlienClustersCount(),
-                options = cluster._originalGroup.options,
-                isSingleton = cluster.isSingletonCluster();
-
-            return new L.DivIcon({
-                html: '<div style="background-color: ' + "yellow" + '; border-color: ' +
-                (isSingleton ? "black" : "red") + ';">' + alienClustersCount +
-                (isSingleton ? '<span>' + options.data.name + '</span>' : "") + '</div>',
-                className: isSingleton ? "marker-state" : 'marker-counties-cluster',
-                iconSize: null
-            });
-        },
-        setLabel: function (cluster) {
-            var isSingleton = cluster.isSingletonCluster(),
-                options = cluster._originalGroup.options;
-
-            cluster.bindLabel(
-                isSingleton ?
-                    "States in " + options.data.name +
-                    "<br />Total included cities: " + cluster.getChildCount() +
-                    "<br />Lat: " + cluster._latlng.lat +
-                    "<br />Lng: " + cluster._latlng.lng :
-
-                    "States in part of " + options.data.name +
-                    "<br />Total included cities: " + cluster.getChildCount(),
-                {
-                    offset: [25, -15]
-                }
-            );
-        }
-    }).addTo(map),
-    stateCodes = Object.keys(link),
-    stateGroup,
-    stateData,
-    county,
-    countiesTotal = 0,
-    countyGroup,
-    city,
-    citiesTotal = 0;
-
-for(i = 0; i < stateCodes.length; i += 1) {
-    if (true || stateCodes[i] === "HI" || stateCodes[i] === "DE" || stateCodes[i] === "DC") {
-        // stateData keys: stateName,lat,lng,stateCounties
-        stateData = link[stateCodes[i]];
-        hue = getRandomHue2();
-        hsl = {h: hue, s: 100, l: 50};
-        stateGroup = L.markerClusterGroup({
-            stateData: L.extend(L.extend({}, stateData), {stateCode: stateCodes[i]}),
-            stateHue: hue,
-            stateHSL: getHSL(hsl),
-            stateHSLA: getHSLA(hsl, 0.6),
-            center: L.latLng(stateData.lat, stateData.lng),
-            iconCreateFunction: function (cluster) {
-                var childCount = cluster.getChildCount(),
-                    alienClustersCount = cluster.getAlienClustersCount(),
-                    options = cluster._originalGroup.options,
-                    isSingleton = cluster.isSingletonCluster();
-
-                return new L.DivIcon({
-                    html: '<div style="background-color: ' + options.stateHSL + '; border-color: ' +
-                            (isSingleton ? "black" : options.stateHSLA) + ';">' + alienClustersCount +
-                            (isSingleton ? '<span>' + options.stateData.stateName + '</span>' : "") + '</div>',
-                    className: isSingleton ? "marker-state" : 'marker-counties-cluster',
-                    iconSize: null
-                });
-            },
-            setLabel: function (cluster) {
-                var isSingleton = cluster.isSingletonCluster(),
-                    options = cluster._originalGroup.options,
-                    childCount = cluster.getChildCount();
-
-                cluster.bindLabel(
-                    isSingleton ?
-                        "Total counties in " + options.stateData.stateName + " State" +
-                        "<br />State Code: " + options.stateData.stateCode +
-                        "<br />Lat: " + options.stateData.lat +
-                        "<br />Lng: " + options.stateData.lng +
-                        "<br />Total included cities: " + childCount :
-
-                        "Counties in part of " + options.stateData.stateName +
-                        "<br />Total included cities: " + childCount,
-                    {
-                        offset: [25, -15]
-                    }
-                );
-            }
-        }).addTo(map);
-
-        for(j = 0; j < stateData.stateCounties.length; j += 1) {
-            county = stateData.stateCounties[j];
-            hsl = generateHSL(hue);
-            hsla = getHSLA(hsl, 0.6);
-
-            // Special case of county "Aleutians West" (code 16) in Alaska, coordinates [51.959447, 178.338813]
-            // Wrap it back to negative longitude, so that it is displayed closer to the rest of the State.
-            if (county.code === 16) {
-                county.lng -= 360;
-            }
-
-            countyGroup = L.markerClusterGroup({
-                // countyData keys: name,type,code,lat,lng
-                countyData: L.extend({}, county),
-                countyHSLA: hsla,
-                countyHSL: getHSL(hsl),
-                center: L.latLng(county.lat, county.lng),
-                //forcedSingletonClusterAtZoom: 13,
-                iconCreateFunction: function (cluster) {
-                    var childCount = cluster.getChildCount(),
-                        options = cluster._originalGroup.options,
-                        isSingleton = cluster.isSingletonCluster();
-
-                    return new L.DivIcon({
-                        html: '<div style="background-color: ' + options.countyHSL + '; border-color: ' +
-                                (isSingleton ? "black" : options.countyHSLA) + ';">' + childCount +
-                                (isSingleton ? '<span>' + options.countyData.name /*+ " " + options.countyData.type*/ + '</span>' : "") + '</div>',
-                        className: isSingleton ? "marker-county" : 'marker-cities-cluster',
-                        iconSize: null
-                    });
-                },
-                setLabel: function (cluster) {
-                    var isSingleton = cluster.isSingletonCluster(),
-                        options = cluster._originalGroup.options;
-
-                    cluster.bindLabel(
-                        isSingleton ?
-                        "Total cities in " + options.countyData.name + " " + options.countyData.type +
-                        "<br />County Code: " + options.countyData.code +
-                        "<br />Lat: " + options.countyData.lat +
-                        "<br />Lng: " + options.countyData.lng :
-                        "Cities in part of " + options.countyData.name + " " + options.countyData.type,
-                        {
-                            offset: [20, -15]
-                        }
-                    );
-                }
-            });
-
-            for(k = 0; k < county.cities.length; k += 1) {
-                city = county.cities[k];
-
-                // Special case of city (GNIS 2418783) in Alaska, coordinates [52.880248, 173.256076]
-                // Wrap it back to negative longitude, so that it is displayed closer to the rest of the State.
-                if (city.GNIS === 2418783) {
-                    city.lng -= 360;
-                }
-
-                // city keys: code,GNIS,name,type,lat,lng
-                L.marker([city.lat, city.lng], {
-                    icon: new L.DivIcon({
-                        html: '<div style="background-color: ' + hsla + ';"><span>' + city.name + '</span></div>',
-                        className: 'marker-city',
-                        iconSize: null
-                    })
-                }).
-                    addTo(countyGroup).
-                    bindPopup(
-                    "City: " + city.name +
-                    "<br />Code: " + city.code +
-                    "<br />GNIS: " + city.GNIS +
-                    "<br />Type: " + city.type +
-                    "<br />From County: " + county.name +
-                    "<br />Latitude: " + city.lat +
-                    "<br />Longitude: " + city.lng
-                );
-                city = null;
-                citiesTotal += 1;
-            }
-
-            // In case a county has only 1 city, force a cluster so that the user sees the county icon at some point.
-            if (k === 1) {
-                countyGroup.options.forcedSingletonClusterAtZoom = 17;
-            }
-
-            countyGroup.addTo(map);
-            map.removeLayer(countyGroup);
-
-            //console.log("Adding county: " + county.name + " with cities: " + countyGroup._topClusterLevel.getChildCount());
-
-            if (countyGroup._topClusterLevel.getChildCount()) {
-                if (stateData.stateCounties.length === 1) {
-                    stateGroup.options.forcedSingletonClusterAtZoom = countyGroup.getSingletonCluster()._zoom + 1;
-                }
-                stateGroup.addLayer(countyGroup);
-            }
-            //stateGroup.addLayer(countyGroup);
-            countyGroup = null;
-            county = null;
-            hsl = null;
-            hsla = null;
-            county = null;
-            countiesTotal += 1;
-        }
-
-        // Clean stateGroup.
-        map.removeLayer(stateGroup);
-
-        // Add stateGroup to countryGroup.
-        countryGroup.addLayer(stateGroup);
-        stateGroup = null;
-        stateData = null;
-    }
-
-}
-
-// Since we have forced single marker clusters, remove them when not needed.
-countryGroup.cleanSingleMarkerClusters();
-
-// If a group "center" latlng position is specified, use it to display the singleton cluster, instead of the weighted latlng.
-countryGroup.replaceSingletonLatLng();
-
-// Bind labels if specified.
-countryGroup.setIconLabels();
-
-// Hack to display layers that are in the viewport.
-// Needed because we have disabled the display in addLayer().
-map.removeLayer(countryGroup);
-countryGroup.addTo(map);
-
-console.log("Total Cities: " + countryGroup._topClusterLevel.getChildCount() + " / " + citiesTotal);
-console.log("Total Counties: " + countryGroup._topClusterLevel.getChildCount() + " / " + countiesTotal);
diff --git a/MarkerCluster.Default.css b/hierarchical-tree-of-groups/MarkerCluster.Default.css
similarity index 100%
rename from MarkerCluster.Default.css
rename to hierarchical-tree-of-groups/MarkerCluster.Default.css
diff --git a/MarkerCluster.css b/hierarchical-tree-of-groups/MarkerCluster.css
similarity index 100%
rename from MarkerCluster.css
rename to hierarchical-tree-of-groups/MarkerCluster.css
diff --git a/hierarchical-tree-of-groups/clustertest.js b/hierarchical-tree-of-groups/clustertest.js
new file mode 100644
index 0000000..1974d96
--- /dev/null
+++ b/hierarchical-tree-of-groups/clustertest.js
@@ -0,0 +1,435 @@
+/**
+ * Created by boris on 9/14/15.
+ */
+
+// See also https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#hsl%28%29
+// and https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#hsla%28%29
+function getRandomHue2() {
+    return Math.floor(Math.random() * 360);
+}
+
+// Try to get a minimum of saturation (colorness) (0% is grey)
+function getRandomSaturation2() {
+    return Math.round(30 + Math.random() * 70);
+}
+
+// Try to stay within average lightness (0% is black, 100% is white)
+function getRandomLightness2() {
+    return Math.round(40 + Math.random() * 40);
+}
+
+function generateHSL(hue) {
+    if (typeof hue === "undefined") {
+        hue = getRandomHue2();
+    }
+
+    return {
+        h: hue,
+        s: getRandomSaturation2(),
+        l: getRandomLightness2()
+    }
+}
+
+function getHSL(hsl) {
+    return "hsl(" + hsl.h + "," + hsl.s + "%," + hsl.l + "%)";
+}
+
+function getHSLA(hsl, alpha) {
+    alpha = alpha || 1;
+
+    return "hsla(" + hsl.h + "," + hsl.s + "%," + hsl.l + "%," + alpha + ")";
+}
+
+// Adapted from: http://stackoverflow.com/questions/10787782/full-height-of-a-html-element-div-including-border-padding-and-margin
+function getOuterHeight(elmID) {
+    var elmHeight, elmMargin, elmPadding, elm = document.getElementById(elmID);
+    if(document.all) {// IE
+        elmHeight = parseInt(elm.currentStyle.height, 10);
+        elmMargin = parseInt(elm.currentStyle.marginTop, 10) + parseInt(elm.currentStyle.marginBottom, 10);
+        elmPadding = parseInt(elm.currentStyle.paddingTop, 10) + parseInt(elm.currentStyle.paddingBottom, 10);
+    } else {// Mozilla
+        elmHeight = parseInt(document.defaultView.getComputedStyle(elm, '').getPropertyValue('height'), 10);
+        elmMargin = parseInt(document.defaultView.getComputedStyle(elm, '').getPropertyValue('margin-top'), 10) +
+            parseInt(document.defaultView.getComputedStyle(elm, '').getPropertyValue('margin-bottom'), 10);
+        elmPadding = parseInt(document.defaultView.getComputedStyle(elm, '').getPropertyValue('padding-top'), 10) +
+            parseInt(document.defaultView.getComputedStyle(elm, '').getPropertyValue('padding-bottom'), 10);
+    }
+    return (elmHeight + elmMargin + elmPadding);
+}
+
+var map,
+    zoomLevel = document.getElementById("zoomLevel"),
+    form = document.getElementById("options"),
+    forceSingletonPosition,
+    addCities,
+    wrapCoordinates,
+    countryGroup;
+
+form.addEventListener("submit", function (evt) {
+    forceSingletonPosition = document.getElementById("forceSingletonPosition").checked;
+    addCities = document.getElementById("addCities").checked;
+    wrapCoordinates = document.getElementById("wrapCoordinates").checked;
+
+    showTopGroup();
+
+    evt.preventDefault();
+    return false;
+});
+
+document.addEventListener("DOMContentLoaded", function () {
+
+    // Resize the map container.
+    var h1 = getOuterHeight("pageTitle"),
+        h2 = getOuterHeight("options"),
+        h3 = getOuterHeight("zoomInfo"),
+        h0 = document.getElementById("leftPane").offsetHeight;
+
+    document.getElementById("map").style.height = (h0 - h1 - h2 - h3) + "px";
+
+    // Initialize the map.
+    map = L.map(
+            'map',
+            {
+                center: [39.5, -98.35],
+                zoom: 4,
+                layers: [
+                    new L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
+                        attribution: '© <a href="http://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap contributors</a>'
+                    })
+                ]
+            }
+        );
+
+    // Prepare the zoom information.
+    map.on("zoomend", function () {
+        zoomLevel.innerHTML = map.getZoom();
+    });
+
+    // Prepare the links to set map view.
+    var mapSetViewLinks = document.getElementsByClassName("mapSetView"),
+        mapSetViewLink;
+
+    for(var i = 0; i < mapSetViewLinks.length; i += 1) {
+        mapSetViewLink = mapSetViewLinks[i];
+        mapSetViewLink.addEventListener("click", function (evt) {
+            var data = evt.target.dataset,
+                lat = parseFloat(data.lat),
+                lng = parseFloat(data.lng),
+                zoom = (typeof data.zoom !== "undefined") ?
+                    parseInt(data.zoom, 10) : map.getZoom();
+
+            map.setView([lat, lng], zoom);
+
+            evt.preventDefault();
+            return false;
+        });
+    }
+
+    // Fill the map with data.
+    document.getElementById("submit").click();
+});
+
+function showTopGroup() {
+    // Reset any pre-existing group.
+    if (countryGroup && countryGroup instanceof L.MarkerClusterGroup && countryGroup._map) {
+        map.removeLayer(countryGroup);
+        countyGroup = null;
+    }
+
+    // USA map
+    var i = 0,
+        j = 0,
+        k = 0,
+        hue = 1,
+        hsl = {},
+        hsla = "",
+        USA = DATA.USA,
+        link = USA.states,
+        stateCodes = Object.keys(link),
+        stateGroup = null,
+        stateData = null,
+        county = null,
+        countiesTotal = 0,
+        countyGroup = null,
+        city = null,
+        citiesTotal = 0;
+
+
+    // USA keys: lat,lng,states
+    countryGroup = L.markerClusterGroup({
+        center: forceSingletonPosition ? L.latLng(USA.lat, USA.lng) : null,
+        data: {
+            name: "USA",
+            code: "USA",
+            color: "#b22234" //rgb(178,34,52) from https://en.wikipedia.org/wiki/Flag_of_the_United_States
+        },
+        //disableClusteringAtZoom: 3, // Try this option to keep individual States at low zoom levels, but there will be a bunch overlapping...
+        iconCreateFunction: function (cluster) {
+            var alienClustersCount = cluster.getAlienClustersCount(),
+                options = cluster._originalGroup.options,
+                isSingleton = cluster.isSingletonCluster();
+
+            return new L.DivIcon({
+                html: '<div style="background-color: ' + options.data.color + '; border-color: ' +
+                (isSingleton ? "black" : "rgba(178,34,52,0.6)") + ';">' + alienClustersCount +
+                (isSingleton ? '<span class="country-' + options.data.code + '"> ' + options.data.name + '</span>' : "") + '</div>',
+                className: isSingleton ? "marker-country" : 'marker-states-cluster',
+                iconSize: null
+            });
+        },
+        setLabel: function (cluster) {
+            var isSingleton = cluster.isSingletonCluster(),
+                options = cluster._originalGroup.options;
+
+            cluster.bindLabel(
+                isSingleton ?
+                "States in " + options.data.name +
+                "<br />Total included " + (addCities ? "cities" : "counties") + ": " + cluster.getChildCount() +
+                "<br />Lat: " + cluster._latlng.lat +
+                "<br />Lng: " + cluster._latlng.lng :
+
+                "States in part of " + options.data.name +
+                "<br />Total included " + (addCities ? "cities" : "counties") + ": " + cluster.getChildCount(),
+                {
+                    offset: [25, -15]
+                }
+            );
+        }
+    }).addTo(map);
+
+    // For each State.
+    for(i = 0; i < stateCodes.length; i += 1) {
+        // Condtion used only for testing with fewer data.
+        if (true || stateCodes[i] === "AK" || stateCodes[i] === "DE" || stateCodes[i] === "DC") {
+            // stateData keys: stateName,lat,lng,stateCounties
+            stateData = link[stateCodes[i]];
+            hue = getRandomHue2();
+            hsl = {h: hue, s: 100, l: 50};
+            stateGroup = L.markerClusterGroup({
+                stateData: L.extend(L.extend({}, stateData), {stateCode: stateCodes[i]}),
+                stateHue: hue,
+                stateHSL: getHSL(hsl),
+                stateHSLA: getHSLA(hsl, 0.6),
+                center: forceSingletonPosition ? L.latLng(stateData.lat, stateData.lng) : null,
+                //forceSingletonClusterAtZoom: 3, // For Alaska // does not work as expected because even at this zoom level, we still have individual cities not clustered in counties...
+                iconCreateFunction: function (cluster) {
+                    var childCount = cluster.getChildCount(),
+                        alienClustersCount = addCities ? cluster.getAlienClustersCount() : childCount,
+                        options = cluster._originalGroup.options,
+                        isSingleton = cluster.isSingletonCluster();
+
+                    return new L.DivIcon({
+                        html: '<div style="background-color: ' + options.stateHSL + '; border-color: ' +
+                        (isSingleton ? "black" : options.stateHSLA) + ';">' + alienClustersCount +
+                        (isSingleton ? '<span class="state-' + options.stateData.stateCode + '"> ' + options.stateData.stateName + '</span>' : "") + '</div>',
+                        className: isSingleton ? "marker-state" : 'marker-counties-cluster',
+                        iconSize: null
+                    });
+                },
+                setLabel: function (cluster) {
+                    var isSingleton = cluster.isSingletonCluster(),
+                        options = cluster._originalGroup.options,
+                        childCount = cluster.getChildCount();
+
+                    cluster.bindLabel(
+                        isSingleton ?
+                        "Total counties in " + options.stateData.stateName + " State" +
+                        "<br />State Code: " + options.stateData.stateCode +
+                        "<br />Lat: " + options.stateData.lat +
+                        "<br />Lng: " + options.stateData.lng +
+                        (addCities ? "<br />Total included cities: " + childCount : "") :
+
+                        "Counties in part of " + options.stateData.stateName +
+                        (addCities ? "<br />Total included cities: " + childCount : ""),
+                        {
+                            offset: [25, -15],
+                            direction: isSingleton ?
+                                "left": // To let the flag and State Name visible
+                                "right"
+                        }
+                    );
+                }
+            }).addTo(map);
+
+            // For each county.
+            for(j = 0; j < stateData.stateCounties.length; j += 1) {
+                county = stateData.stateCounties[j];
+                hsl = generateHSL(hue);
+                hsla = getHSLA(hsl, 0.6);
+
+                // Special case of county "Aleutians West" (code 16) in Alaska, coordinates [51.959447, 178.338813]
+                // Wrap it back to negative longitude, so that it is displayed closer to the rest of the State.
+                if (wrapCoordinates && county.code === 16) {
+                    county = L.extend({}, county); // Get a shallow copy of data to keep it intact.
+                    county.lng -= 360;
+                }
+
+                if (stateData.stateCode === "DC") {
+                    console.log("Processing Washington DC " + addCities);
+                }
+
+                if (addCities) {
+                    countyGroup = L.markerClusterGroup({
+                        // countyData keys: name,type,code,lat,lng
+                        countyData: L.extend({}, county),
+                        countyHSLA: hsla,
+                        countyHSL: getHSL(hsl),
+                        center: forceSingletonPosition ? L.latLng(county.lat, county.lng) : null,
+                        iconCreateFunction: function (cluster) {
+                            var childCount = cluster.getChildCount(),
+                                options = cluster._originalGroup.options,
+                                isSingleton = cluster.isSingletonCluster();
+
+                            return new L.DivIcon({
+                                html: '<div style="background-color: ' + options.countyHSL + '; border-color: ' +
+                                (isSingleton ? "black" : options.countyHSLA) + ';">' + childCount +
+                                (isSingleton ? '<span>' + options.countyData.name /*+ " " + options.countyData.type*/ + '</span>' : "") + '</div>',
+                                className: isSingleton ? "marker-county" : 'marker-cities-cluster',
+                                iconSize: null
+                            });
+                        },
+                        setLabel: function (cluster) {
+                            var isSingleton = cluster.isSingletonCluster(),
+                                options = cluster._originalGroup.options;
+
+                            cluster.bindLabel(
+                                isSingleton ?
+                                "Total cities in " + options.countyData.name + " " + options.countyData.type +
+                                "<br />County Code: " + options.countyData.code +
+                                "<br />Lat: " + options.countyData.lat +
+                                "<br />Lng: " + options.countyData.lng :
+                                "Cities in part of " + options.countyData.name + " " + options.countyData.type,
+                                {
+                                    offset: [20, -15]
+                                }
+                            );
+                        }
+                    });
+
+                    // For each City.
+                    for(k = 0; k < county.cities.length; k += 1) {
+                        city = county.cities[k];
+
+                        // Special case of city (GNIS 2418783) in Alaska, coordinates [52.880248, 173.256076]
+                        // Wrap it back to negative longitude, so that it is displayed closer to the rest of the State.
+                        if (wrapCoordinates && city.GNIS === 2418783) {
+                            city = L.extend({}, city); // Get a shallow copy of data to keep it intact.
+                            city.lng -= 360;
+                        }
+
+                        // city keys: code,GNIS,name,type,lat,lng
+                        L.marker([city.lat, city.lng], {
+                            icon: new L.DivIcon({
+                                html: '<div style="background-color: ' + hsla + ';"><span>' + city.name + '</span></div>',
+                                className: 'marker-city',
+                                iconSize: null
+                            })
+                        }).
+                            addTo(countyGroup).
+                            bindPopup(
+                            "City: " + city.name +
+                            "<br />Code: " + city.code +
+                            "<br />GNIS: " + city.GNIS +
+                            "<br />Type: " + city.type +
+                            "<br />From County: " + county.name +
+                            "<br />Latitude: " + city.lat +
+                            "<br />Longitude: " + city.lng
+                        );
+                        city = null;
+                        citiesTotal += 1;
+                    }
+
+                    // In case a county has only 1 city, force a cluster so that the user sees the county icon at some point.
+                    if (k === 1) {
+                        countyGroup.options.forceSingletonClusterAtZoom = 17;
+                    }
+
+                    // countyGroup does not need to be added on map before adding markers into it,
+                    // because we do not nest sub-groups into it.
+                    countyGroup.addTo(map);
+                    map.removeLayer(countyGroup);
+
+                    // Add the county in State if not empty.
+                    if (countyGroup._topClusterLevel.getChildCount()) {
+                        // In case the State has only 1 county, force a cluster so that the user sees the State icon at some point.
+                        if (stateData.stateCounties.length === 1) {
+                            stateGroup.options.forceSingletonClusterAtZoom = countyGroup.getSingletonCluster()._zoom + 1;
+                        }
+                        stateGroup.addLayer(countyGroup);
+                    }
+                    countyGroup = null;
+                    county = null;
+                    hsl = null;
+                    hsla = null;
+                    county = null;
+                    countiesTotal += 1;
+
+                } else { // Not adding cities.
+                    // county
+                    // countyData keys: name,type,code,lat,lng
+                    countyGroup = L.marker([county.lat, county.lng], {
+                        icon: new L.DivIcon({
+                            html: '<div style="background-color: ' + getHSL(hsl) + ';"><span>' + county.name  + " " + county.type + '</span></div>',
+                            className: "marker-county",
+                            iconSize: null
+                        })
+                    }).
+                        bindPopup(
+                        "County: " + county.name +
+                        "<br />Code: " + county.code +
+                        "<br />Type: " + county.type +
+                        "<br />From State: " + stateData.stateName +
+                        "<br />Latitude: " + county.lat +
+                        "<br />Longitude: " + county.lng
+                    );
+
+                    // In case the State has only 1 county, force a cluster so that the user sees the State icon at some point.
+                    if (stateData.stateCounties.length === 1) {
+                        stateGroup.options.forceSingletonClusterAtZoom = 17;
+                    }
+                    stateGroup.addLayer(countyGroup);
+                    countyGroup = null;
+                    county = null;
+                    countiesTotal += 1;
+                }
+
+
+            }
+
+            // Clean stateGroup.
+            map.removeLayer(stateGroup);
+
+            // Add stateGroup to countryGroup if not empty.
+            if (stateGroup._topClusterLevel.getChildCount()) {
+                countryGroup.addLayer(stateGroup);
+            }
+            stateGroup = null;
+            stateData = null;
+        }
+
+    }
+
+// Since we have forced single marker clusters, remove them when not needed.
+    countryGroup.cleanSingleMarkerClusters();
+
+// If a group "center" latlng position is specified, use it to display the singleton cluster, instead of the weighted latlng.
+    countryGroup.replaceSingletonLatLng();
+
+// Bind labels if specified.
+    countryGroup.setIconLabels();
+
+// Hack to display layers that are in the viewport.
+// Needed because we have disabled the display in addLayer().
+    map.removeLayer(countryGroup);
+    countryGroup.addTo(map);
+
+    if (addCities) {
+        console.log("Total Cities: " + countryGroup._topClusterLevel.getChildCount() + " added / " + citiesTotal + " in data");
+        console.log("Total Counties: " + countiesTotal);
+    } else {
+        console.log("Total Counties: " + countryGroup._topClusterLevel.getChildCount() + " added / " + countiesTotal + " in data");
+    }
+
+}
+
+
diff --git a/convert.html b/hierarchical-tree-of-groups/convert.html
similarity index 100%
rename from convert.html
rename to hierarchical-tree-of-groups/convert.html
diff --git a/data_usa.js b/hierarchical-tree-of-groups/data_usa.js
similarity index 99%
rename from data_usa.js
rename to hierarchical-tree-of-groups/data_usa.js
index 1dc0ab5..dd4f1a8 100644
--- a/data_usa.js
+++ b/hierarchical-tree-of-groups/data_usa.js
@@ -208828,8 +208828,8 @@ var DATA = {
    },
    "SC": {
     "stateName": "South Carolina",
-    "lat": 32.7784,
-    "lng": -86.929,
+    "lat": 33.9169, // 32.7784
+    "lng": -80.8957, // -86.9290
     "stateCounties": [
      {
       "code": 1,
@@ -212447,7 +212447,7 @@ var DATA = {
    },
    "SD": {
     "stateName": "South Dakota",
-    "lat": 44.4017,// 33.9169,
+    "lat": 44.4446, //44.4017,// 33.9169,
     "lng": -100.2282,
     "stateCounties": [
      {
diff --git a/data_usa_raw.js b/hierarchical-tree-of-groups/data_usa_raw.js
similarity index 99%
rename from data_usa_raw.js
rename to hierarchical-tree-of-groups/data_usa_raw.js
index cf9bdd1..7917fd7 100644
--- a/data_usa_raw.js
+++ b/hierarchical-tree-of-groups/data_usa_raw.js
@@ -39,8 +39,8 @@ var states = [
     'Oregon ;US-OR ;43.9336°N 120.5617°W',
     'Pennsylvania ;US-PA ;40.8786°N 77.7985°W',
     'Rhode Island ;US-RI ;41.6762°N 71.5562°W',
-    'South Carolina ;US-SC ;32.7784°N 86.9290°W',
-    'South Dakota ;US-SD ;33.9169°N 100.2282°W',
+    'South Carolina ;US-SC ;33.9169°N 80.8957°W', // bad previous value: 32.7784°N 86.9290°W
+    'South Dakota ;US-SD ;44.4446°N 100.2282°W', // bad previous value: 33.9169°N 100.2282°W
     'Tennessee ;US-TN ;35.8605°N 86.3504°W',
     'Texas ;US-TX ;31.4789°N 99.3287°W',
     'Utah ;US-UT ;39.3057°N 111.6685°W',
diff --git a/hierarchical-tree-of-groups/flags/19px-Flag_of_Idaho.svg.png b/hierarchical-tree-of-groups/flags/19px-Flag_of_Idaho.svg.png
new file mode 100644
index 0000000..f35e54a
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/19px-Flag_of_Idaho.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/19px-Flag_of_Rhode_Island.svg.png b/hierarchical-tree-of-groups/flags/19px-Flag_of_Rhode_Island.svg.png
new file mode 100644
index 0000000..bb06ced
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/19px-Flag_of_Rhode_Island.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/20px-Flag_of_Connecticut.svg.png b/hierarchical-tree-of-groups/flags/20px-Flag_of_Connecticut.svg.png
new file mode 100644
index 0000000..fa3d66a
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/20px-Flag_of_Connecticut.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/21px-Flag_of_Alaska.svg.png b/hierarchical-tree-of-groups/flags/21px-Flag_of_Alaska.svg.png
new file mode 100644
index 0000000..4ab90d5
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/21px-Flag_of_Alaska.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/21px-Flag_of_North_Dakota.svg.png b/hierarchical-tree-of-groups/flags/21px-Flag_of_North_Dakota.svg.png
new file mode 100644
index 0000000..91479b5
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/21px-Flag_of_North_Dakota.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/22px-Flag_of_Iowa.svg.png b/hierarchical-tree-of-groups/flags/22px-Flag_of_Iowa.svg.png
new file mode 100644
index 0000000..f54b5a4
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/22px-Flag_of_Iowa.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/22px-Flag_of_Virginia.svg.png b/hierarchical-tree-of-groups/flags/22px-Flag_of_Virginia.svg.png
new file mode 100644
index 0000000..d1f6877
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/22px-Flag_of_Virginia.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/22px-Flag_of_Wyoming.svg.png b/hierarchical-tree-of-groups/flags/22px-Flag_of_Wyoming.svg.png
new file mode 100644
index 0000000..f2a88bd
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/22px-Flag_of_Wyoming.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Alabama.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Alabama.svg.png
new file mode 100644
index 0000000..7fac5ed
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Alabama.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Arizona.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Arizona.svg.png
new file mode 100644
index 0000000..0883af5
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Arizona.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Arkansas.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Arkansas.svg.png
new file mode 100644
index 0000000..aae1704
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Arkansas.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_California.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_California.svg.png
new file mode 100644
index 0000000..8cd65ba
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_California.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Colorado.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Colorado.svg.png
new file mode 100644
index 0000000..f347377
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Colorado.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Delaware.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Delaware.svg.png
new file mode 100644
index 0000000..5366498
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Delaware.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Florida.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Florida.svg.png
new file mode 100644
index 0000000..e7b3f8c
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Florida.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Georgia_(U.S._state).svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Georgia_(U.S._state).svg.png
new file mode 100644
index 0000000..346f502
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Georgia_(U.S._state).svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Hawaii.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Hawaii.svg.png
new file mode 100644
index 0000000..9674ebc
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Hawaii.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Illinois.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Illinois.svg.png
new file mode 100644
index 0000000..ed7081c
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Illinois.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Indiana.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Indiana.svg.png
new file mode 100644
index 0000000..ba3e5a2
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Indiana.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Kansas.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Kansas.svg.png
new file mode 100644
index 0000000..a88544f
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Kansas.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Kentucky.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Kentucky.svg.png
new file mode 100644
index 0000000..7908bed
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Kentucky.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Louisiana.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Louisiana.svg.png
new file mode 100644
index 0000000..97fe029
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Louisiana.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Maine.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Maine.svg.png
new file mode 100644
index 0000000..8d1380f
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Maine.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Maryland.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Maryland.svg.png
new file mode 100644
index 0000000..5261548
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Maryland.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Massachusetts.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Massachusetts.svg.png
new file mode 100644
index 0000000..0fa0824
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Massachusetts.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Michigan.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Michigan.svg.png
new file mode 100644
index 0000000..26d83e1
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Michigan.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Minnesota.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Minnesota.svg.png
new file mode 100644
index 0000000..2b1bb96
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Minnesota.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Mississippi.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Mississippi.svg.png
new file mode 100644
index 0000000..482c1e9
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Mississippi.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Missouri.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Missouri.svg.png
new file mode 100644
index 0000000..aefc882
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Missouri.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Montana.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Montana.svg.png
new file mode 100644
index 0000000..08f0cf2
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Montana.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Nebraska.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Nebraska.svg.png
new file mode 100644
index 0000000..5b536fe
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Nebraska.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Nevada.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Nevada.svg.png
new file mode 100644
index 0000000..235f481
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Nevada.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_New_Hampshire.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_New_Hampshire.svg.png
new file mode 100644
index 0000000..4d737e7
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_New_Hampshire.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_New_Jersey.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_New_Jersey.svg.png
new file mode 100644
index 0000000..e292dea
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_New_Jersey.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_New_Mexico.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_New_Mexico.svg.png
new file mode 100644
index 0000000..3769e2f
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_New_Mexico.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_New_York.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_New_York.svg.png
new file mode 100644
index 0000000..acbacc7
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_New_York.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_North_Carolina.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_North_Carolina.svg.png
new file mode 100644
index 0000000..8272efd
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_North_Carolina.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Ohio.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Ohio.svg.png
new file mode 100644
index 0000000..a5e7f05
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Ohio.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Oklahoma.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Oklahoma.svg.png
new file mode 100644
index 0000000..61049ff
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Oklahoma.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Oregon.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Oregon.svg.png
new file mode 100644
index 0000000..e777d55
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Oregon.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Pennsylvania.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Pennsylvania.svg.png
new file mode 100644
index 0000000..95b6f33
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Pennsylvania.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_South_Carolina.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_South_Carolina.svg.png
new file mode 100644
index 0000000..33e159b
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_South_Carolina.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_South_Dakota.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_South_Dakota.svg.png
new file mode 100644
index 0000000..7be4ebc
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_South_Dakota.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Tennessee.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Tennessee.svg.png
new file mode 100644
index 0000000..b5fe439
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Tennessee.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Texas.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Texas.svg.png
new file mode 100644
index 0000000..6e50452
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Texas.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Utah.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Utah.svg.png
new file mode 100644
index 0000000..1cfe0c4
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Utah.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Vermont.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Vermont.svg.png
new file mode 100644
index 0000000..917df22
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Vermont.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Washington.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Washington.svg.png
new file mode 100644
index 0000000..dc23c83
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Washington.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_WashingtonDC.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_WashingtonDC.svg.png
new file mode 100644
index 0000000..8d9e0da
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_WashingtonDC.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_West_Virginia.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_West_Virginia.svg.png
new file mode 100644
index 0000000..ad983d3
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_West_Virginia.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_Wisconsin.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_Wisconsin.svg.png
new file mode 100644
index 0000000..ea6cf07
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_Wisconsin.svg.png differ
diff --git a/hierarchical-tree-of-groups/flags/23px-Flag_of_the_United_States.svg.png b/hierarchical-tree-of-groups/flags/23px-Flag_of_the_United_States.svg.png
new file mode 100644
index 0000000..22f5712
Binary files /dev/null and b/hierarchical-tree-of-groups/flags/23px-Flag_of_the_United_States.svg.png differ
diff --git a/images/layers-2x.png b/hierarchical-tree-of-groups/images/layers-2x.png
similarity index 100%
rename from images/layers-2x.png
rename to hierarchical-tree-of-groups/images/layers-2x.png
diff --git a/images/layers.png b/hierarchical-tree-of-groups/images/layers.png
similarity index 100%
rename from images/layers.png
rename to hierarchical-tree-of-groups/images/layers.png
diff --git a/images/marker-icon-2x.png b/hierarchical-tree-of-groups/images/marker-icon-2x.png
similarity index 100%
rename from images/marker-icon-2x.png
rename to hierarchical-tree-of-groups/images/marker-icon-2x.png
diff --git a/images/marker-icon.png b/hierarchical-tree-of-groups/images/marker-icon.png
similarity index 100%
rename from images/marker-icon.png
rename to hierarchical-tree-of-groups/images/marker-icon.png
diff --git a/images/marker-shadow.png b/hierarchical-tree-of-groups/images/marker-shadow.png
similarity index 100%
rename from images/marker-shadow.png
rename to hierarchical-tree-of-groups/images/marker-shadow.png
diff --git a/hierarchical-tree-of-groups/index.html b/hierarchical-tree-of-groups/index.html
new file mode 100644
index 0000000..a938221
--- /dev/null
+++ b/hierarchical-tree-of-groups/index.html
@@ -0,0 +1,523 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Demo of Hierarchical Tree of Leaflet Marker Cluster Groups</title>
+    <link rel="stylesheet" href="leaflet.css" />
+    <link rel="stylesheet" href="MarkerCluster.css" />
+    <link rel="stylesheet" href="MarkerCluster.Default.css" />
+    <link rel="stylesheet" href="leaflet.label.css" />
+
+    <style>
+
+        .marker-country {
+            width: 50px;
+            height: 50px;
+            text-align: center;
+            line-height: 50px;
+            margin: -25px 0 0 -25px;
+
+        }
+
+        .marker-country div {
+            width: 20px;
+            height: 20px;
+            border-radius: 5px;
+            background-clip: padding-box;
+            border: 2px solid black;
+            display: inline-block;
+            vertical-align:middle;
+            line-height: 22px;
+        }
+
+        .marker-country span {
+            margin: -17px 0 0 27px;
+            display: inline-block;
+            text-align: left;
+            line-height: 15px;
+            vertical-align: top;
+            white-space: nowrap;
+        }
+
+        .marker-states-cluster {
+            width: 50px;
+            height: 50px;
+            text-align: center;
+            line-height: 50px;
+            margin: -25px 0 0 -25px;
+        }
+
+        .marker-states-cluster div {
+            background-clip: padding-box;
+            width: 25px;
+            height: 25px;
+            border-radius: 25px;
+            border: 5px solid black;
+            display: inline-block;
+            vertical-align:middle;
+            line-height: 27px;
+        }
+
+        .marker-state {
+            width: 50px;
+            height: 50px;
+            text-align: center;
+            line-height: 50px;
+            margin: -25px 0 0 -25px;
+
+        }
+
+        .marker-state div {
+            width: 25px;
+            height: 25px;
+            border-radius: 25px;
+            background-clip: padding-box;
+            border: 3px solid black;
+            display: inline-block;
+            vertical-align:middle;
+            line-height: 27px;
+        }
+
+        .marker-state span {
+            margin: -20px 0 0 32px;
+            display: inline-block;
+            text-align: left;
+            line-height: 15px;
+            vertical-align: top;
+            white-space: nowrap;
+        }
+
+        .marker-counties-cluster {
+            width: 50px;
+            height: 50px;
+            text-align: center;
+            line-height: 50px;
+            margin: -25px 0 0 -25px;
+        }
+
+        .marker-counties-cluster div {
+            background-clip: padding-box;
+            width: 25px;
+            height: 25px;
+            border-radius: 5px;
+            border: 3px solid black;
+            display: inline-block;
+            vertical-align:middle;
+            line-height: 27px;
+        }
+
+        .marker-county {
+            width: 40px;
+            height: 40px;
+            text-align: center;
+            line-height: 40px;
+            margin: -20px 0 0 -20px;
+
+        }
+
+        .marker-county div {
+            width: 20px;
+            height: 20px;
+            border-radius: 5px;
+            background-clip: padding-box;
+            border: 2px solid black;
+            display: inline-block;
+            vertical-align:middle;
+            line-height: 22px;
+        }
+
+        .marker-county span {
+            margin: -18px 0 0 25px;
+            display: inline-block;
+            text-align: left;
+            line-height: 15px;
+            vertical-align: top;
+        }
+
+        .marker-cities-cluster {
+            width: 40px;
+            height: 40px;
+            text-align: center;
+            line-height: 40px;
+            margin: -20px 0 0 -20px;
+        }
+
+        .marker-cities-cluster div {
+            background-clip: padding-box;
+            width: 20px;
+            height: 20px;
+            border-radius: 20px;
+            border: 3px solid black;
+            display: inline-block;
+            vertical-align:middle;
+            line-height: 22px;
+        }
+
+        .marker-city {
+            width: 30px;
+            height: 30px;
+            text-align: center;
+            line-height: 30px;
+            margin: -15px 0 0 -15px;
+        }
+
+        .marker-city div {
+            width: 10px;
+            height: 10px;
+            border-radius: 10px;
+            border: 1px solid black;
+            display: inline-block;
+            vertical-align:middle;
+        }
+
+        .marker-city span {
+            margin: -2px 0 0 15px;
+            display: inline-block;
+            text-align: left;
+            line-height: 15px;
+            vertical-align: top;
+        }
+
+        .country-USA::before {content: url("flags/23px-Flag_of_the_United_States.svg.png");}
+
+        .state-AL::before {content: url("flags/23px-Flag_of_Alabama.svg.png");}
+        .state-AK::before {content: url("flags/21px-Flag_of_Alaska.svg.png");}
+        .state-AZ::before {content: url("flags/23px-Flag_of_Arizona.svg.png");}
+        .state-AR::before {content: url("flags/23px-Flag_of_Arkansas.svg.png");}
+        .state-CA::before {content: url("flags/23px-Flag_of_California.svg.png");}
+        .state-CO::before {content: url("flags/23px-Flag_of_Colorado.svg.png");}
+        .state-CT::before {content: url("flags/20px-Flag_of_Connecticut.svg.png");}
+        .state-DE::before {content: url("flags/23px-Flag_of_Delaware.svg.png");}
+        .state-DC::before {content: url("flags/23px-Flag_of_WashingtonDC.svg.png");}
+        .state-FL::before {content: url("flags/23px-Flag_of_Florida.svg.png");}
+        .state-GA::before {content: url("flags/23px-Flag_of_Georgia_%28U.S._state%29.svg.png");}
+        .state-HI::before {content: url("flags/23px-Flag_of_Hawaii.svg.png");}
+        .state-ID::before {content: url("flags/19px-Flag_of_Idaho.svg.png");}
+        .state-IL::before {content: url("flags/23px-Flag_of_Illinois.svg.png");}
+        .state-IN::before {content: url("flags/23px-Flag_of_Indiana.svg.png");}
+        .state-IA::before {content: url("flags/22px-Flag_of_Iowa.svg.png");}
+        .state-KS::before {content: url("flags/23px-Flag_of_Kansas.svg.png");}
+        .state-KY::before {content: url("flags/23px-Flag_of_Kentucky.svg.png");}
+        .state-LA::before {content: url("flags/23px-Flag_of_Louisiana.svg.png");}
+        .state-ME::before {content: url("flags/23px-Flag_of_Maine.svg.png");}
+        .state-MD::before {content: url("flags/23px-Flag_of_Maryland.svg.png");}
+        .state-MA::before {content: url("flags/23px-Flag_of_Massachusetts.svg.png");}
+        .state-MI::before {content: url("flags/23px-Flag_of_Michigan.svg.png");}
+        .state-MN::before {content: url("flags/23px-Flag_of_Minnesota.svg.png");}
+        .state-MS::before {content: url("flags/23px-Flag_of_Mississippi.svg.png");}
+        .state-MO::before {content: url("flags/23px-Flag_of_Missouri.svg.png");}
+        .state-MT::before {content: url("flags/23px-Flag_of_Montana.svg.png");}
+        .state-NE::before {content: url("flags/23px-Flag_of_Nebraska.svg.png");}
+        .state-NV::before {content: url("flags/23px-Flag_of_Nevada.svg.png");}
+        .state-NH::before {content: url("flags/23px-Flag_of_New_Hampshire.svg.png");}
+        .state-NJ::before {content: url("flags/23px-Flag_of_New_Jersey.svg.png");}
+        .state-NM::before {content: url("flags/23px-Flag_of_New_Mexico.svg.png");}
+        .state-NY::before {content: url("flags/23px-Flag_of_New_York.svg.png");}
+        .state-NC::before {content: url("flags/23px-Flag_of_North_Carolina.svg.png");}
+        .state-ND::before {content: url("flags/21px-Flag_of_North_Dakota.svg.png");}
+        .state-OH::before {content: url("flags/23px-Flag_of_Ohio.svg.png");}
+        .state-OK::before {content: url("flags/23px-Flag_of_Oklahoma.svg.png");}
+        .state-OR::before {content: url("flags/23px-Flag_of_Oregon.svg.png");}
+        .state-PA::before {content: url("flags/23px-Flag_of_Pennsylvania.svg.png");}
+        .state-RI::before {content: url("flags/19px-Flag_of_Rhode_Island.svg.png");}
+        .state-SC::before {content: url("flags/23px-Flag_of_South_Carolina.svg.png");}
+        .state-SD::before {content: url("flags/23px-Flag_of_South_Dakota.svg.png");}
+        .state-TN::before {content: url("flags/23px-Flag_of_Tennessee.svg.png");}
+        .state-TX::before {content: url("flags/23px-Flag_of_Texas.svg.png");}
+        .state-UT::before {content: url("flags/23px-Flag_of_Utah.svg.png");}
+        .state-VT::before {content: url("flags/23px-Flag_of_Vermont.svg.png");}
+        .state-VA::before {content: url("flags/22px-Flag_of_Virginia.svg.png");}
+        .state-WA::before {content: url("flags/23px-Flag_of_Washington.svg.png");}
+        .state-WV::before {content: url("flags/23px-Flag_of_West_Virginia.svg.png");}
+        .state-WI::before {content: url("flags/23px-Flag_of_Wisconsin.svg.png");}
+        .state-WY::before {content: url("flags/22px-Flag_of_Wyoming.svg.png");}
+
+        html, body {
+            margin: 0;
+            padding: 0;
+            height: 100%;
+            width: 100%;
+        }
+
+        h1 {
+            margin-left: 1em;
+            margen-right: 1em;
+        }
+
+        #leftPane {
+            position: fixed;
+            height: 100%;
+            width: 50%;
+        }
+
+        #map {
+            width: 100%;
+            height: 200px;
+        }
+
+        #zoomInfo {
+            padding: .5em;
+        }
+
+        #options {
+            padding: .5em;
+        }
+
+        #rightPane {
+            margin-left: 50%;
+            padding: 1em .5em 1em 1em;
+        }
+
+        code {
+            color: brown;
+        }
+
+    </style>
+</head>
+<body>
+<div id="leftPane">
+    <h1 id="pageTitle">Demo of Hierarchical Tree of Leaflet Marker Cluster Groups</h1>
+
+    <div id="map"></div>
+
+    <div id="zoomInfo">Zoom level: <span id="zoomLevel">4</span></div>
+
+    <form id="options">
+        <label for="forceSingletonPosition">
+            <input type="checkbox" id="forceSingletonPosition" checked="checked" />
+            Force singleton cluster position to the conventional geographic center
+        </label>
+        <br />
+
+        <label for="wrapCoordinates">
+            <input type="checkbox" id="wrapCoordinates" checked="checked" />
+            Wrap coordinates of points far West of Alaska (from somewhere in the
+            170's degrees of longitude to below -180 degrees), so that they can
+            cluster with other points.
+        </label>
+        <br />
+
+        <label for="addCities">
+            <input type="checkbox" id="addCities" />
+            Include Cities in the data (CAUTION: because of the amount of data,
+            the processing time may be a few dozens of seconds, please be
+            patient if you check this option; allow the script to continue if
+            prompted)
+        </label>
+        <br />
+
+        <button id="submit" type="submit">Update map</button>
+    </form>
+</div>
+<div id="rightPane">
+    <div id="explanations">
+        <h2>Explanations</h2>
+        <p>The data is structured in a hierarchical tree made of 4 levels:</p>
+        <ol>
+            <li>Big Square: Country (1 – USA)</li>
+            <li>Big Disks: States (51 – including Washington DC)</li>
+            <li>Medium Squares: Counties (3,143 – including cities and boroughs
+                that are at the same level as counties)</li>
+            <li>Small Disks: Cities (29,155*) (note: not displaying this level
+                by default, because of the required processing time. If you
+                wish to add it, tick the corresponding box in the options above
+                and submit)</li>
+        </ol>
+        <p>
+            Each level has the above number of Marker Cluster Groups or Markers.
+            That is, there is 1 group for the country, 51 groups for the States,
+            3,143 groups for the counties, and finally 29,155 markers for the
+            cities.
+        </p>
+        <p>
+            Each Group is nested in a Group of the upper level, but it can cluster only
+            with sibling Groups (i.e. from the same level) which share the same parent Group, and only once it has
+            clustered down to a single cluster** (called "singleton").
+            See for example the
+            <a class="mapSetView" href="" title="Set the map view to West side of Oklahoma"
+               data-lat="36.7473255" data-lng="-100.9834555" data-zoom="7"
+                    >West side of Oklahoma</a> (in the middle of USA,
+            just above Texas): there are a few cities and counties very close to Texas
+            cities and counties, but they are note allowed to cluster with them, because they
+            do not belong to the same Group.
+        </p>
+        <p>
+            Each State group receives a random hue (type of color) at page
+            initialization (so if you want to play and get different colors,
+            just reload the page).
+        </p>
+        <p>
+            Each county receives random saturation and lightness values, but
+            inherit from its State hue. So all counties in a given State have a
+            similar color as the State.
+        </p>
+        <p>
+            Each city in a county receives the exact color (hue, saturation and
+            lightness) as its county.
+        </p>
+
+        <h2>The code</h2>
+        <p>
+            This code is far from bullet proof, it is more like a proof of
+            concept. It assumes that the data structure will not change after
+            Marker Cluster Groups are nested in another one (no more
+            <code>addLayer</code> or <code>removeLayer</code>), otherwise it
+            would break the parent Group, by breaking the singleton cluster
+            detection.
+        </p>
+        <p>
+            Because I have made most of the checks in <code>addLayer</code>
+            rather than in <code>_addLayer</code> (internal method), it is
+            necessary to have a Group added on the map before nesting other
+            Groups into it. Otherwise, they will be appended to
+            <code>_NeedsClustering</code> array, then they will be passed
+            straight to <code>_addLayer</code> once the Group is added to the
+            map, hence bypassing my checks. Definitely I made a mistake there.
+        </p>
+        <p>
+            Groups are removed from the map before being nested in their parent
+            group, otherwise the markers may get stuck.
+        </p>
+        <p>
+            There is a bug with events on markers and clusters that are
+            initially visible. I did not have time to look for the root cause,
+            so the simple work around I use is to disable the initial display
+            (but still have the parent group on the map), then remove the group
+            from the map and add it back.
+        </p>
+        <p>
+            I added a method (<code>group.replaceSingletonLatLng()</code>) to
+            force the position of the singleton cluster to given coordinates
+            (specified in <code>options.center</code>), instead of the weighted
+            average of all children positions. It is called once on the top
+            group before adding it back to the map. It may be useful to avoid
+            a singleton cluster being displayed in a place too far away from the
+            conventional position of an administrative area. For example, if
+            that area is not convex, and many children are on the extremities,
+            the weighted average position may be outside of the administrative
+            area. In the case of USA, because of Alaska and Hawaii, the weighted
+            average position is
+            <a class="mapSetView" href=""
+               title="Set the map view to USA singleton cluster (please also update the map without forcing singleton clusters position)"
+               data-lat="31.4661" data-lng="-128.1486" data-zoom="0"
+                >somewhere offshore the West coast</a>, in the
+            Pacific Ocean! With this method, we can force the singleton cluster
+            at a known position.
+        </p>
+        <p>
+            I also tried to implement an option
+            (<code>forceSingletonClusterAtZoom</code>) to force a group to cluster all
+            its children in a singleton cluster at a specified zoom level. The
+            idea would be to make sure all groups are displayed as singletons at
+            the same zoom level. For example, we could have all States shown
+            with their flag (not considering overlapping that would happen on
+            the East coast...). But this option breaks if sub-groups are not at
+            least singleton clusters themselves at that zoom level. Look for
+            example Alaska (the big State on the far North West...): at zoom
+            level 3, there is still a
+            <a class="mapSetView" href=""
+               title="Set the map view to Point Hope (please also update the map with cities included)"
+               data-lat="68.343731" data-lng="-166.669369" data-zoom="3"
+                >single city displayed (Point Hope)</a>, so its parent
+            county (North Slope) is not a singleton, and I cannot gather it into
+            the Alaska State with my current code. Maybe with more time I could
+            try to overcome this issue. However, forcing a clustering may badly
+            impair the user experience, because we could fall in a situation
+            where we still have a cluster for highly distant children, beyond
+            the viewport. In that case, MarkerCluster algorithm behaves badly
+            because it never shows the children when the user zooms on the
+            cluster, since they are outside the visible bounds. Same thing if
+            the user clicks on the cluster: it will try to zoom until the
+            children are shown, which may never happen! This option is still
+            used nevertheless to implement the single cluster trick (see note
+            **).
+        </p>
+        <p>
+            On the opposite, it is very possible to use the option
+            <code>disableClusteringAtZoom</code> from the original MarkerCluster
+            plugin. That way, you can force a given level not to cluster, until
+            all children become singletons. The drawback is that this condition
+            may happen for low zoom levels, when many other children are already
+            heavily overlapping... Yes, I am thinking about Alaska again :-)
+        </p>
+
+        <h2>Notes</h2>
+        <ul>
+            <li>
+                * Displayed cities are those from OpenGeocode with geographic
+                coordinates and for which the first associated county (sometimes
+                a city is associated with more than 1 county) also has
+                geographic coordinates.
+            </li>
+            <li>
+                ** In the case of a group that has only 1 child, normally it
+                never "clusters" with the initial version of MarkerCluster.
+                In an early version of this code, I allowed the single child to cluster with
+                any group of the upper level, as if it were already its own
+                parent (that is, a city alone in its county could have clustered
+                with other full counties at zoom level max - 1 or above). But
+                this may look strange because it is still rendered as a single
+                object of lower level (for example, a city marker that clusters
+                with a full county), so I tried to implement forcing a cluster
+                to be made, and keep it only at the zoom level just above the
+                level it clusters with other groups. You can have a look at
+                <a class="mapSetView" href=""
+                   title="Set the map view to Washington DC"
+                   data-lat="38.904103" data-lng="-77.017229" data-zoom="7"
+                        >Washington DC</a> (District of Columbia, somewhere North East) for
+                example: it clusters with Delaware State at zoom 6. At zoom 7,
+                it is rendered as a State. At zoom 8 and below, it is rendered as a
+                county. If you have displayed Cities, this actually occurs 1
+                zoom level below: it clusters with Delaware at zoom 5, it is a
+                State at zoom 6, a county at zoom 7 and at zoom 8 and below, it
+                is a city. This is due to Delaware cities which force
+                that State to appear only at zoom level 6, hence it can cluster
+                with District of Columbia State only at zoom 5. This is slightly
+                different from <code>options.singleMarkerMode</code>, because
+                the latter simply replaces the icon by one similar to clusters,
+                for all zoom levels, whereas here I want only the same icon for
+                1 zoom level, just before it clusters.
+            </li>
+            <li>
+                ** It may happen that a group (nested or not) never clusters to
+                a singleton cluster. Typically for Alaska: when coordinates are
+                not wrapped, a city
+                (<a class="mapSetView" href=""
+                   title="Set the map view to Attu Station (please update the map without wrapping coordinates)"
+                   data-lat="352.880248" data-lng="173.256076" data-zoom="0"
+                    >Attu Station</a>) and its county (Aleutians West) are on longitude somewhere in
+                the 170's degrees, hence they are never within 80 pixels of another
+                city of its county or another county of Alaska, even at zoom level 0. I
+                tried to force nevertheless the whole State to cluster (see
+                explanation about <code>forceSingletonClusterAtZoom</code>), but this
+                would probably require a more complex algorithm than what I have
+                done. The simple workaround for now is to wrap the coordinates.
+            </li>
+        </ul>
+
+        <h2>Sources of data</h2>
+        <ul>
+            <li>
+                USA and States: <a href="https://en.wikipedia.org/wiki/Main_Page" target="_blank"
+                                        >Wikipedia</a>
+                (<a href="https://en.wikipedia.org/wiki/List_of_states_and_territories_of_the_United_States" target="_blank"
+                    >List of states and territories of the United States</a>
+                and
+                <a href="https://en.wikipedia.org/wiki/Geographic_centers_of_the_United_States" target="_blank"
+                        >Geographic centers of the United States</a>,
+                license CC-BY-SA 3.0 Unported)
+            </li>
+            <li>Counties and cities: <a href="http://opengeocode.org" target="_blank">OpenGeocode</a> (public domain)</li>
+            <li>Map and tiles: <a href="http://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap contributors</a>, license ODbL.</li>
+        </ul>
+    </div>
+</div>
+
+    <script src="data_usa.js"></script>
+
+    <script src="leaflet-src.js"></script>
+    <script src="leaflet.markercluster-src-hierarchicalTree.js"></script>
+    <script src="leaflet.label-src.js"></script>
+    <script src="clustertest.js"></script>
+</body>
+</html>
\ No newline at end of file
diff --git a/leaflet-src.js b/hierarchical-tree-of-groups/leaflet-src.js
similarity index 100%
rename from leaflet-src.js
rename to hierarchical-tree-of-groups/leaflet-src.js
diff --git a/leaflet.css b/hierarchical-tree-of-groups/leaflet.css
similarity index 100%
rename from leaflet.css
rename to hierarchical-tree-of-groups/leaflet.css
diff --git a/leaflet.label-src.js b/hierarchical-tree-of-groups/leaflet.label-src.js
similarity index 100%
rename from leaflet.label-src.js
rename to hierarchical-tree-of-groups/leaflet.label-src.js
diff --git a/leaflet.label.css b/hierarchical-tree-of-groups/leaflet.label.css
similarity index 100%
rename from leaflet.label.css
rename to hierarchical-tree-of-groups/leaflet.label.css
diff --git a/leaflet.markercluster-src.js b/hierarchical-tree-of-groups/leaflet.markercluster-src-hierarchicalTree.js
similarity index 97%
rename from leaflet.markercluster-src.js
rename to hierarchical-tree-of-groups/leaflet.markercluster-src-hierarchicalTree.js
index 8f1275a..6b8aecc 100644
--- a/leaflet.markercluster-src.js
+++ b/hierarchical-tree-of-groups/leaflet.markercluster-src-hierarchicalTree.js
@@ -47,8 +47,8 @@
 				this.options.iconCreateFunction = this._defaultIconCreateFunction;
 			}
 
-			if (typeof options.forcedSingletonClusterAtZoom === "undefined") {
-				this.options.forcedSingletonClusterAtZoom = -2;
+			if (typeof options.forceSingletonClusterAtZoom === "undefined") {
+				this.options.forceSingletonClusterAtZoom = -2;
 			}
 
 			this._featureGroup = L.featureGroup();
@@ -79,15 +79,12 @@
 
 		// ghybs Sep-2015
 		// To be called after all children have been added / nested.
-		// Replaces all clusters with single marker (which have been created through forcedSingletonClusterAtZoom) by the marker at upper zoom level.
+		// Replaces all clusters with single marker (which have been created through forceSingletonClusterAtZoom) by the marker at upper zoom level.
 		// Cannot use _recursively because we are changing the childClusters tree on the fly.
 		cleanSingleMarkerClusters: function () {
 			function execute(cluster) {
 				var child,
 					marker,
-					/*gridClusters = this._gridClusters,
-					gridUnclustered = this._gridUnclustered,
-					map = this._map,*/
 					backupParent;
 
 				for(var i = 0; i < cluster._childClusters.length; i += 1) {
@@ -113,14 +110,11 @@
 
 							// Replace all intermediate clusters by a new one.
 							// Leave DistanceGrid dirty...
-							//var newCluster;
 							for(var z = marker._zoom - 1; z > cluster._zoom; z -= 1) {
-								console.log("zoom: " + marker._zoom);
 								marker = new L.MarkerCluster(marker._originalGroup, z, marker);
 								marker._group = cluster._group;
 								//marker = newCluster;
 							}
-							console.log("cluster zoom: " + cluster._zoom);
 
 							// Add the last (lower zoom) newCluster at cluster level.
 							// Disconnect parent first to avoid propagating counts up.
@@ -156,64 +150,33 @@
 			}
 
 			execute(this._topClusterLevel);
-
-
-			/*this._topClusterLevel._recursively(
-				new L.LatLngBounds(new L.LatLng(90, -180), new L.LatLng(-90, 180)),
-				-1,
-				this._maxZoom,
-				// Run at every level.
-				function (c) {
-					var parent = c.__parent;
-					if (c._childCount === 1 && parent && c._originalGroup === parent._originalGroup) {
-						var marker = [];
-
-						c.getAllChildMarkers(marker);
-						marker = marker[0];
-
-						console.log("removing layer at zoom " + c._zoom);
-
-						parent._group._removeLayer(c, true);
-						parent._addChild(marker);
-
-						/*if (parent._group.hasLayer(c)) {
-							parent._group._removeLayer(c, true);
-							parent._addChild(marker);
-						}* /
-					}
-				}
-			);*/
 		},
 
 		// ghybs Sep-2015
 		// To be called after all children have been added / nested.
 		// Sets the latlng position of all singleton clusters to their center (user specified position) if any.
 		replaceSingletonLatLng: function () {
-			this._topClusterLevel._recursively(
-				new L.LatLngBounds(new L.LatLng(90, -180), new L.LatLng(-90, 180)),
-				-1,
-				this._maxZoom,
-				// Run at every level.
-				function (c) {
-					c._setSingletonLatLng();
+			function replaceLatLng(cluster) {
+				cluster._setSingletonLatLng();
+				for (var j = 0; j < cluster._childClusters.length; j += 1) {
+					replaceLatLng(cluster._childClusters[j]);
 				}
-			);
+			}
+			replaceLatLng(this._topClusterLevel, this);
 		},
 
 		// ghybs Sep-2015
 		// To be called after all children have been added / nested.
 		setIconLabels: function () {
-			this._topClusterLevel._recursively(
-				new L.LatLngBounds(new L.LatLng(90, -180), new L.LatLng(-90, 180)),
-				-1,
-				this._maxZoom,
-				// Run at every level.
-				function (c) {
-					if (typeof c._originalGroup.options.setLabel === "function") {
-						c._originalGroup.options.setLabel(c);
-					}
+			function setLabel(cluster) {
+				if (typeof cluster._originalGroup.options.setLabel === "function") {
+					cluster._originalGroup.options.setLabel(cluster);
 				}
-			);
+				for (var j = 0; j < cluster._childClusters.length; j += 1) {
+					setLabel(cluster._childClusters[j]);
+				}
+			}
+			setLabel(this._topClusterLevel, this);
 		},
 
 		addLayer: function (layer) {
@@ -245,8 +208,8 @@
 				// Replace the cluster group, so that the cluster will be displayed in the correct _featureGroup.
 				function replaceClusterGroup(cluster, group) {
 					cluster._group = group;
-					for (var i = 0; i < cluster._childClusters.length; i += 1) {
-						replaceClusterGroup(cluster._childClusters[i], group);
+					for (var j = 0; j < cluster._childClusters.length; j += 1) {
+						replaceClusterGroup(cluster._childClusters[j], group);
 					}
 				}
 				replaceClusterGroup(layer._topClusterLevel, this);
@@ -255,6 +218,12 @@
 				layer = layer.getSingletonCluster();
 				if (layer.__parent) {
 					zoom = layer._zoom - 1;
+
+					// In case disableClusteringAtZoom is set, make sure we import a cluster of zoom at most equal to this._maxZoom.
+					while (zoom > this._maxZoom) {
+						layer = layer.__parent;
+						zoom -= 1;
+					}
 				} else { // We got a _topClusterLevel.
 					// If there is only 1 single marker, it can cluster with other markers and clusters of THIS group.
 					if (layer.getChildCount() === 1) {
@@ -1074,7 +1043,7 @@
 
 				// ghybs Sep-2015
 				// Implement force singleton cluster.
-				var closest = (zoom <= this.options.forcedSingletonClusterAtZoom) ?
+				var closest = (zoom <= this.options.forceSingletonClusterAtZoom) ?
 						gridClusters[zoom].getAnyObject() :
 						gridClusters[zoom].getNearObject(markerPoint);
 				//var closest = gridClusters[zoom].getNearObject(markerPoint);
@@ -1089,7 +1058,7 @@
 				//Try find a marker close by to form a new cluster with
 				// ghybs Sep-2015: now closest can be a cluster! In that case, closest._zoom = zoom + 1
 				// Implement force singleton cluster.
-				closest = (zoom <= this.options.forcedSingletonClusterAtZoom) ?
+				closest = (zoom <= this.options.forceSingletonClusterAtZoom) ?
 					gridUnclustered[zoom].getAnyObject() :
 					gridUnclustered[zoom].getNearObject(markerPoint);
 				//closest = gridUnclustered[zoom].getNearObject(markerPoint);
@@ -1146,7 +1115,7 @@
 
 					// ghybs Sep-2015
 					// Make a new cluster even for the very first marker / alienCluster, in case it will be the only one.
-				} else if (zoom <= this.options.forcedSingletonClusterAtZoom) {
+				} else if (zoom <= this.options.forceSingletonClusterAtZoom) {
 					newCluster = new L.MarkerCluster(this, zoom, layer);
 					gridClusters[zoom].addObject(newCluster, this._map.project(newCluster._cLatLng, zoom));
 					layer.__parent = newCluster;
@@ -1565,7 +1534,7 @@
 			var singletonCenter = this._originalGroup.options.center,
 				condition = this.isSingletonCluster();
 
-			this._latlng = (this.isSingletonCluster() && typeof singletonCenter !== "undefined") ?
+			this._latlng = (this.isSingletonCluster() && singletonCenter instanceof L.LatLng) ?
 				singletonCenter :
 				this._wLatLng;
 		},
@@ -1595,10 +1564,6 @@
 			if (this.__parent) {
 				this.__parent._addChild(new1, true);
 			}
-
-			// ghybs Sep-2015
-			// Now that child is added up to the top, we can check whether THIS cluster is singleton or not, and adjust its position if necessary.
-			//this._setSingletonLatLng();
 		},
 
 		//Expand our bounds and tell our parent to
@@ -1840,9 +1805,6 @@
 			for (i = childClusters.length - 1; i >= 0; i--) {
 				this._expandBounds(childClusters[i]);
 			}
-
-			// ghybs Sep-2015
-			//this._setSingletonLatLng();
 		},
 
 		//Returns true if we are the parent of only one cluster and that cluster is the same as us
diff --git a/papaparse.js b/hierarchical-tree-of-groups/papaparse.js
similarity index 100%
rename from papaparse.js
rename to hierarchical-tree-of-groups/papaparse.js
diff --git a/index.html b/index.html
deleted file mode 100644
index 0483cdc..0000000
--- a/index.html
+++ /dev/null
@@ -1,185 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <title>Leaflet MarkerClusters Test</title>
-    <link rel="stylesheet" href="leaflet.css" />
-    <link rel="stylesheet" href="MarkerCluster.css" />
-    <link rel="stylesheet" href="MarkerCluster.Default.css" />
-    <link rel="stylesheet" href="leaflet.label.css" />
-
-    <style>
-        #map {
-            height: 900px;
-            width: 900px;
-        }
-
-        .marker-cluster {
-            background-color: rgba(220, 220, 220, 0.6);
-        }
-
-        .marker-state {
-            width: 50px;
-            height: 50px;
-            text-align: center;
-            line-height: 50px;
-            margin: -25px 0 0 -25px;
-
-        }
-
-        .marker-state div {
-            width: 30px;
-            height: 30px;
-            border-radius: 30px;
-            background-clip: padding-box;
-            border: 3px solid black;
-            display: inline-block;
-            vertical-align:middle;
-            line-height: 32px;
-        }
-
-        .marker-state span {
-            margin: -23px 0 0 35px;
-            display: inline-block;
-            text-align: left;
-            line-height: 15px;
-            vertical-align: top;
-        }
-
-        .marker-counties-cluster {
-            width: 50px;
-            height: 50px;
-            text-align: center;
-            line-height: 50px;
-            margin: -25px 0 0 -25px;
-        }
-
-        .marker-counties-cluster div {
-            background-clip: padding-box;
-            width: 25px;
-            height: 25px;
-            border-radius: 5px;
-            border: 3px solid black;
-            display: inline-block;
-            vertical-align:middle;
-            line-height: 27px;
-        }
-
-        .marker-county {
-            width: 40px;
-            height: 40px;
-            text-align: center;
-            line-height: 40px;
-            margin: -20px 0 0 -20px;
-
-        }
-
-        .marker-county div {
-            width: 20px;
-            height: 20px;
-            border-radius: 5px;
-            background-clip: padding-box;
-            border: 2px solid black;
-            display: inline-block;
-            vertical-align:middle;
-            line-height: 22px;
-        }
-
-        .marker-county span {
-            margin: -18px 0 0 25px;
-            display: inline-block;
-            text-align: left;
-            line-height: 15px;
-            vertical-align: top;
-        }
-
-        .marker-cities-cluster {
-            width: 40px;
-            height: 40px;
-            text-align: center;
-            line-height: 40px;
-            margin: -20px 0 0 -20px;
-        }
-
-        .marker-cities-cluster div {
-            background-clip: padding-box;
-            width: 20px;
-            height: 20px;
-            border-radius: 20px;
-            border: 3px solid black;
-            display: inline-block;
-            vertical-align:middle;
-            line-height: 22px;
-        }
-
-        .marker-city {
-            width: 30px;
-            height: 30px;
-            text-align: center;
-            line-height: 30px;
-            margin: -15px 0 0 -15px;
-        }
-
-        .marker-city div {
-            width: 10px;
-            height: 10px;
-            border-radius: 10px;
-            border: 1px solid black;
-            display: inline-block;
-            vertical-align:middle;
-        }
-
-        .marker-city span {
-            margin: -2px 0 0 15px;
-            display: inline-block;
-            text-align: left;
-            line-height: 15px;
-            vertical-align: top;
-        }
-
-        .cluster {
-        }
-
-        .cluster div {
-            min-width: 20px;
-            padding: 5px;
-            text-align: center;
-            border-radius: 15px;
-            font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
-        }
-
-        .cluster span {
-            /*line-height: 30px;*/
-        }
-
-        .cluster0 {
-            background-color: rgba(181, 226, 140, 0.6);
-        }
-
-        .cluster0  div {
-            background-color: rgba(110, 204, 57, 0.6);
-        }
-
-        .cluster1 {
-            background-color: rgba(241, 211, 87, 0.6);
-        }
-
-        .cluster1  div {
-            background-color: rgba(240, 194, 12, 0.6);
-        }
-    </style>
-</head>
-<body>
-    <h1>Leaflet Marker Clusters Test</h1>
-    <input id="radius" type="number" value="80" /><label for="radius">Radius</label>
-
-    <div id="map"></div>
-
-    <script src="data_usa.js"></script>
-
-    <script src="leaflet-src.js"></script>
-    <script src="leaflet.markercluster-src.js"></script>
-    <script src="leaflet.label-src.js"></script>
-    <script src="clustertest.js"></script>
-</body>
-</html>
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/leaflet-markercluster.git



More information about the Pkg-javascript-commits mailing list