Leaflet – Modifier un libellé dans le Popup d'un marker créé

Utiliser un textarea ou Input dans le popup d'un marker et l'associer au marker concerné

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je découvre leaflet et souhaite, lors de l’ajout d’un marker qu’une partie du Popup soit personnalisable, idéalement sans avoir besoin d’un bouton "Save".

Voici un code fonctionnel utilisant un input me permettant de personnaliser le contenu du popup.

Il pose problème faute de mémoriser le marker choisi. En effet, si on crée plusieurs marker (1 2 et 3) et qu’on choisi de personnaliser le marker 1 après validation du texte, c’est le dernier de la liste, le 3, qui s’actualise.

Bref comment procéder ?

Merci.

<!DOCTYPE html>
<html lang="fr">
  <head>
  <meta charset="utf-8" />
    <title>Leaflet Map</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
    <style>
      #map {
        width: 1000px;
        height: 500px;
      }
    </style>
  </head>

  <body>
    <div id="map"></div>
    <script>
      var map = L.map('map', {scrollWheelZoom:false}).setView([46.82, 2.9], 6);

      L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      }).addTo(map);

      WayPointsTrace = new L.LayerGroup();

      map.on("contextmenu", function (e) {
      addMarker(e);
      map.addLayer(WayPointsTrace);
      });

      function addMarker(e) {
      // Mémoriser position du marker
      event_Marker = e;
      Wpt_Name = '<b><input type="text" value="Etape NN" id="MyName"/> <input type="button" value="Save" OnClick="Update_Popup(event_Marker)"/>';
      var Google = '<a href="https://www.google.com/maps?q=' + e.latlng.lat + "," + e.latlng.lng + '&spn=0.05,0.05&t=h&om=1" target="_blank">';
      ItemPopup = Wpt_Name + "<br>" + e.latlng.lat.toFixed(6) + " - " + e.latlng.lng.toFixed(6) + "<br>" + Google + "Google Maps</a><br></b>";
      // création du marker sans Drag et Drop
      m = L.marker([e.latlng.lat, e.latlng.lng], {draggable: "false"}).bindPopup(ItemPopup);
      // Ajout de la propriété name
      m.data = {
      properties: { name: Wpt_Name }
      };
      // Attacher le marker au layerGroup
      m.addTo(WayPointsTrace);

      m.getPopup().on("click", function (e) {
	  
	  //  m.setLatLng(e.latlng);
	  
	  m.getPopup().setContent(ItemPopup);
      });
      }

      function Update_Popup(e) {
      Wpt_Name = document.getElementById("MyName").value;
      m.data.properties.name = Wpt_Name;
	  
      // *************************************** TEST CONSOLE *************************************
      console.log("1- data : " + m.data.properties.name);
      console.log("2- GetContent : " + m.getPopup().getContent());
      // ******************************************************************************************
	  
      m.closePopup();
      // Actualiser content
      var Google = '<a href="https://www.google.com/maps?q=' + e.latlng.lat + "," + e.latlng.lng + '&spn=0.05,0.05&t=h&om=1" target="_blank">';
      ItemPopup = Wpt_Name + "<br>" + e.latlng.lat.toFixed(6) + " - " + e.latlng.lng.toFixed(6) + "<br>" + Google + "Google Maps</a><br></b>";
      m.getPopup().setContent(ItemPopup);
      }
    </script>
  </body>
</html>

Bonjour,

La méthode la plus simple de faire ce que tu souhaite est de créer des element HTML via la code Javascript et d’ajouter un évènement sur ces éléments : Plus d’infos

