Creating a WordPress Tag Search using jQuery

The technique applied on Seth Anderson’s photo site.

The WordPress taxonomy functions make it easy to give your visitors links to per-tag archives of posts. But is it possible to give them archives of more than one tag? Sure it is!

“Any” & “And” Tag Intersections

By passing parameters via the URL, WordPress will create pages for the intersections of multiple tags. This means we can get posts with any of the tags by separating terms with a comma, like so: /?tag=onetag,anothertag. That is to say a post must have one but need not have all of the tags to qualify.

Conversely, we can get posts with all of the tags by separating terms with a plus, like so: /?tag=onetag+anothertag. This will return only posts that have every tag. There’s various issues with the default output of this, however, so go ahead and install the tTDO Tag Fixes plugin. Running this plugin changes the “all” URL string to /?tdo_tag=onetag+anothertag.

Show All Tags

The first thing we’ll do is print out all the tags, with links, onto the page. This goes in your theme’s functions.php:

function showalltags() {
 
	$tags = get_tags();
	$html;
	foreach ($tags as $tag){
		$tag_link = get_tag_link($tag->term_id);
 
		$html .= "<a href='{$tag_link}' title='{$tag->name} Tag' class='{$tag->slug}'>";
		$html .= "{$tag->name}</a>";
	}
	echo $html;
 
}

And output it somewhere in your theme like so:

<div class="taxonomies">
	<h3 id="tags">Tags</h3>
	<div class="taglist"><?php showalltags(); ?></div>
</div>

Rewrite the markup

Now we’re going to use JavaScript to update the page’s markup to reflect the JavaScript-dependent functionality we’re building. We do this with JS because these controls are only relevant to users with JS-enabled browsers — for others their presence would only be confusing.

Get your jQuery(document).ready(function($) started then include this:

function initialLoad () {
$('.taxonomies h3').html('Select one or more tags, then press <em>&ldquo;Search Tags&rdquo;</em>');
$('.taglist').before('<div class="searchcontrols"><span>Find photos with </span><a id="any" class="tagtoggle selected">any</a><span class="slash"> / </span><a id="all" class="tagtoggle">all</a><span> of the selected criteria</span></div>');	
$('.taxonomies').append('<div><a class="searchtags">Search Tags</a></div>');	
}
 
initialLoad();

Capture tag clicks

When a user clicks a tag, we’ll override the link and instead add the class “selectedtag”:

$('.taglist a').bind('click', function(event) {
event.preventDefault();
 
if ( $(this).hasClass('selectedtag') ) {
$(this).removeClass('selectedtag');
} else {
$(this).addClass('selectedtag');
}
 
});

Toggle “Any” & “And”

Similarly, capture clicks to the controls:

$('.tagtoggle').bind('click', function(event) {
event.preventDefault()
$('.tagtoggle').removeClass('selected');
$(this).addClass('selected');
});

Construct the URL

This function is the core of the mechanism:

function searchTags() {
var optionTexts = [];
 
// For each selected tag...
$('.selectedtag').each(function() { 
 
// capture the slug from class (stripping out the " selectedtag")
var str = $(this).attr('class').replace(/\sselectedtag+/g, '');
 
// and add it to an array
optionTexts.push(str);
});	
 
// Set the URL format appropriate to the selected search type
if ( $('#any').hasClass('selected') ) {
var param = 'tag';
var separator = ',';
} else {
var param = 'tdo_tag';
var separator = '+';			
}
 
// Put the tag list together
var tagstring = optionTexts.join(separator);
 
// And send them off to the final, constructed URL
window.location = '/?' + param + '=' + tagstring;
 
}

Enable the Search Button

Last but not least, the action on the search button calls the search function:

$('.searchtags').bind('click', function(event) {
event.preventDefault()
searchTags();
});

And that’s it! You can grab the complete code from Gist.

Updated December 10, 2011 to capture the tag slug from the class, rather than inferring it from the tag name.
Updated May 20, 2012 to reflect a suggestion made by commenter Fris.
Updated May 20, 2013 to reflect a IE7 fix submitted by Betty Jašková.

Posted November 2011

This website is hosted by Media Temple. Thanks, guys!