Creating a WordPress Tag Search using jQuery

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!

The technique applied on Seth Anderson’s photo site.

“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 8th, 2011

  • http://www.facebook.com/profile.php?id=100002346616296 Kubodo Architecture

    where is CSS?

  • Hiuyu

    Is there a way if I want to add categories together filter with tags?

    • Hiuyu

      How can use “slug” instead of tag name for the input for search?
      because I customize the tag name and slug, they are different,
      I want to use slug for search, but not for the display tag name.
      Thank you for teaching.

      • Arne_mulder

        Same thing here, I use Qtranslate, so the tags are translated and appear in the url, which end in a 404 because I need the slugs in the url.
        I would really like to know how to fix this. Thanx in advance!

        • Anonymous

          Yes, using slugs is a more solid approach. Replace this line:
          var str = $(this).text().replace(/s+/g, ‘-’).toLowerCase();

          With this:
          var str = $(this).attr(‘class’).replace(/sselectedtag+/g, ”);

          I’ve updated the post. Thanks guys.

          • Hiuyu

            Yes!!! It works!!!!
            Thank you. You are great.
            Now, I can use slug instead of name display for search.

          • Arne_mulder

            I figured it would be that line, but my javacript knowledge is very limited so thanx a lot for this fix. You also might want to change the content behind the link “the full JavaScript in context here”, because that still contains the ‘old’ code now.
            Thanx a lot for the quick reply!

    • Anonymous

      It’s possible to specify a single category with which to limit the tag search. The format for this is, for instance:

      ?category_name=category-slug&tag=tag-slug,another-tag-slug

      It would be a matter of using the same jQuery techniques described above to output the category names, turn them into buttons, then add them to the query string. It’s fairly straightforward.

      I haven’t yet researched specifying more than one category or doing exclusions, which would be accomplished with a plug-in.

      • Hiuyu

        I’m not familiar with the jquery and wordpress code. But I will try hard.

  • Irulsastra

    how to create tag like http://stackoverflow.com/questions/tagged/javascript and i clicked on related post tag will added to be  http://stackoverflow.com/questions/tagged/javascript+jquery can you create like a sample

  • Ride2ride

    Really great solution! Thank you so much – you save my day dude, i love you!! ))

  • http://twitter.com/iheartwordpress fris

    you dont need the wp query part for the functions.php, since get_tags isnt used in the loop, its used to get site wide tags, you dont need to create another query.

    • martyspellerberg

      You’re correct, thanks. I’ve updated the post.

  • Franck

    Hi, I ve been testing this, but the all function doesn’t work for some reason I don’t know… http://didakticiel.com/?tdo_tag=facile+gratuit

  • HibestNick

    Is there a wordpress plugin that make me use it easily ? thanks

  • http://twitter.com/alma_taawo Alma Taawo

    I really need this functionality on my blog! But I don’t exactly understand the instructions. Is it possible that you could create a short instructional movie?

  • Betty Jašková

    I noticed submit link doesn’t load for IE 7 and IE8. Tested http://b12partners.net/photo/ on too.

    Is there any fix to support IE 7/8?

    • Betty Jašková

      I found the fix: append can’t handle invalid HTML, so I removed on line 9 and added to line 7 after final

      • martyspellerberg

        Thanks Betty! I’ve updated the post to reflect the invalid HTML fix.

  • Scott

    Is it possible to only output tags that are in a single category?

    • martyspellerberg

      Yes. See line 5 of the functions.php where we get the tags and put them into a variable? You could use another, more sophisiticated method of constructing that list of tags. And then, with your desired tags in-hand, proceed with the rest of this. I’m afraid that constructing that more sophisticated method is outside the scope of this tutorial, however.

  • Salat-Production

    URL ?tag=tag1+tag2 doesnt work in 3.5.2

  • jason

    hi,fist thanks your code,I want to know, how can I show zhe tags in the page of Results,just like this “tags: tag1 +tag2 + tag3” ,by the way,my tags names are chinese, I can‘t show zhe name ,I just use jQuery to show the sulg ,can you tell me how to show the name ? can i use php code show them?

  • http://stephbarnard.com Steph Barnard

    Is there a way to display the tag search on just one page, rather than writing it into the theme?

  • TDG

    Hi I installed the plugin but after that my post give me 404 error page. If I unistall the plugin they works great (I use custom post type for post). I use wordpress 3.6.1. How can resolve this problem? Thank you in advance

  • bardirian

    Guys I found this multiple dropdowns menu, and multiple filters which allows you use dropdown menu + radio(or) + check(and), even plus a search!!

    here, and see the demo in live preview
    http://codecanyon.net/item/taxonomies-filter-widget/4282257?ref=I0

    My own test site

    • martyspellerberg

      That looks pretty good. Also, just stumbled on this one, possibly interesting:
      https://facetwp.com/

      • bardirian

        ouch..this looks better..

  • manuel

    nice. really nice. thanks for putting this together. just a quick question. is there any way to highlight the current tag(s) being displayed in the mask? to keep bold for example them after running the search query?

  • Semivile

    Is there any way to make tags differ in size (the more frequent the larger), like in default tags behavior?

    • martyspellerberg

      Sorry for the delayed response. Yes, you can set the size based on the number of items. In the showalltags() function, you can use $tag->count to output the number of items. The simplest is just to append this to a class. Here’s a demo:

      https://gist.github.com/halfempty/b9c54bd5f2eec7f3dddd

      A more sophisticated approach might be to use ranges and assign class names such as “small, medium, large, extralarge,” etc.

      In both cases, you’d then set the font size itself in your CSS.