Search code examples
leaflet

leaflet - 2nd map kills first?


Please help! I am trying to use leaflet to display a series of maps. I need to generate them dynamically, and so have been trying to do it with the l.map and l.tileLayer objects created as nodes of a container object.

That all works fine until I add a second map to the page. Each has unique "keys" in the container object, but as soon as the second map initalises it freezes the first one. I'm at a loss!

Here is a simplified version of the code:

`

    <div id="main"></div>

    <script>
        let mapObjects = {};
        
        createMap("main", "map1div", 500, 500, "map1", "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png");
        

// first map loads and works correctly whilse timeout below counts down

        setTimeout(function() {
            createMap("main", "map2div", 500, 500, "map2", "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png");
        }, 3000);

// but then the second map loads and only map2 works, map1 is frozen

        function createMap(parent, div, height, width, map, tiles) {
            let DIVHTML = "<div id='"+div+"' style='height: "+height+"px; width: "+width+"px;'></div>";
            document.getElementById(parent).innerHTML += DIVHTML;
            mapObjects[map] = L.map(div).setView([51.509865, -0.118092], 15);
            let t = map+"_tiles";
            mapObjects[t] = L.tileLayer(tiles, { maxZoom: 19,}).addTo(mapObjects[map]);
        };

    </script>
`

Or use this: https://codepen.io/Martyn-Hanmore/pen/XWOBEya


Solution

  • You are adding map containers by appending to the innerHTML property of a DOM node:

    document.getElementById(parent).innerHTML += DIVHTML;

    Let me quote from the documentation for innerHTML:

    Setting the value of innerHTML removes all of the element's descendants and replaces them with nodes constructed by parsing the HTML given in the string htmlString.

    (Re)setting the innerHTML property does, in fact, destroy all DOM nodes inside. By appending more HTML (using the += operator) you're essentially generating a string of HTML from the current DOM nodes, destroying the DOM nodes, then re-creating everything again.

    The (possibly not obvious) caveat is that the new nodes do not share event handlers with their old counterparts. Therefore, all the references that the Leaflet javascript had to any DOM elements are then left dangling.