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 media → Create Gallery). Or you can do it by adding a gallery short code to your post (Figure 1).
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' => $post->ID,
'include' => '',
'exclude' => ''
), $attrs));
$id = intval($id);
if ( !empty($include) ) {
$params = array(
'include' => $include,
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => 'ASC',
'orderby' => 'menu_order ID');
$_attachments = get_posts( $params );
$attachments = array();
foreach ( $_attachments as $key => $val ) {
$attachments[$val->ID] = $_attachments[$key];
}
} elseif ( !empty($exclude) ) {
$params = array(
'post_parent' => $id,
'exclude' => $exclude,
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => 'ASC',
'orderby' => 'menu_order ID');
$attachments = get_children( $params );
} else {
$params = array(
'post_parent' => $id,
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
'order' => 'ASC',
'orderby' => 'menu_order ID');
$attachments = get_children( $params );
}
if ( empty($attachments) )
return '';
$selector = "gallery-{$instance}";
$gallery_div = sprintf("<div class='flexslider'><ul id='%s' class='slides gallery galleryid-%d gallery-columns-1 gallery-size-full'>", $selector, $id);
$output = $gallery_div;
foreach ( $attachments as $id => $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 && trim($attachment->post_excerpt) ){
$caption = sprintf("\n\t<figcaption class='wp-caption-text gallery-caption'>\n\t<div>\n%s\n\t</div>\n\t</figcaption>", wptexturize($attachment->post_excerpt));
}
/*
Set the output for each slide.
*/
$output .= sprintf("<li class='gallery-item'><figure class='gallery-icon'>%s\n\t%s</figure></li>", $img, $caption);
}
$output .= '</ul>\n</div>';
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");
});
});