Je vais également te donner quelques conseils comme tu sembles débuter en Javascript :

  • Utiliser des noms de variables plus clair (ex : marker à la place de m)
  • Utiliser des noms de variables en minuscules
  • Bien déclarer tes variables avec un var devant (exemple pour m qui n’est pas déclaré dans ton code (Si tu veux aller plus loin il est même préférable d’utiliser let et const à la place de var, plus d’infos)

Voici une proposition de correction qui semble fonctionner :

<!DOCTYPE html>
<html lang="fr">
  <head>
  <meta charset="utf-8" /> 
    <title>Leaflet Map</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
    <style>
      #map {
        width: 1000px;
        height: 500px;
      }
    </style>
  </head>

  <body>
    <div id="map"></div>
    <script>
      var map = L.map('map', {scrollWheelZoom:false}).setView([46.82, 2.9], 6);

      L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
		attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      }).addTo(map);

      WayPointsTrace = new L.LayerGroup();

      map.on("contextmenu", function (e) {
		  addMarker(e);
		  map.addLayer(WayPointsTrace);
      });

    function addMarker(e) {
		let m = L.marker([e.latlng.lat, e.latlng.lng], {draggable: "false"});

		// Création du text
		let input = document.createElement('input');
		input.value = "Etape NN";

		// Creation du bouton
		let btn = document.createElement('button');
		btn.innerText = 'Save';
		btn.onclick =  function() {
		  Update_Popup(e, m, input.value);
		}

		// Creation de l'élément contenu dans la pop-up
		let divElement = document.createElement('div');
		divElement.appendChild(input);
		divElement.appendChild(btn);

		m.bindPopup(divElement).openPopup();
			
		// Attacher le marker au layerGroup
		m.addTo(WayPointsTrace);

		m.getPopup().on("click", function (e) {
			m.getPopup().setContent(ItemPopup);
		});
    }

    function Update_Popup(e, marker, value)  {
		marker.closePopup();
		  
		// Actualiser content
		var Google = '<a href="https://www.google.com/maps?q=' + e.latlng.lat + "," + e.latlng.lng + '&spn=0.05,0.05&t=h&om=1" target="_blank">';
		ItemPopup = value + "<br>" + e.latlng.lat.toFixed(6) + " - " + e.latlng.lng.toFixed(6) + "<br>" + Google + "Google Maps</a><br></b>";
		marker.getPopup().setContent(ItemPopup);
    }
    </script>
  </body>
</html>

Bonjour sehvek,

Outre votre codage DOM, évident une fois proposé, un grand merci pour vos remarques concernant les types de variable dont j’avais zappée l’existence et dont je vais désormais abuser pour blinder le code !

En m’inspirant de votre code j’ai cherché à simplifier l’interface utilisateur via un textarea avec validation par la touche "enter", évitant un bouton.

Deux interrogations cependant :

1- Puis-je obtenir le focus sur input à l’ouverture du popup en DOM ou utiliser obligatoirement du CSS ?

2- Via le code source ci-dessous comment obtenir l’ouverture automatique du popup lors de l’ajout du marker ?

Et surtout un point de blocage :

3- Comment transformer l’objet [HTMLTextAreaElement] soit "divElement" en code html dans la variable ItemPopup ? Encadrer obligatoirement le contenu ItemPopup dans un div id=xxx ?

Disposer d’un information complète dans le popup (Libellé, latitude / longitude et lien Google) lors de l’ajout et le conserver pour autoriser une correction du nom du marker, y compris après un Drag in Drop, tans que ce dernier n’a pas été modifié…

Merci par avance et mes excuses pour abuser de votre partage de connaissance.

