• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

[GELÖST] Bitte um Hilfe bei JavaScript Closure

fronk

New member
Liebes Forum,
ich bin ganz neu hier und erbitte hiermit Eure Hilfe. JavaScript ist im Großen und Ganzen leider noch ein Buch mit sieben Siegeln für mich. Ich bin eher in HTML und CSS zu Hause. Allerdings ist es nun für eines meiner Projekte nötig, eine Funktionalität mit JavaScript auszuführen.

Worum geht es? Es soll eine Web-App erstellt werden, welche mittels Google Maps die Position des Besuchers und einige vorher in einem JSON-Dokument festgelegte Orte und dazu einige zusätzliche Informationen per Pin anzeigen. Beim Klick auf den Pin sollen dann also die Zusatzinfos per Info-Fenster angezeigt werden. Hinten dran hängt dann auch noch eine kleine Entfernungsberechnung, die gibt den Abstand vom aktuellen Standort zu den festgelegten Punkten an. Den bisherigen Code habe ich von einem Lehr-Buch übernommen und soweit angepasst, dass er auf mein Projekt passt. Bisher funktioniert das Meiste auch ganz gut. Alle Standorte werden angezeigt usw. Allerdings werden in jedem der Infofenster immer nur die Daten des letzten Standortes aus dem JSON-Dokument angezeigt. Recherchen meinerseits haben nun ergeben, dass man dies durch ein »JavaScript Closure« beheben muss. Nun habe ich aber absolut keinen Schimmer, wie ich diesen bei meinem Beispiel realisieren muss. Auch versuche generell ein »Closure« zu verstehen, sind bisher nicht so ganz erfolgreich gewesen. Daher meine Bitte, ich würde hier gern mal den Quelltext posten in der Hoffnung, dass mir eventuell jemand die hoffentlich wenigen Zeilen Code ergänzen würde. Ein paar Code-Krümel eines Versuchs von einer anderen Website sind noch im Code drinnen. Leider haben die nicht wirklich funktioniert.

Hier nun der Quellcode:

HTML:
<!DOCTYPE html>
<html lang="de">
  <head>
    <title>Weihnachtsfest Frauenfeld</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="stylesheet" href="css/ratchet.min.css">
 
    <script type="text/javascript">
		window.scrollTo(0,1);
	</script>
  </head>
  <body>
    <div class="segmented-control">
      <nav class="bar bar-tab">
        <a class="tab-item control-item active" href="#karte">
          <span class="icon icon-home"></span>
<!--          <span class="tab-label">Karte</span>
-->        </a>
        <a class="tab-item control-item" href="#liste">
          <span class="icon icon-info"></span>
          <span class="tab-label">Erläuterungen</span>
        </a>
      </nav>
    </div>
    <div class="content">
      <div id="karte" class="karte control-content active">
        <div class="google-karte" id="google-karte"></div>
      </div>
      <div class="card control-content" id="liste">
        <ul class="table-view" id="standort_list">
      		<!-- Hier kommt die Standort-Liste rein -->
        </ul>
      </div>

    
    <script src="js/segmented-controllers.js"></script>
    <script src="js/toggles.js"></script>
    <script>
      var karte;
      var marker;
      var myLongitude, myLatitude;
		var myLon, myLat;
      
      var showPosition = function(position){
		
        width = document.querySelector('#google-karte').offsetWidth;
        height = document.querySelector('#google-karte').offsetHeight;

        myLongitude = position.coords.longitude;
        myLatitude = position.coords.latitude;
		  
		//myLon = position.coords.longitude;
        //myLat = position.coords.latitude; 
		 
        var options = { //Maps-Optionen
          zoom: 14,
          center: new google.maps.LatLng(myLatitude, myLongitude),
			//scrollwheel: false,
          mapTypeId: google.maps.MapTypeId.ROADMAP,
			
			disableDefaultUI: true, // blendet alle Google-Bedienungs-Elemente aus
        	
        };
        		  		
		  
        karte = new google.maps.Map(document.querySelector('#google-karte'), options);
        loadStandorte();
      };
      // Mögliche Labels für die Marker
		var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
      	var labelIndex = 0;
		
      var loadStandorte = function(){
        var standort_list = document.querySelector('#standort_list');
        standort_list.innerHTML = '';

        request = new XMLHttpRequest();
        request.open('get','daten/standort.json',true);
        request.send();
        
		marker0 = new google.maps.Marker({ // Zeigt den aktuellen Standort an
             position: new google.maps.LatLng(myLatitude, myLongitude),
			  map: karte,
			  icon: "rot.png",
			 opacity:0.75,
			 title:"Aktueller Standort",
			// This marker is 20 pixels wide by 32 pixels high.
    		//size: new google.maps.Size(20, 32),
            });
		 
		  var infoWindow0 = new google.maps.InfoWindow({
			content: '<div id="content"><h4>Ihr aktueller Standort</h4></div>'
        });
		
		google.maps.event.addListener(marker0, 'click', function() {
			infoWindow0.open(marker0.get('map'), marker0);
       });
		  
		  // Creating a global infoWindow object that will be reused by all markers
		  var infoWindow = new google.maps.InfoWindow();  
		
		 // Looping through the JSON data
         request.addEventListener('load',function(){
           var data = JSON.parse(this.response);
          for(standort in data){
            standort_list.insertAdjacentHTML('beforeend','<li class="table-view-cell media '+data[standort]+'"><div class="media-body">'+standort+'<br><p><img src="'+data[standort].Icon+'"/></p><p>'+data[standort].Beschreibung+'<br>Bis hier sind es '+calculateDistance(myLongitude,myLatitude,data[standort].Position.Longitude,data[standort].Position.Latitude)+' zu gehen.</p></div></li>');
          			  
			  // Creating a marker and putting it on the map
			  var marker = new google.maps.Marker({
					map: karte,
					icon:(data[standort].Icon),
					content:(data[standort].Beschreibung),
					animation: google.maps.Animation.DROP,
					opacity:0.75,
					position: new google.maps.LatLng(data[standort].Position.Latitude,data[standort].Position.Longitude),
				  //label: labels[labelIndex++ % labels.length],
					title:(data[standort].Titel)
			  });
			  
		// Creating a closure to retain the correct data 
		//Note how I pass the current data in the loop into the closure (marker, data)
						  
			  (function(marker, data) {

			  // Attaching a click event to the current marker
			  google.maps.event.addListener(marker, "click", function(e) {
					infoWindow.setContent(data[standort].Beschreibung);
					infoWindow.open(karte, marker);
			  });

		})(marker, data);	  

		  } //Ende Loop
        });
      };
      		
      var calculateDistance = function(myLongitude, myLatitude, long1, lat1) {
        erdRadius = 6371;

        myLongitude = myLongitude * (Math.PI/180);
        myLatitude = myLatitude * (Math.PI/180);
        long1 = long1 * (Math.PI/180);
        lat1 = lat1 * (Math.PI/180);

        x0 = myLongitude * erdRadius * Math.cos(myLatitude);
        y0 = myLatitude  * erdRadius;

        x1 = long1 * erdRadius * Math.cos(lat1);
        y1 = lat1  * erdRadius;

        dx = x0 - x1;
        dy = y0 - y1;

        d = Math.sqrt((dx*dx) + (dy*dy));

        if(d < 1) {
          return Math.round(d*1000)+" m";
        } else {
          return Math.round(d*10)/10+" km";
        }
      };
            
      navigator.geolocation.getCurrentPosition(showPosition);
    </script>
        <script async defer src="https://maps.googleapis.com/maps/api/js?key=meinKey">
    </script>
</div>
  </body>
</html>

Wie schon geschrieben, über Hilfe würde ich mich sehr freuen.

Mit freundlichen Grüßen
fronk
 
Zuletzt bearbeitet von einem Moderator:
Code:
	// Creating a closure to retain the correct data
	//Note how I pass the current data in the loop into the closure (marker, data)
	(function(marker, data) {
		// Attaching a click event to the current marker
		google.maps.event.addListener(marker, "click", function(e) {
			infoWindow.setContent(data[standort].Beschreibung);
			infoWindow.open(karte, marker);
		});
	})(marker, data);
Der Ansatz ist nicht schlecht, aber du muss data[standort] oder gleich data[standort].Beschreibung an die Funktion übergeben, oder zusätzlich auch noch standort, da letzteres eigentlich das Problem erzeugt:
Code:
	google.maps.event.addListener(marker, "click", function(karte, marker, beschreibung){
		return function(e){
			infoWindow.setContent(beschreibung);
			infoWindow.open(karte, marker);
		}
	}(karte, marker, data[standort].Beschreibung));
- ungetestet.
 
Zuerst einmal vielen Dank für Deine Mühe. Merkwürdigerweise bekomme ich jetzt folgenden Fehler in der Console angezeigt: SyntaxError: Unexpected token '}'. Expected ')' to end a compound expression.

Der Code des Loops sieht jetzt so aus:

HTML:
// Looping through the JSON data
         request.addEventListener('load',function(){
           var data = JSON.parse(this.response);
          for(standort in data){
            standort_list.insertAdjacentHTML('beforeend','<li class="table-view-cell media '+data[standort]+'"><div class="media-body">'+standort+'<br><p><img src="'+data[standort].Icon+'"/></p><p>'+data[standort].Beschreibung+'<br>Bis hier sind es '+calculateDistance(myLongitude,myLatitude,data[standort].Position.Longitude,data[standort].Position.Latitude)+' zu gehen.</p></div></li>');
          			  
			  // Creating a marker and putting it on the map
			  var marker = new google.maps.Marker({
					map: karte,
					icon:(data[standort].Icon),
					content:(data[standort].Beschreibung),
					animation: google.maps.Animation.DROP,
					opacity:0.75,
					position: new google.maps.LatLng(data[standort].Position.Latitude,data[standort].Position.Longitude),
				  //label: labels[labelIndex++ % labels.length],
					title:(data[standort].Titel)
			  });
			  
		// Creating a closure to retain the correct data 
		//Note how I pass the current data in the loop into the closure (marker, data)
						  
			  (function(marker, data) {

			  // Attaching a click event to the current marker
			  google.maps.event.addListener(marker, "click", function(karte, marker, beschreibung){
		return function(e){
			infoWindow.setContent(beschreibung);
			infoWindow.open(karte, marker);
		}
	}(karte, marker, data[standort].Beschreibung));	  

	  } //Ende Loop
        });
      };

Und zwar wird die Zeile direkt unter dem Hinweis »Ende Loop« bemängelt?
 
Oh, ganz großes Tennis, jetzt funktioniert es! Vielen herzlichen Dank für die Hilfe!

Mit freundlichen Grüßen
fronk
 
Zurück
Oben