Home > OS >  Google maps API use dragend to update one of multiple markers
Google maps API use dragend to update one of multiple markers

Time:05-18

I'm using google maps API with multiple equipment locations fed from a Mysql database. I can successfully show the markers on the map and make them draggable. If I drag any marker to a new location, it prompts to ask if you want to update the database and if yes, supposedly sends the updated lat/lng to the database. This isn't working correctly, and instead always only updates the last item in the markers array.

Note that I have done this successfully with a single marker, and am able to update it anywhere I drag the new marker. But for multiple markers, I just don't seem to be able to get the current dragged marker's id and new lat/lon data to send back to the ajax call to update the database for that particular marker. I'm thinking it's because I'm not accessing the current marker's data, but I'm struggling with how to get that.

Any ideas what I'm doing wrong? I know it's got to be something simple I'm overlooking.

Here's a Fiddle to demonstrate my issue: JSFiddle

<!-- php stuff would be up here to get the database and feed the google API.    Instead here I've just created the const markers to show the markers. -->

<html>

  <head>
    <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAgc6RYO3zsMBE6QVKjkTU-UQ3XhpK0s2A&callback=initMap"></script>
  </head>

  <body>
    <div id="mapCanvas"></div>
  </body>

</html>
<style>#mapCanvas {
    width: 100%;
    height: 850px;
  }
  
  </style>

<script>
function initMap() {
  var map;
  var bounds = new google.maps.LatLngBounds();
  var mapOptions = {
    mapTypeId: 'hybrid'
  };


  // Display a map on the web page
  map = new google.maps.Map(document.getElementById("mapCanvas"), mapOptions);
  map.setTilt(100);

  // Multiple markers location, latitude, and longitude
  const mapIcon = "https://maps.google.com/mapfiles/marker_grey.png";
  const markers = [
    ['Pike-1', 35.42526738862006, -81.172076628969, mapIcon, 10819],
    ['Pike-2', 35.425311504805924, -81.17216095766817, mapIcon, 10820],
    ['Pike-3', 35.425171475622824, -81.17188553479076, mapIcon, 10821],
    ['Pike-4', 35.42530668524588, -81.17134696588283, mapIcon, 10822],
    ['Pike-5', 35.42559347700399, -81.17218140606506, mapIcon, 10823],
    ['Pike-5', 35.426094498781885, -81.17195101338058, mapIcon, 26455],
    ['Pike-6', 35.42532308059036, -81.17215505637606, mapIcon, 26456]
  ];


  // Place each marker on the map  
  for (i = 0; i < markers.length; i  ) {
    var position = new google.maps.LatLng(markers[i][1], markers[i][2]);
    var eid = markers[i][4];
    bounds.extend(position);
    marker = new google.maps.Marker({
      position: position,
      map: map,
      draggable: true,
      animation: google.maps.Animation.DROP,
      icon: markers[i][3],
      equipid: markers[i][4],
      title: markers[i][0]
    });



    //Add listener if marker is moved, then ask to update and call function if yes.
    google.maps.event.addListener(marker, 'dragend', function() {
      var mytitle = marker.equipid;
      var latLng = marker.latLng;

      let updateDB = confirm('Update location to database?');
      if (updateDB) {
        update_marker(latLng, mytitle);
        console.log(latLng, mytitle);
      }
    });





    // Center the map to fit all markers on the screen
    map.fitBounds(bounds);

    function update_marker(Marker, mytitle)
    //This is the function that sends the update to the ajax call.  Currently not working.
    //with multiple markers, I can't get the selected marker equipment ID and new lat/lng.
    {
      //Update saved marker from DB and map using jQuery Ajax
      var mLatLang = marker.getPosition().toUrlValue(); //get marker position - this does not get the marker position, but the last row of the result set from mysql
      var mytitle = marker.equipid; //get marker equipment id - this currently gets the last row[id] of the mysql result set.
      var myData = {
        update: 'true',
        name: mytitle,
        latlang: mLatLang
      };
      $.ajax({
        type: "POST",
        url: "equipment-ajaxupdate-gps.php",
        data: myData,
        success: function(data) {
          alert(data);
          console.log(mytitle, mLatLang);
        },
        error: function(xhr, ajaxOptions, thrownError) {
          alert("Error! Update Failed!")
          console.log(mytitle, mLatLang);
        }
      });
    }


  } //end of for( i = 0)

  // Set zoom level
  var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
    this.setZoom(19);
    google.maps.event.removeListener(boundsListener);
  });


} //End of function(initmap)