<!DOCTYPE html>
<html lang="fr">
  <head>
    <meta charset="utf-8" />
    <title>Leaflet Map</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
    <style>
      #map {
        width: 1000px;
        height: 500px;
      }
      textarea {
        resize: none;
      }
    </style>
  </head>

  <body>
    <div id="map"></div>
    <script>
      var map = L.map("map", { scrollWheelZoom: false }).setView([46.82, 2.9], 6);

      L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
        attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
      }).addTo(map);

      WayPointsTrace = new L.LayerGroup();

      map.on("contextmenu", function (e) {
        addMarker(e);
        map.addLayer(WayPointsTrace);
      });

      function addMarker(e) {
        let m = L.marker([e.latlng.lat, e.latlng.lng], { draggable: "false" });
        m.feature = {
          properties: { name: "Etape NN" },
        };

        let input = document.createElement("textarea");
        input.value = "Etape NN";
        // input.resize = "none";
        input.style.border = "none";
        input.style.color = "red";
        input.maxLength = "30";
        input.cols = "19";
        input.rows = "1";

        // Creation de l'élément contenu dans la pop-up
        let divElement = document.createElement("div");
        divElement.appendChild(input);
        console.log(divElement);
        // input.focus();

        input.addEventListener("input", function handleChange(event) {
          // console.log("value : " + event.target.value);
          event.target.addEventListener("keydown", (event) => {
            // console.log("event.keyCode : " + event.keyCode);
            if (event.isComposing || event.keyCode === 13) {
              Update_Popup(e, m, input.value);
              return;
            }
          });
        });

// ********************** Comment insérer HTML du divElement dans ItemPoup ***********************
// ***********************************************************************************************
        // m.bindPopup(divElement).openPopup(); // ==> Ne provoque pas l'ouverture du popup après ajout du marker !

        let Google = '<a href="https://www.google.com/maps?q=' + e.latlng.lat + "," + e.latlng.lng + '&spn=0.05,0.05&t=h&om=1" target="_blank">';
        let ItemPopup = divElement + "<br>" + e.latlng.lat.toFixed(6) + " - " + e.latlng.lng.toFixed(6) + "<br>" + Google + "Google Maps</a><br></b>";

        m.bindPopup(ItemPopup);
// ***********************************************************************************************
// ***********************************************************************************************

        // Attacher le marker au layerGroup
        m.addTo(WayPointsTrace);

        m.getPopup().on("click", function (e) {
          m.getPopup().setContent(ItemPopup);
        });

        // Détection de fin de Drag et Drop du marqueur
        m.on("dragend", function (e) {
          // Actualiser contenu popup du marker
          let Google = '<a href="https://www.google.com/maps?q=' + e.target.getLatLng().lat + "," + e.target.getLatLng().lng + '&spn=0.05,0.05&t=h&om=1" target="_blank">';
          let ItemPopup = "<b>" + m.feature.properties.name + "<br>" + e.target.getLatLng().lat.toFixed(6) + " - " + e.target.getLatLng().lng.toFixed(6) + "<br>" + Google + "Google Maps</a><br></b>";
          m.getPopup().setContent(ItemPopup);
        });
      }

      function Update_Popup(e, marker, value) {
        marker.closePopup();
        marker.feature = {
          properties: { name: value },
        };
        // Actualiser content
        let Google = '<a href="https://www.google.com/maps?q=' + e.latlng.lat + "," + e.latlng.lng + '&spn=0.05,0.05&t=h&om=1" target="_blank">';
        let ItemPopup = value + "<br>" + e.latlng.lat.toFixed(6) + " - " + e.latlng.lng.toFixed(6) + "<br>" + Google + "Google Maps</a><br></b>";
        marker.getPopup().setContent(ItemPopup);
      }
    </script>
  </body>
</html>

+0 -0

Aucun problème, le forum est fait pour poser des questions :

1- Il suffit de faire un focus sur ton input lors du click sur le marker, mais ça ne fonctionne que si l’input n’est pas transformé en HTML (sinon il faut le récupérer via un id unique) :

m.on('click', function(event) {
	input.focus();
});

2- Utiliser m.openPopup(); à la fin de la méthode marker (par contre je ne comprends pas pourquoi ça ne fonctionne qu’à partir du second marker

3- divElement.innerHTML pour le récupérer sous forme de contenu HTML, mais je te conseille de passer toutes tes informations sous forme d’élément HTML (document.createElement), et de mettre à jour le contenu via la propriété divElement.innerHTML.

Bonsoir,

Encore un grand merci pour vos conseils et votre patience. A charge de revanche sur ce forum.

3- Aveuglé par les mots clef leaflet, un classique innerHTML ne m’était même pas venu à l’idée !

Excellente fin de journée et bonnes fêtes à venir pour vous et votre famille !

Sujet considéré résolu !

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte