• How do I loop through my wordpress custom post type (locations) and generate google map api markers for each post. I’m really bad at js syntax so any help would be greatly appreciated.

    Here is what I have so far

    <section class="businessMap">
      <div id="map1" class="">
      </div><!-- close map -->
    </section>
    
    <?php 
     
      $centeredLatitude = "39.18624"; 
      $centeredLongitude = "-75.53448";
    
      $args = array( 
        'orderby' => 'title',
        'order' => 'ASC',
        'post_type' => 'location', 
        'posts_per_page'=>-1
        );
      
      $locations = new WP_Query( $args );
    
      if( $locations->have_posts() ) {
    
         $markers = "";
    
        while( $locations->have_posts() ) {
          $location->the_post();
          $location_name = get_field('location_name');
          $address = get_field('address');
          $latitude = get_field('latitude');
          $longitude = get_field('longitude');
          $link = get_permalink();
          
          // create map marker for each location in the loop
          $markers .= "
    
            {
              'title': '".$location_name."',
              'lat': '".$latitude."',
              'lng': '".$longitude."',
              'description': '".$address."',
              'link': '".$link."',
              'icon': logo
            },
            ";
    
        } // end while
      } // end if
    
    ?>
    
      <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAbBq6dIV44bXUu32r_Me98cA1GpEib4_8"></script>       
      <script type="text/javascript">
    
          var mapStyles= [];
    
          // When the window has finished loading create our google map below
              google.maps.event.addDomListener(window, 'load', init);
    
              function init() {
                 
                  var mapOptions1 = {
                    zoom: 12,
                    center: new google.maps.LatLng(<?php echo $centeredLatitude; ?>, <?php echo $centeredLongitude; ?>),
                    styles: mapStyles
                  };
    
                  var mapElement1 = document.getElementById('map1');
    
                  var map1 = new google.maps.Map(mapElement1, mapOptions1);
                  var logo = "../logo.png";
    
                  var marker = new google.maps.Marker({
                      position: new google.maps.LatLng(<?php echo $latitude; ?>, <?php echo $longitude; ?>),
                      map: map1,
                      title: "Location Name",
                      icon: logo
                  });
    
                  marker.setMap(map1);
              }
      </script> 
    
    • This topic was modified 3 years, 3 months ago by aaron4osu.
    • This topic was modified 3 years, 3 months ago by Jan Dembowski.
