Tiffany B. Brown

29 September 2014

Using FlexSlider 2 with WordPress

I'm currently working on a WordPress-theme development project that requires a simple gallery. WordPress makes this easy with built-in support for photo galleries, but the layout is limited to a sort of slides-on-a-light-box layout. This project called for a slider.

My go-to sliding gallery script of choice has been WooThemes' FlexSlider 2 because of its simple setup and open source license. But the markup that FlexSlider requires is radically different than that of WordPress’ default gallery. Merging the two — and merging them in a way that makes it easy for the client to manage — would take a little more effort than copy-and-paste.

WordPress gallery shortcode

Creating a gallery in WordPress is actually pretty simple to do. You can do it visually, buy selecting photos from the media panel (Add mediaCreate Gallery). Or you can do it by adding a gallery short code to your post (Figure 1).

[gallery link="none" columns="1" ids="20,21,22,23,24,25,26,27"]

Figure 1: An example of a WordPress gallery shortcode.

A gallery short code starts with a left square bracket, and the word gallery. Next come the attributes of that gallery. These may include link, what each photo should link to; columns, or how many columns to use for this gallery; and ids, a comma-separated list of the media library image id numbers for each image.

By default, WordPress uses a series of <div> and <figure> elements to mark up galleries. However, FlexSlider expects a list, with a class attribute value of slides nested within a parent element with a class attribute value of flexslider.

The good news, of course, is that WordPress provides a mechanism for adjusting the output of short codes, including that of galleries.

Overriding the WordPress gallery shortcode

Though possible to override a short code handler by adding a new one with add_shortcode, the correct way is to use a filter, specifically, the post_gallery filter.

We can add a filter using the add_filter function. add_filter accepts two arguments: the filter to replace, and the name of a function that returns replacement markup.

That may sound complicated, but here's what it looks like. First, the code that returns the replacement markup. It is modeled on the gallery_shortcode function found in wp-includes/media.php.

function build_gallery_content( $attrs ){

    static $instance = 0;
    $instance++;

    /* 
    Limiting what the user can do by 
    locking down most short code options.
    */
    extract(shortcode_atts(array(
            'id'         =&gt; $post-&gt;ID,
            'include'    =&gt; '',
            'exclude'    =&gt; ''
    ), $attrs));

    $id = intval($id);

    if ( !empty($include) ) {
         $params = array(
                    'include' =&gt; $include,
                    'post_status' =&gt; 'inherit',
                    'post_type' =&gt; 'attachment',
                    'post_mime_type' =&gt; 'image',
                    'order' =&gt; 'ASC', 
                    'orderby' =&gt; 'menu_order ID');
            $_attachments = get_posts( $params );
            $attachments = array();
            foreach ( $_attachments as $key =&gt; $val ) {
                    $attachments[$val-&gt;ID] = $_attachments[$key];
            }
    } elseif ( !empty($exclude) ) {
            $params = array(
                    'post_parent' =&gt; $id,
                    'exclude' =&gt; $exclude,
                    'post_status' =&gt; 'inherit',
                    'post_type' =&gt; 'attachment',
                    'post_mime_type' =&gt; 'image',
                    'order' =&gt; 'ASC', 
                    'orderby' =&gt; 'menu_order ID');
            $attachments = get_children( $params );
    } else {
            $params = array(
                    'post_parent' =&gt; $id, 
                    'post_status' =&gt; 'inherit', 
                    'post_type' =&gt; 'attachment',
                    'post_mime_type' =&gt; 'image', 
                    'order' =&gt; 'ASC',
                    'orderby' =&gt; 'menu_order ID'); 
            $attachments = get_children( $params );
    }

    if ( empty($attachments) )
            return '';

    $selector = "gallery-{$instance}";

    $gallery_div = sprintf("&lt;div class='flexslider'&gt;&lt;ul id='%s' class='slides gallery galleryid-%d gallery-columns-1 gallery-size-full'&gt;", $selector, $id);
    $output = $gallery_div;


    foreach ( $attachments as $id =&gt; $attachment ) {
        /* 
        Use wp_get_attachment_link to return a photo + link 
        to attachment page or image
        http://codex.wordpress.org/Function_Reference/wp_get_attachment_link 
        */
        $img = wp_get_attachment_image( $id, 'full', false);

        $caption = '';

        /*
        Set the caption string if there is one.
        */

        if( $captiontag &amp;&amp; trim($attachment-&gt;post_excerpt) ){
            $caption = sprintf("\n\t&lt;figcaption class='wp-caption-text gallery-caption'&gt;\n\t&lt;div&gt;\n%s\n\t&lt;/div&gt;\n\t&lt;/figcaption&gt;", wptexturize($attachment-&gt;post_excerpt));
        }

        /*
        Set the output for each slide.
        */  
        $output .= sprintf("&lt;li class='gallery-item'&gt;&lt;figure class='gallery-icon'&gt;%s\n\t%s&lt;/figure&gt;&lt;/li&gt;", $img, $caption);
    }
    $output .= '&lt;/ul&gt;\n&lt;/div&gt;';
    return $output;
}

In this code, we're building the markup we need to add a FlexSlider gallery to each page. The $gallery_div variable holds the markup for the FlexSlider parent container (<div class='flexslider'>) and outer list element (<ul class="slides">). For each image in the gallery, we're adding a figure element inside of a list item. Finally, we add the closing ul and div tags and return the output.

Then we can call it from the function that will be our post_gallery filter.

function custom_gallery_shortcode( $output = '', $attrs){
    $return = $output;

    # Gallery function that returns new markup.
    $gallery = build_gallery_content( $attrs );


    if( !empty( $gallery ) ) {
        $return = $gallery;
    }

    return $return;
}

add_filter( 'post_gallery', 'custom_gallery_shortcode', 10, 2);

You don't have to use build_gallery_content or a similar function, of course. You could just fold that code into custom_gallery_shortcode. But using a separate function is a bit more readable.

Both of these functions should be placed in the functions.php file for your theme. If you're using an off-the-shelf theme, you may want to build a child theme so that you don't override your functions.php changes when you upgrade.

To make it all work, add FlexSlider code to your site's JavaScript file.

$(window).load(function() {
  $('.flexslider').flexslider();
  $('.flexslider').flexslider("pause");
});

To support multiple FlexSlider galleries on a page, use the code below.

$(window).load(function() {
  $('.flexslider').each( function(ind){
    $(this).flexslider();
    $(this).flexslider("pause");
  });
});