Conditional content loading in WordPress with AJAX, Part 2 – The Javascript Request

This article is the second in a series on coding AJAX requests in WordPress. You can read Part 1 here.

Now we move into our Javascript file. We’ll be writing a jQuery function that does the following:

  1. Test which page we’re on and only proceed if the test passes.
  2. Send the post ID to a specific function in functions.php.
  3. Insert the markup we receive back for that function into the page.

My slideshow script of choice, Flexslider, requires jQuery so we have a solid excuse to stick with that and make this coding easier.

Everything gets wrapped in the usual jQuery document.ready() function:

jQuery(document).ready(function() { });

Inside the ready() function we use an if statement to test the page and see if our AJAX should load. This is the basic picture:

if( jQuery('.page-gallery').length > 0 && document.documentElement.clientWidth > 480 ) { }

The .page-gallery class is generated by a little snippet I throw in the functions.php file, but this could be anything unique to the page(s) where the AJAX should fire. We look for the unique element and see if it exists. If it does exist, we know we’re on the right page so we proceed.

The document.documentElement.clientWidth part is taken straight from Jeremy Keith, and it targets the browser window size for this particular AJAX call. The sample above will move ahead and get the AJAX data if the window is wider than 480 pixels. The sizes for these tests can be anything and should be determined by the breakpoints that arise naturally from the design.

I got all the rest of this script from Gary Cao

Inside our page test, we create a jQuery.post object that talks to our functions.php file:

jQuery.post();

We add three pieces to the post object: our ajaxurl variable that sends info to functions.php, an object where we put the data that we’re sending, and a function that we use to work with the markup that comes back from functions.php:

jQuery.post(
  MyAjax.ajaxurl,
  {},
  function( response ) {
  }
);

MyAjax.ajaxurl comes from wp_localize_script() in our setup code in functions.php “MyAjax” could be anything as long as we use the same name in the wp_localize_script() function.

Then we put some stuff in those empty brackets.

MyAjax.ajaxurl,
{
  action : 'gallery-large',
  postID : jQuery('body').attr('data-id')
},
function( response ) {
}

The action is the really critical thing here that makes it all work. If we will need multiple AJAX calls, this name needs to be unique, and remember it because we’ll be using it again soon over in functions.php.

In the “postID” sample above, we use jQuery to grab the data attribute we inserted earlier into the header.php template. We only need this if the database query that we use to generate our markup will need the post ID of the page where the gallery appears.

There may be other parameters you want to send over to the server that are required for the database query, and this is the place to put them.

Finally, we fill in the function that receives the markup from functions.php and inserts it into our document.

	 	 
function( response ) {	 	  	 
 jQuery('.gallery').append( response );	 	 
}	 	 

In this example, we’re dropping the markup generated by our AJAX request into an element with the class of “gallery”. This will vary based on how the slide show is structured.

Here’s the final sample version all put together:

jQuery(document).ready(function() {
  // test whether to run the AJAX request
  if( jQuery('.page-gallery').length > 0 && document.documentElement.clientWidth > 480 ) {
    // from http://www.garyc40.com/2010/03/5-tips-for-using-ajax-in-wordpress/
    jQuery.post(
      // see tip #1 for how we declare global javascript variable
      MyAjax.ajaxurl,
      {
        // here we declare the parameters to send along with the request
        // each of these will be called in php with $POST_['whatever']

        // this means the following action hooks will be fired in functions.php:
        // wp_ajax_nopriv_gallery-large and wp_ajax_gallery-large
        action : 'gallery-large',

        // other parameters can be added along with "action"
        // this grabs the value of the 'data-id' attribute, added to the body in header.php
        postID : jQuery('body').attr('data-id')
      },
      function( response ) {
        // add the html response into the DOM
        jQuery('.gallery').append( response );
        }
    ); // end jQuery.post()
  } // end if( jQuery('.page-gallery').length > 0 && document.documentElement.clientWidth > 480  )
});

This script works for making a single AJAX request that pulls in the complete slide show markup. Since we already have markup in place for users without Javascript, this means we now have redundant markup!

In this case, I will use Modernizr’s .js and .no-js classes to hide the no-Javascript markup so it is cleanly replaced with the new markup from the AJAX request.