// Load initialize function
google.maps.event.addDomListener(window, 'load', initMap);


</script>

CodePudding user response:

I made a few changes to your code - this seems to work OK as it sends the correct details via the ajax call so updating the db should be trivial from that point forth.

With the script tag that loads the Google Maps api you specify the callback function so there is no need to then manually call initMap function as you are with google.maps.event.addDomListener(window, 'load', initMap);

The update_marker function can be simplified to use a single argument that is the reference to the marker itself. This greatly simplifies accessing properties of the marker itself as you can see below where self is used within the function ( could be any name - it is a reference to the marker )

Rather than the clunky for (i = 0; i < markers.length; i ) { loop to iterate through the array elements a simpler forEach loop means you no longer need to use the name[i][2] type syntax - though if the actual data is coming from your db you'll likely be using JSON anyway which would necessitate a different loop strategy.

<?php
    if( $_SERVER['REQUEST_METHOD']=='POST' && isset(
        $_POST['update'],
        $_POST['name'],
        $_POST['latlang']
    )){
        
        $_POST['date']=date( DATE_RSS );
        $payload=json_encode( $_POST );
        
        
        exit( $payload );
    }
?>
<html>
    <head>
        <style>
            #mapCanvas {
                width: 100%;
                height: 850px;
            }
        </style>
        <script src='//code.jquery.com/jquery-latest.js'></script>
    </head>
    <body>
        <div id="mapCanvas"></div>
        <script>
            function initMap() {
                var map;
                var bounds = new google.maps.LatLngBounds();
                var mapOptions = {
                    mapTypeId:'hybrid'
                };
                map = new google.maps.Map( document.getElementById("mapCanvas"), mapOptions );
                map.setTilt(100);


                const mapIcon = "https://maps.google.com/mapfiles/marker_grey.png";
                const markers = [
                    ['Pike-1', 35.42526738862006, -81.172076628969, mapIcon, 10819],
                    ['Pike-2', 35.425311504805924, -81.17216095766817, mapIcon, 10820],
                    ['Pike-3', 35.425171475622824, -81.17188553479076, mapIcon, 10821],
                    ['Pike-4', 35.42530668524588, -81.17134696588283, mapIcon, 10822],
                    ['Pike-5', 35.42559347700399, -81.17218140606506, mapIcon, 10823],
                    ['Pike-6', 35.426094498781885, -81.17195101338058, mapIcon, 26455],
                    ['Pike-7', 35.42532308059036, -81.17215505637606, mapIcon, 26456]
                ];


                // Place each marker on the map. 
                // A forEach loop is, IMO, cleaner than the for(i=0;i<n;i  ) {} etc
                markers.forEach(a=>{
                    let title=a[0];
                    let latlng=new google.maps.LatLng( a[1], a[2] );
                    let icon=a[3];
                    let eid=a[4];
                    
                    let marker=new google.maps.Marker({
                        position: latlng,
                        map: map,
                        draggable: true,
                        animation: google.maps.Animation.DROP,
                        icon:icon,
                        /* custom properties */
                        equipid:eid,
                        title:title             
                    });
                    bounds.extend( latlng );
                    
                    google.maps.event.addListener( marker, 'dragend', function(e) {
                        if( confirm('Update location to database?') ) {
                            /*
                                Within the context of this function `this` refers
                                to the marker itself that invoked the event handler.
                                
                                Passing `this` as the function parameter to `update_marker`
                                allows us to access all properties of the marker from
                                within that function.
                                
                                As the marker has been assigned custom properties when it was
                                added to the map we can access those easily within `update_marker`
                                
                            */
                            update_marker( this );
                            console.log('Update - Position:%s, Title:%s', this.getPosition().toUrlValue(), this.title );
                        }
                    });
                    
                    function update_marker( self ){
                        /*
                            self is the marker reference
                        */
                        $.ajax({
                            type:"POST",
                            url:location.href,  //"equipment-ajaxupdate-gps.php"
                            data: {
                                update:'true',
                                name:self.title,
                                latlang:self.getPosition().toUrlValue()
                            },
                            success: function( response ) {
                                console.log( 'Ajax response: %o',response );
                                bounds.extend( latlng );
                                map.fitBounds( bounds );
                            },
                            error: function( error ) {
                                alert( "Error! Update Failed!\n" error )
                            }
                        });
                    };
                    
                });//end forEach loop
                
                map.fitBounds( bounds );
            }
        </script>
        <script async defer src="https://maps.googleapis.com/maps/api/js?key=APIKEY&callback=initMap"></script>
    </body>
</html>
  • Related