WordPress count child posts of each parent custom post type and use in json array for google maps jquery plugin

So i have been looking for a couple of days now and cant find a solution to this anywhere. It is a fairly bespoke request from a client… I am using a jQuery google maps plugin to add markers for each post (area) that the admin creates using a custom meta box with lat and long coordinates.

Each of these markers has a tooltip associated with it. In the tool tip i have got some text, the title of each post used to create the marker itself and a permalink to the post (area).

Read More

But i would like to display a count of all children posts (deals) of each of the posts (areas).

I have this working on the (area) posts themselves but cannot get them to display in my map tooltips.

This is the code i have so far i dont think i am far away from a solution but my php skills are still at a novice level so any help would be much appreciated.

<script type="text/javascript">
    $(document).ready(function(){
        var myMarkers = {"markers": [
            <?php $items3 = new wp_Query( array(
                'post_type' => 'area',
                'post_status' => 'publish',
                'posts_per_page' => -1,
                'orderby' => 'date',
                'order' => 'desc',
            ) );
            $post_id = $post->ID; //or somehow get the current post ID.
            $parent_id = get_post_ancestors($post_id);
            $parent = get_post_type( $parent_id );
            $args = array(
                'post_type' => 'deal',
                'post_status' => 'published',
                'post_parent' => $parent,
                'numberposts' => -1
            );
            $this_page_id=$wp_query->post->ID;
            $num = count( get_posts( $args ) );
            while ( $items3->have_posts() ) : $items3->the_post(); ?>
                        {"latitude": "<?php echo get_post_meta($post->ID, '_arealat', true); ?>", "longitude": "<?php echo get_post_meta($post->ID, '_arealong', true); ?>", "icon": "/wp-content/themes/localdoubleglazingdeals/assets/img/design/logo-icon.png", "baloon_text": 'We have <span><?php echo $num ?></span> deals in <strong><?php the_title(); ?></strong><br/><a href="<?php the_permalink(); ?>">View deals</a>'},
            <?php endwhile; ?>
            ]
                };
    $("#map").mapmarker({
        zoom    : 7,
        center  : 'Liverpool',
        markers : myMarkers
    });
});

it is the…

<?php echo $num ?>

part i am stuck on.

Related posts

1 comment

  1. First of all you should alway separate php from javascript.
    Generally talking, it’s a bad practise mix them, and specifically to WordPress, it also force you to add javascript inline instead using the WordPress proper way: using wp_enqueue_script.
    When you need pass variables from PHP to javascript, the proper WordPress way to do it is using wp_localize_script.

    So, your javascript code should be just something like this:

    jQuery(document).ready(function($){
      var myMarkers = {"markers": [ my_map_data.markers ] };
      $("#map").mapmarker({
        zoom : 7,
        center : 'Liverpool',
        markers : myMarkers
      });
    });
    

    Readable, isn’t it? Also note how I have used jQuery no conflict wrapper, this because I hope you are enqueuing jQuery properly, (i.e. using wp_enqueue_script to load the WP embedded jQuery version) and if so WordPress use jQuery in no conflict mode, so to make it works you should use no confict wrappers.

    Now that you have the code above, you should save it in a file, and call it e.g. my-map.js and save in your theme (sub)folder (or in your plugin folder, if you are developing a plugin).

    Assuming here you save that file in ‘js’ subfolder of your theme.
    Now you have to include in the right template. I don’t know where you are printing the map, and I assume here you have a page template called 'page-map.php' and you want to include there your map, so you have to include there your javascript.

    In your functions.php you should add:

    add_action('wp_enqueue_scripts', 'add_map_scripts');
    function add_map_scripts() {
       if ( is_page_template('page-map.php') ) {
          $jsurl = get_template_directory_uri() . '/js/my-map.js';
          wp_enqueue_script('my-map', $jsurl, array('jquery') );
          wp_localize_script('my-map', 'my_map_data', get_map_data() );
       }
    }
    

    This is the proper way to add the script in WordPress. If you look ad wp_enqueue_script docs I’ve linked, you can see I’ve added a 3rd argument to the function, it is the dependency array, whatever script you added in the array, if not already included in the page will be added, and also your script will be included after that. I’ve included jQuery, in the dependency array, in this way I’m sure jQuery will be added to the page: if you are manually adding jquery to page… remove it.
    You said you are using a plugin that have its own js script, you should look at the handle of this script (it’s the first param of wp_enqueue_script) and add it to the dependency array, in this way you are sure your script is added after the plugin script.

    Now if you loow at the javascript code I posted, you note that the markers array is taken from my_map_data.markers variable. But where this variable is defined?

    The answer is in the wp_localize_script that I called in the code above, just after wp_enqueue_script. If you see the wp_localize_script docs I’ve linked above, you see that I’m passing an object to the script called 'my_map_data' and the content of that object is what is returnd by get_map_data function. this function does not exist yet, so let’s write it (should go in your functions.php):

    function get_map_data() {
      // assure we are in right page
      if ( ! is_page_template('page-map.php' ) return;
      $areas = new WP_Query( array(
        'post_type' => 'area', 'post_status' => 'publish', 'posts_per_page' => -1,
        'orderby' => 'date', 'order' => 'desc'
      ) );
      if ( ! $areas->have_posts() ) return; // no areas, nothing to do    
      $markers = array();
      while ( $areas->have_posts() ) : $areas->the_post();
        global $post; // current area post object
        $deals_args = array(
          'post_type' => 'deal', 'post_status' => 'publish', 'numberposts' => -1
          'post_parent' => $post->post_parent
        );
        $d_num = count( get_posts($deals_args) );
        $ballon_f = 'We have <span>%d</span> deals in <strong>%s</strong>';
        $ballon_f .= '<br/><a href="%s">View deals</a>';
        $marker = array(
          'latidude' => get_post_meta( get_the_ID(), '_arealat', true),
          'longitude' => get_post_meta( get_the_ID(), '_arealong', true),
          'icon': get_template_directory_uri() . '/assets/img/design/logo-icon.png',
          'baloon_text' => sprintf($ballon_f, $d_num, get_the_title(), get_permalink() );
        );
        $markers[] = (object) $marker; // collect all markes in the $markes array
      endwhile;
      wp_reset_postdata(); // reset the post data after the custom query
      // return the array of markes to wp_localize_script that will json_encode it and
      // pass it to javascipt
      return array( 'markers' => $markers );
    }
    

    Now our function return an array to wp_localize_script and that function convert this array in JSON, and pass it as global object (named ‘my_map_data’) to the javascript. In this way when in javascript you use

    {"markers": [ my_map_data.markers ] };
    

    It will contain the array of object created by get_map_data function.

Comments are closed.