But what if we don’t want a bunch of redundant markup, half of which gets hidden and essentially wasted?

What if we need a separate AJAX request for each slide?

It might be more graceful to do a separate request for each item in the slide show and insert each image into the list individually. To be honest, at the time of this writing I have no idea what the performance implications might be for multiple AJAX requests vs. one single chunk request, but we’ll work out the code for how to do it here.

First off, we’ll target all of the slides. Assuming that our markup is an unordered list with a class of “slides”, we can use jQuery to store all of the list items in a variable:

var projects = $('.slides li');

Following the example above, we again test for the page we are viewing and the window size:

if( jQuery('.page-gallery').length > 0 && document.documentElement.clientWidth > 480 ) { }

Then we will apply jQuery’s “each” method to our projects variable.

projects.each(function() {
  // jQuery.post() code will go in here
}); // end projects.each()

jQuery’s super-handy each() gives us a ready-made loop so we can do our AJAX request separately for each item in the slide show.

But before we move on to the jQuery.post() stuff, we have to get the post ID for each item in the list!

Like we did before in editing the header.php template, we need to make sure the ID appears the markup so we can send it with our request. The easiest way is to apply it to the <li> elements in our “.slides” list using WordPress’s “the_ID()” function:

<li id="<?php the_ID(); ?>"></li>

We can then add a new variable at the start of our each() loop storing the value of the id:

var projectID = $(this).attr('id');

“$(this)” is jQuery’s reference to “this” particular list item in the loop we’re running.

But let’s say the ID appears in each list item as follows, using a standard WordPress post-labeling format.

<ul class="slides">
  <li id="post-<?php the_ID(); ?>"></li>
</ul>

This appears in the markup as something like:

<ul class="slides">
  <li id="post-215">
</ul>

We would then need to strip off the “post-” that is appearing before the ID number, which we can accomplish using substring():

var projectID = $(this).attr('id').substring(5);

We also need a variable to refer to the list item we’re working with, in order to append the new markup to it:

var projectID = $(this).attr('id').substring(5),
        slide = $(this);

Inside our each() loop, after we create the projectID variable, we insert all of the jQuery.post() stuff from the above example, with a couple of changes.

As you no doubt recall, inside the curly braces right after MyAjax.ajaxurl, we listed “action” and “postID” followed by a colon and a value. We will use our new projectID variable as the value for postID:

postID : projectID

Lastly, we need to adjust the code where we insert the markup we receive from our AJAX request.

function( response ) {
  // add the html response into the DOM
  slide.prepend( response );
}

In the example above, we use the “slide” variable we just created as a hook to add the markup. We are using jQuery’s prepend() function (adding the markup at the beginning of the element) instead of the append() function (at the end of the element). We are receiving the image ony and inserting it at the beginning of each list item as we run through the each() loop.

Finally, here’s the full code for our second sample:

jQuery(document).ready(function() {
  var projects = $('.slides li');
	
  // test whether to run the AJAX request
  if( jQuery('.page-gallery').length > 0 && document.documentElement.clientWidth > 480 ) {
		
    projects.each(function() {
      var projectID = $(this).attr('id').substring(5),
              slide = $(this);
			
      // from http://www.garyc40.com/2010/03/5-tips-for-using-ajax-in-wordpress/
      jQuery.post(
        MyAjax.ajaxurl,
        {
          // here we declare the parameters to send along with the request
          // each of these will be called in php with $POST_['whatever']

          // this means the following action hooks will be fired in functions.php:
          // wp_ajax_nopriv_gallery-large and wp_ajax_gallery-large
          action : 'gallery-large',

          // other parameters can be added along with &quot;action&quot;
          // this grabs the value of the 'data-id' attribute, added to the body in header.php
          postID : projectID
        },
        function( response ) {
          // add the html response into the DOM
          slide.prepend( response );
        }
      ); // end jQuery.post()
    }); // end projects.each()
  } // end if( ( jQuery('.page-gallery').length > 0 && document.documentElement.clientWidth > 480 )
});

Once we have finished our Javascript using one of these approaches (or a variation of either), we will move back into our functions.php file to write the PHP to receive the AJAX request and generate the response.