Search code examples
imageleafletpopuppreload

Preloading Images into Leaflet Popup


I'm currently adding some popups to my leaflet map of tourist destinations within a country. The popups will have a title, image and wiki link. I want to check that the images are available and preload them. I've succeeded in all of this, but now I don't know how to insert the preloaded images into the popup.

Here is my code:

var tourists = result.tourists.geonames;

        var images_urls = [];

        for (let i in tourists) {
            $.get(tourists[i].thumbnailImg)
                .done(function () {
                    images_urls.push(tourists[i].thumbnailImg);
                }).fail(function () {
                    images_urls.push("libs/css/image/wiki.png");
                })
            
        }

        var images = [];

        function preload(arguments) {
            for (var i = 0; i < arguments.length; i++) {
                images = new Image();
                images.src = arguments[i];
            }
        }

        preload(images_urls);
       

        for (let i in tourists) { 
            markers.addLayer(
                L.marker([tourists[i].lat, tourists[i].lng], { icon: touristIcon })
                    .bindPopup(`<b>${tourists[i].title}</b> <br> INSERT PRELOADED IMAGES <br> <a href="https://${tourists[i].wikipediaUrl}" target="_blank" >Wikipedia Article<a> <br>`)
            )
        }

Solution

  • I finally figured out the problem! I needed to construct the popup before I bound it to the marker! So here is the code to check the URL works and then to preload the image.

    function preloadImage(url, width, height) {
      var img = new Image(width, height);
      img.src = url;
      return img;
    }
    
    function checkImage(imageSrc, backup, width, height) {
      var http = new XMLHttpRequest();
    
      http.open('HEAD', imageSrc, true);
      http.send();
    
      if (http.status != 404) {
          return preloadImage(imageSrc, width, height)
      } else {
          return preloadImage(backup, width, height)
        }
    }
    

    Here is how to construct the popup:

     var tourists = result.tourists.geonames;
    
            for (let i in tourists) {
    
                var popup = document.createElement('div');
                var br = document.createElement('br');
                var picture_popup = checkImage(tourists[i].thumbnailImg, 'libs/css/image/wiki.png', 120, 100);
                var a = document.createElement('a');
                var linkText = document.createTextNode(tourists[i].title);
                a.appendChild(linkText);
                a.title = 'Wikipedia article';
                a.target = '_blank';
                a.href = 'https://' + tourists[i].wikipediaUrl;
    
                popup.appendChild(picture_popup);
                popup.appendChild(br);
                popup.appendChild(a);
    
                markers.addLayer(
                    L.marker([tourists[i].lat, tourists[i].lng], {
                        icon: touristIcon
                    })
                        .bindPopup(popup)
                )
            }
    

    The only issue with it now is the relative backup URL not functioning, but it's basically there!