Viewing 11 replies - 1 through 11 (of 11 total)
  • Moderator bcworkz

    (@bcworkz)

    Bear in mind you’re using PHP running server side to generate inline JavaScript that will run client side. PHP has to supply all needed data in its output. Avoid any need for any further interaction, like JS needing more PHP data after it starts executing.

    Place your PHP loop where you’re currently creating the one marker with new google.maps.Marker(). Be sure to manage the <?php ?> tags correctly. The PHP loop would output the necessary new marker code each time through the loop, using the current location post’s data to assign appropriate values the new marker code needs.

    The resulting output would be inline JS code with several new marker code blocks in sequence. Each block has the unique values generated from one pass through the PHP loop.

    BTW, you don’t really need to do an assignment to $markers. Just use the intermediate variables like $location_name to directly output related JS code like title: "<?php echo $location_name; ?>,".

    Your query is not correct. What i assume is that the Google map would load with a “Center co-ordinate” and a map radius of lets say 5 km.
    So based on the map radius defined, you have write the WP Query with meta query, assuming that latutide is saved in a meta key and lngitude is saved n another meta key. Similar to this.

    new WP_Query(array(
    'post_type'=>'location',
    'posts_per_page'=>999,
    'meta_query'=>array(
        'relation'=>'AND'
        array(
            'key'=>'longitude'
            'value'=>(23.009,42.009), //based on your calculation of the radius,
            'compare'=>'BETWEEN'
        ),
        

    array(
    ‘key’=>’latitude’
    ‘value’=>(23.009,42.009), //based on your calculation of the radius,
    ‘compare’=>’BETWEEN’
    ),`
    ));`

    Thread Starter aaron4osu

    (@aaron4osu)

    @bcworkz I rebuilt the init map function with the wordpress loop where the markers are being generated. I also updated the entire init map function with a current example from Google Maps API using the new google.maps.Marker() function. However I’m gettin getting this error
    Unhandled Promise Rejection: InvalidValueError: initMap is not a function:

    If I pull out everything inside the // get location posts and replace with a static new google.maps.Marke

    var marker = new google.maps.Marker({
          position: { lat:<?php echo $centeredLatitude; ?>, lng: <?php echo $centeredLongitude; ?>  },
          map,
          icon: image,
        });
    

    it works fine. So it seems like the init function doesn’t like being interrupted with the php loop? Any ideas?

    Here is what I have now

    
     // center map around this location - hard coded for now. 
      $centeredLatitude = "39.18624"; 
      $centeredLongitude = "-75.53448";
    ?>     
    <script type="text/javascript">
    
      var mapStyles= [];
    
      function initMap() {
    
      
        const map = new google.maps.Map(document.getElementById("map"), {
          zoom: 4,
          center: { lat:<?php echo $centeredLatitude; ?>, lng: <?php echo $centeredLongitude; ?> },
          styles: mapStyles,
        });
        
        const image ="path-to-image.png";
    
       
        <?php 
          // get location posts
          $args = array( 
            'orderby' => 'title',
            'order' => 'ASC',
            'post_type' => 'location', 
            'posts_per_page'=>-1
            );
          
          $locations = new WP_Query( $args );
       
          if( $locations->have_posts() ) {
            // looop through each location and create marker
            while( $locations->have_posts() ) {
              $location->the_post();
              $location_name = get_field('location_name');
              $latitude = get_field('latitude');
              $longitude = get_field('longitude');
              ?>
    
             var marker = new google.maps.Marker({
               position: { lat:<?php echo $latitude; ?>, lng: <?php echo $longitude; ?> },
                map,
                icon: image,
              });
    
        <?php 
            } // end while
          } // endif 
           // end get location posts
        ?>
    
      }// end initMap()
    
    </script>

    `

    • This reply was modified 3 years, 3 months ago by aaron4osu.
    • This reply was modified 3 years, 3 months ago by aaron4osu.
    Moderator bcworkz

    (@bcworkz)

    The JS is not interrupted by PHP. PHP should have already been run and is done when JS executes. Don’t forget server code vs. client code. All that’s left of PHP is the JS marker code it had generated. Whatever is calling initMap() is likely executing before the function declaration had fully loaded. It must wait until the document has loaded before starting.
    window.onload = initMap;

    Thread Starter aaron4osu

    (@aaron4osu)

    Thanks @bcworkz. where do I put window.onload = initMap; ? I tried right after the closing bracket from initMap() {...}

    Here is the error
    Unhandled Promise Rejection: InvalidValueError: initMap is not a function

    here is the current script. I have a test marker in there as well. If I pull out the php post loop the map loads and the marker is there.

    <script type="text/javascript">
    
      var mapStyles= [];
    
      function initMap() {
    
        <?php 
          $latitude = "39.18624"; 
          $longitude = "-74.53448";
          $centeredLatitude = "39.18624"; 
          $centeredLongitude = "-75.53448";
        ?> 
    
        const map = new google.maps.Map(document.getElementById("map"), {
          zoom: 4,
          center: { lat:<?php echo $centeredLatitude; ?>, lng: <?php echo $centeredLongitude; ?> },
          styles: mapStyles,
        });
        
        const image ="footer-fish-icon-110.png";
    
        var marker = new google.maps.Marker({
          position: { lat:<?php echo $latitude; ?>, lng: <?php echo $longitude; ?> },
          map,
          icon: image,
        });
    
        <?php 
    
          $args = array( 
            'orderby' => 'title',
            'order' => 'ASC',
            'post_type' => 'location', 
            'posts_per_page'=>-1
            );
          
          $locations = new WP_Query( $args );
       
          if( $locations->have_posts() ) {
            // looop through each location and create marker
            while( $locations->have_posts() ) {
              $location->the_post();
              $location_name = get_field('location_name');
              $latitude = get_field('latitude');
              $longitude = get_field('longitude');
              ?>
    
              var marker = new google.maps.Marker({
                position: { lat:<?php echo $latitude; ?>, lng: <?php echo $longitude; ?> },
                map,
                icon: image,
              });
    
        <?php 
            } // end while
          } // endif 
        ?>
    
      }
    
      window.onload = initMap;
    
    </script>
    

    here is the output

    <script type="text/javascript">
    
      var mapStyles= [];
    
      function initMap() {
    
        const map = new google.maps.Map(document.getElementById("map"), {
          zoom: 4,
          center: { lat:39.18624, lng: -75.53448 },
          styles: mapStyles,
        });
        
        const image ="https://eatpokebros.com/wp-content/themes/poke-signal-theme/assets/img/footer-fish-icon-110.png";
    
        var marker = new google.maps.Marker({
          position: { lat:39.18624, lng: -75.53448 },
          map,
          icon: image,
        });
    
        var marker = new google.maps.Marker({
          position: { lat:39.18624, lng: -75.53448  },
          map,
          icon: image,
        });
    
        <!DOCTYPE html>
    <html lang="en-US">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta name="viewport" content="width=device-width">
            <meta name='robots' content='noindex, follow' />
        <title>WordPress &rsaquo; Error</title>
        <style type="text/css">...</style>
    </head>
    <body data-rsssl=1 id="error-page">
        <div class="wp-die-message"><p>There has been a critical error on this website.</p><p><a href="https://www.ads-software.com/support/article/faq-troubleshooting/">Learn more about troubleshooting WordPress.</a></p></div></body>
    </html>
        </script>
    Moderator bcworkz

    (@bcworkz)

    Calling initMap like that should be fine.

    There’s a PHP error: undefined variable $location after the while(): loop is initiated. You should have:
    $locations->the_post();
    ($locations plural, not singular)

    You would have likely found this yourself if you had WP_DEBUG defined as true in wp-config.php. ?? Just be sure to restore it to false when you’re done coding. Leaving it as true slightly decreases your site’s security.

    Thread Starter aaron4osu

    (@aaron4osu)

    Thanks @bcworkz! that fixed it. So Ive got the markers added to the map and I’m trying to add an event listener and info window popup to each marker to display a phone number and link to the that location. The problem when you click any of the 40+ markers it’s popping up the same marker regardless of which marker you click on. and it’s the last marker in the loop so I’m guessing the event listen is just attaching to the last one and that I need some kind of unique identifier for each one? Any ideas?

    
    function initMap() {
    
      <?php 
        $centeredLatitude = "39.1203097150555"; 
        $centeredLongitude = "-80.33246546973088";
      ?> 
    
      const map = new google.maps.Map(document.getElementById("map"), {
        zoom: 7,
        center: { lat:<?php echo $centeredLatitude; ?>, lng: <?php echo $centeredLongitude; ?> },
        styles: mapStyles,
      });
      
      const image ="footer-fish-icon-40.png";
    
      <?php 
    
        $args = array( 
          'orderby' => 'title',
          'order' => 'ASC',
          'post_type' => 'location', 
          'posts_per_page'=>-1
          );
        
        $locations = new WP_Query( $args );
     
        if( $locations->have_posts() ) {
          // looop through each location and create marker
          while( $locations->have_posts() ) {
            $locations->the_post();
            $location_name = get_field('location_name');
            $latitude = get_field('latitude');
            $longitude = get_field('longitude'); 
            $phone = get_field('phone');
            ?>
    
            var card = 
    
            '<div class="card">'+
            '<div class="card-header"><?php echo $location_name; ?></div>'+
            '<div class="card-body">'+
             '<p class="card-text">Phone: <?php echo $phone; ?></div>'+
             '<a href="<?php echo get_the_permalink() ?>" class="btn btn-primary">Location Details</a>'+
            '</div>'
            '</div>';
    
            var infowindow = new google.maps.InfoWindow({
              content: card,
            });
            
            var marker = new google.maps.Marker({
              position: { lat:<?php echo $latitude; ?>, lng: <?php echo $longitude; ?> },
              map,
              icon: image,
            });
    
            marker.addListener("click", () => {
              infowindow.open({
                anchor: marker,
                map,
                shouldFocus: false,
              });
            });
    
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(function (position) {
                  initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                  map.setCenter(initialLocation);
                });
            }
    
      <?php 
          } // end while
          wp_reset_postdata();
        } // endif 
      ?>
    
    }
    
    window.onload = initMap;
    

    thanks agin for all your help

    • This reply was modified 3 years, 3 months ago by aaron4osu.
    Moderator bcworkz

    (@bcworkz)

    I don’t think it’s the marker listener that’s the issue, it’s the card attached to the event that’s the problem. The last card defined is the only one used. The var infowindow isn’t used for its data until the marker is clicked. At that time, only the last one defined is the only one available. The other earlier infowindow versions had been overwritten.

    Probably the best way to handle this is to assign each card to an array element. A new element is added each time through the loop. Initialize a PHP counter var before the loop starts. Also initialize an empty JS array before the PHP loop starts. Increment the counter at the end of the loop. Use this counter as the array index value to not only assign a card to a new array element, but also to pass that same element to the current event listener. This way every listener is assigned a different card.

    This approach is a little weird because a PHP value is used to specify a JS array index. This is OK because the resulting JS code would have static index values as a result of a PHP variable.

    BTW, the entire if (navigator.geolocation) {...} bit should be after the PHP loop completes. There’s no point in outputting this multiple times. Multiples still work, but all but one are redundant and wasteful.

    Thread Starter aaron4osu

    (@aaron4osu)

    @bcworkz thanks again. it’s getting close. So I added the counter, and created a cards array as you suggested. I’m not getting an errors, and the inspector shows all the cards are being created. How do I pass each card to the event listener?

    Here is what I have now.

    
    function initMap() {
    
      <?php 
        // center of map default
        $centeredLatitude = "39.1203097150555"; 
        $centeredLongitude = "-80.33246546973088";
      ?> 
    
      const map = new google.maps.Map(document.getElementById("map"), {
        zoom: 7,
        center: { lat:<?php echo $centeredLatitude; ?>, lng: <?php echo $centeredLongitude; ?> },
        styles: mapStyles,
      });
      
      const image ="https://eatpokebros.com/wp-content/themes/poke-signal-theme/assets/img/footer-fish-icon-40.png";
    
      <?php 
        // pull all locations
        $args = array( 
          'orderby' => 'title',
          'order' => 'ASC',
          'post_type' => 'location', 
          'posts_per_page'=>-1
          );
        $locations = new WP_Query( $args );
        if( $locations->have_posts() ) {
       
          $count=0; ?>
    
          const cards = [];
    
          <?php
           // looop through each location and create marker and event listener
          while( $locations->have_posts() ) {
            $locations->the_post();
            $location_name = get_field('location_name');
            $latitude = get_field('latitude');
            $longitude = get_field('longitude'); 
            $phone = get_field('phone');
            ?>
    
            cards[<?php echo $count;?>] = 
            '<div class="card">'+
            '<div class="card-header"><?php echo $location_name; ?></div>'+
            '<div class="card-body">'+
             '<p class="card-text">Phone: <?php echo $phone; ?></div>'+
             '<a href="<?php echo get_the_permalink() ?>" class="btn btn-primary">Location Details</a>'+
            '</div>'
            '</div>';
    
            var infowindow = new google.maps.InfoWindow({
              content: cards[<?php echo $count;?>],
            });
            
            var marker = new google.maps.Marker({
              position: { lat:<?php echo $latitude; ?>, lng: <?php echo $longitude; ?> },
              map,
              icon: image,
            });
    
            marker.addListener("click", () => {
              infowindow.open({
                anchor: marker,
                map,
                shouldFocus: false,
              });
            });
    
            <?php $count++; ?>
    
      <?php } // end while ?>
    
          // center on users location if they allow
          if (navigator.geolocation) {
              navigator.geolocation.getCurrentPosition(function (position) {
                initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                map.setCenter(initialLocation);
              });
          }
    
          <?php
          wp_reset_postdata();
        } // endif 
      ?>
    }//initMap
    window.onload = initMap;
    

    Thanks again for all your help

    Thread Starter aaron4osu

    (@aaron4osu)

    I figured out the rest. This is the final script in case anyone else needs this…

    
    function initMap() {
    
      <?php 
        // center of map default
        $centeredLatitude = "39.1203097150555"; 
        $centeredLongitude = "-80.33246546973088";
      ?> 
        // create map
        const map = new google.maps.Map(document.getElementById("map"), {
          zoom: 7,
          center: { lat:<?php echo $centeredLatitude; ?>, lng: <?php echo $centeredLongitude; ?> },
          styles: mapStyles,
        });
      
        // set map icon
        const image ="https://eatpokebros.com/wp-content/themes/poke-signal-theme/assets/img/footer-fish-icon-40.png";
    
      <?php 
        // pull all locations
        $args = array( 
          'orderby' => 'title',
          'order' => 'ASC',
          'post_type' => 'location', 
          'posts_per_page'=>-1
          );
        $locations = new WP_Query( $args );
        if( $locations->have_posts() ) {
       
          $count=0; ?>
          
          // initiate arrays
          var cards = [];
          var markers=[];
          var infowindows = [];
    
          <?php
           // looop through each location and create marker and event listener
          while( $locations->have_posts() ) {
            $locations->the_post();
            $location_name = get_field('location_name');
            $latitude = get_field('latitude');
            $longitude = get_field('longitude'); 
            $phone = get_field('phone');
            ?>
            // create marker
            markers[<?php echo $count;?>] = new google.maps.Marker({
              position: { lat:<?php echo $latitude; ?>, lng: <?php echo $longitude; ?> },
              map,
              icon: image
            });
    
            markers[<?php echo $count;?>].index = <?php echo $count;?>; //add index property
            //create card
            cards[<?php echo $count;?>] = 
              '<div class="card">'+
                '<div class="card-header"><?php echo $location_name; ?></div>'+
                '<div class="card-body">'+
                 '<p class="card-text">Phone: <?php echo $phone; ?></div>'+
                 '<a href="<?php echo get_the_permalink() ?>" class="btn btn-primary">Location Details</a>'+
                '</div>'
              '</div>';
    
            // create info window and add card to it
            infowindows[<?php echo $count;?>] = new google.maps.InfoWindow({
                content: cards[<?php echo $count;?>],
                
            });
            
            // add event listener to marker and connect to info window
            google.maps.event.addListener(markers[<?php echo $count;?>], 'click', function() {
                infowindows[this.index].open(map,markers[this.index]);
                map.panTo(markers[this.index].getPosition());
            }); 
    
            <?php $count++; ?>
    
      <?php } // end while ?>
    
          // center on users location if they allow
          if (navigator.geolocation) {
              navigator.geolocation.getCurrentPosition(function (position) {
                initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                map.setCenter(initialLocation);
              });
          }
    
          <?php
          wp_reset_postdata();
        } // endif 
      ?>
    }//initMap
    window.onload = initMap;
    
    </script>
    
    Thread Starter aaron4osu

    (@aaron4osu)

    @bcworkz I have one more issue that I’m trying to work out on this. When you click the different info windows that popup, they do not close when you click off of them on the map or even when you open another. How can I make it so that after you click on one popup, then when you click another it closes the previous one. I’m guessing some how I can create a separate event listener that waits for clicking off the map or at least clicking a 2nd info window? Not sure about the syntax.

    I tried adding this after the first event listener.

    
    google.maps.event.addListener(map, "click", function(event) {
                    infowindows[this.index].close();
                });
    

    full code for section:

    
    var cards = [];
          var markers=[];
          var infowindows = [];
    
          <?php
           // looop through each location and create marker and event listener
          while( $locations->have_posts() ) {
    
                $locations->the_post();
    
            if(get_field('latitude') && get_field('longitude')){
                $location_name = get_field('location_name');
                $latitude = get_field('latitude');
                $longitude = get_field('longitude'); 
                $phone = get_field('phone');
                ?>
                // create marker
                markers[<?php echo $count;?>] = new google.maps.Marker({
                  position: { lat:<?php echo $latitude; ?>, lng: <?php echo $longitude; ?> },
                  map,
                  icon: image
                });
    
                markers[<?php echo $count;?>].index = <?php echo $count;?>; //add index property
                //create card
                cards[<?php echo $count;?>] = 
                  '<div class="card">'+
                    '<div class="card-header"><?php echo $location_name; ?></div>'+
                    '<div class="card-body">'+
                    // '<p class="card-text mb-2">Phone: <?php echo $phone; ?></p>'+
                     '<a>" class="btn btn-block btn-primary">View Location</a>'+
                    '</div>'
                  '</div>';
    
                // create info window and add card to it
                infowindows[<?php echo $count;?>] = new google.maps.InfoWindow({
                    content: cards[<?php echo $count;?>],
                    
                });
                
                // add event listener to marker and connect to info window
                google.maps.event.addListener(markers[<?php echo $count;?>], 'click', function() {
                    infowindows[this.index].open(map,markers[this.index]);
                    map.panTo(markers[this.index].getPosition());
                }); 
    
                google.maps.event.addListener(map, "click", function(event) {
                    infowindows[this.index].close();
                });
    
                <?php $count++; ?>
    
    • This reply was modified 3 years, 2 months ago by aaron4osu.
Viewing 11 replies - 1 through 11 (of 11 total)
  • The topic ‘How do I create Google Map Markers From Custom Posts Loop’ is closed to new replies.