The correct way to call posts with ajax

I’m trying to write an image gallery plugin with jQuery. I’m using jQuerys $.post AJAX method to send and receive info from the relevant post page. Basically I’ll be looping through the attachments and adding a new image each time the next button is hit, until I’ve used all images (when I’ll need to return something to stop the AJAX, not figured out how yet…).

I’ve read some very conflicting info on how to do this. I would very much like to know how I access WP data and functions from another PHP file. Any ideas? I’m threadbare, stressed and generally out of my mind with this one : )

Related posts

Leave a Reply

2 comments

  1. As @MatthewBoynes already stated, making a $.post() request for every image might bring some overhead.

    A maybe better solution would be to grab and cache them, then throw them into your js files using wp_localize_script().

    $attachments = get_posts( array(
         'post_parent'    => get_the_ID()
        ,'post_type'      => 'attachment'
        ,'posts_per_page' => -1
        #,'exclude'        => get_post_thumbnail_ID() // only needed if we want to exclude the feat. image
    ) );
    
    // Hook those to `wp_enqueue_scripts`
    wp_register_script( 
         'gallery'
        ,get_template_directory_uri().'/js/gallery.js'
        ,array( 'jquery' )
        ,filemtime( get_template_directory().'/js/gallery.js' )
        ,true
    );
    wp_localize_script(
         'gallery'
        ,'gallery_object'
        ,json_encode( $attachments )
    );
    

    Then you can access the gallery_object from inside your ~/js/gallery.js file and move to the next image with an .on() click handler.

  2. Using ajax here would probably not be in your best interest (with one exception, see below). First, you’ll be creating unnecessary calls to your server to query on each image. Second, the results won’t be able to be cached, especially if you’re making POST requests (which would not be the correct HTTP method/verb for this, as you aren’t changing anything; in your example, you’d want to use GET requests [$.get() in jQuery ajax speak], but I digress). Third, it will be slow for the user.

    Your best bet would be to loop through your posts in the initial page call and output the image URLs to a javascript array, or output your posts array as JSON. You could also loop through and output <img> tags, but then images would load upfront and not on request (whether or not that’s a good thing depends on the site and the images). I’d go with the first option, and here’s how I’d get it started:

    <script type="text/javascript">
    var my_images = [
    <?php
    # Here is where you'll loop through your attachments
    ?>
    ];
    </script>
    

    The only exception to this is if you had lots of images, e.g. >100 per page. In that case, you’ll have to find the right balance and do ajax calls for batches of images, combining what you’re asking with what I suggested above.

    Good luck!

    Edit:

    On second thought, what I’d do is output a list of links to the images, with the titles as the link text, then use JS to read it out, setup the slideshow, and dynamically load the images (the link tag’s href) on-demand. This is really no different from the JS array, except the data is stored in HTML. Because it’s in HTML, it carries some distinct advantages: browsers with JS disabled will still be able to access the photos, you’ll have captions for the images, search engines spiders which don’t process JS will still index the images, and your hopefully-keyword-rich image titles will also be read by the spiders. Here’s how you’d set this up, pulled in part from the codex:

    <ul>
        <?php if ( have_posts() ) : while ( have_posts() ) : the_post();
        $attachments = get_posts( array(
            'post_type' => 'attachment',
            'numberposts' => -1,
            'post_status' => null,
            'post_parent' => $post->ID
        ) );
        if ( $attachments ) foreach ( $attachments as $attachment ) : ?>
        <li><a href="<?php echo wp_get_attachment_url( $attachment->ID ); ?>"><?php echo apply_filters( 'the_title', $attachment->post_title ); ?></a></li>
        <?php endforeach; ?>
    </ul>