• Skip to primary navigation
  • Skip to main content
  • Skip to footer
  • Books
    • Content Strategy for WordPress (2015)
    • WordPress for Web Developers (2013)
    • Beginning WordPress 3 (2010)
  • Blog
    • Content Modeling for WordPress
    • WordPress Hidden Gems
    • Web Design
  • Work
    • MLIS Class Projects (2019-2022)
    • Portfolio (2002-2019)
    • Services
    • WordPress Plugins
    • WordPress Themes
    • Presentations and Interviews
    • on GitHub →

Stephanie Leary

Writer, WordPress consultant, recent MLIS grad

  • About
    • Press Kit
    • Presentations and Interviews
  • Contact Me

Getting tag autocomplete (and other jQuery stuff) to work for visitors

October 4, 2011 Stephanie Leary 3 Comments

The trickiest part of the latest updates to Twenty Links was getting the tag suggest function to work for users who aren’t logged in. I’m pretty much a n00b when it comes to jQuery — JavaScript in general has always been my weakest skill — so I went looking for a handy tutorial, and I found one: Using WordPress built-in tag auto complete script in your Plugins, posted a couple of years ago by Sudar Muthu. That did the trick — but only for logged-in users.

Why it doesn’t work

WordPress handles jQuery requests using the /wp-admin/admin-ajax.php file. Here’s the catch:

The only cave[a]t to this method is that right now the admin-ajax.php file needs you to be logged in and therefore can only be used in admin pages. But in WordPress 2.9 even anonymous users can load admin-ajax.php file. If you need use auto tag completing in blog pages, then you may have to wait till 2.9 is released.

Obviously that was written before 2.9 came out, so it’s not quite accurate. As it turned out, admin-ajax.php does handle requests from anonymous users — but it kicks them back out to a callback function you specify. I didn’t quite understand what was going on until I actually opened the file and read the code. Here’s the relevant bit:

if ( ! is_user_logged_in() ) {

	// [some stuff having to do with autosave]

	if ( !empty( $_REQUEST['action'] ) )
		do_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] );

	die('-1');
}

Translation: if the user isn’t logged in, call functions hooked to the relevant action prefixed with wp_ajax_nopriv_. If there are no such functions, fail with an error message of -1.

Upshot: your users see this.

auto suggest shows -1 when the user types a word

So, in order to get this working for anonymous visitors, you have to use that wp_ajax_nopriv_[something] action.

How it’s done for authenticated users

Reading a little further down in admin-ajax.php, I found the bit that handles tag suggestions:

switch ( $action = $_GET['action'] ) :
// [other stuff]
case 'ajax-tag-search' :
	if ( isset( $_GET['tax'] ) ) {
		$taxonomy = sanitize_key( $_GET['tax'] );
		$tax = get_taxonomy( $taxonomy );
		if ( ! $tax )
			die( '0' );
		if ( ! current_user_can( $tax->cap->assign_terms ) )
			die( '-1' );
	} else {
		die('0');
	}

	$s = stripslashes( $_GET['q'] );

	if ( false !== strpos( $s, ',' ) ) {
		$s = explode( ',', $s );
		$s = $s[count( $s ) - 1];
	}
	$s = trim( $s );
	if ( strlen( $s ) < 2 )
		die; // require 2 chars for matching

	$results = $wpdb->get_col( $wpdb->prepare( "SELECT t.name FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.name LIKE (%s)", $taxonomy, '%' . like_escape( $s ) . '%' ) );

	echo join( $results, "n" );
	die;
	break;

OK, so in order to avoid all those die() conditions, we need to set the action to ajax-tag-search, and the taxonomy has to be defined. I looked at Sudar’s code again. Sure enough, the query string sent to jQuery.suggest() includes both those things: ?action=ajax-tag-search&tax=post_tag. It’s only failing because the user never makes it this far if they’re not logged in. Even if they did get here, this code does an additional check to see if the user can assign tags: if (!current_user_can($tax->cap->assign_terms)). We’ll need to get rid of that in the anonymous version of the function.

Duplicating the function for visitors

I went back to reading about the nopriv callbacks. What I needed to do was define the function that would fetch tags from the database, just like the code in admin-ajax.php, and hook it to the wp_ajax_nopriv_ajax-tag-search action.

Here’s the code I added to the functions.php file, just after Sudar’s code:

// autocompletion for non-logged-in users
add_action('wp_ajax_nopriv_ajax-tag-search', 'add_autosuggest_20links_callback');

// cribbed from admin-ajax.php
function add_autosuggest_20links_callback() {
	global $wpdb;
	if ( isset( $_GET['tax'] ) ) {
		$taxonomy = sanitize_key( $_GET['tax'] );
		$tax = get_taxonomy( $taxonomy );
		if ( ! $tax )
			die( '0' );
	} else {
		die('0');
	}

	$s = stripslashes( $_GET['q'] );

	if ( false !== strpos( $s, ',' ) ) {
		$s = explode( ',', $s );
		$s = $s[count( $s ) - 1];
	}
	$s = trim( $s );
	if ( strlen( $s ) < 2 )
		die; // require 2 chars for matching

	$results = $wpdb->get_col( $wpdb->prepare( "SELECT t.name FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.name LIKE (%s)", $taxonomy, '%' . like_escape( $s ) . '%' ) );

	echo join( $results, "n" );
}

It’s exactly the same as the section from admin-ajax.php, minus the capability check and the surrounding switch.

And it works! See it in action on my links site. Grab the Twenty Links theme to see the completed functions.php file.

WordPress jquery

Reader Interactions

Comments

  1. Jared says

    October 4, 2011 at 10:48 am

    I’m just letting you know in advance that I plan on stealing this for Tasty ;)

    Reply
    • Stephanie says

      October 4, 2011 at 10:54 am

      I expected you would!

      Reply
  2. Alex says

    March 11, 2014 at 12:43 pm

    Great!!! I was looking exactly for this. Thank you!

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Footer

My Books

I’m a front end developer at Equinox OLI, working on open source library software. I was previously a freelance WordPress developer in higher education. You can get in touch here or on LinkedIn.

Copyright © 2023 Stephanie Leary · Contact