WordPress Hooks and jQuery Custom Events

WordPress Hooks

If you develop with WordPress, you’re very familiar with the Plugins API. This allows you to ‘hook’ into most any part of the application and either filter data or run bits of code at a desired sequence point.

A sample action hook might look like this:

add_action('init', 'foobar_register_post_type', 0);
function foobar_register_post_type(){
    //Do something
}

A sample filter hook might look like this:

add_filter('query_vars', 'foobar_add_public_query_var', 0, 1);
function foobar_add_public_query_var($vars){
    $vars[] = 'foobar_var';
    return $vars;
}

There are hundreds of way to extend WordPress which is why it’s an amazing application upon which to develop. You can even create your own custom hooks using something like the following:

do_action('foobar_action');
$data = apply_filters('foobar_filter', $data);

This gives others access to extend your code with a couple lines of code in the right spots.

jQuery Custom Events

Many WordPress developers are building nice front-end experiences these days on jQuery (JavaScript). More specifically, plugins and themes are using AJAX instead of using native $_POST or $_GET behavior. The problem I’ve run into with several plugins is their lack of front-end extensibility.

On the server-side, the proper WordPress hooks usually exist, but there’s typically no way to extend specific events on the client-side. jQuery gives us the ability to easily follow the pattern of WordPress hooks.

A simple custom event might like this:

//This is similar to the WP function add_action();
jQuery(document).bind('foobar_custom_event', function(event, param1, param2){
    //Do something
});

The way to trigger a custom event is as follows:

//This is similar to the WP function do_action();
jQuery(document).trigger('foobar_custom_event', {arg1 : ['foo', 'bar', 'hello', 'world'], arg2 : 'Hello World' });

As you can see we trigger ‘foobar_custom_event’ and pass in arguments to the callback. If you build plugins or themes for WordPress, it’s as simple as that to make your client-side scripts as extensible as your server-side scripts.

An example use-case would be to allow other plugins to hook into a form submission success state to pass the submitted data onto a third-party API or post it their own registered ‘wp_ajax’ hooks.

There’s no need for building out a complex hook system in JavaScript. It’s already available to you. It’s up to you to make your application as open as possible to cultivate creativity around your codebase.

Create your own admin-ajax.php type handler

The admin-ajax.php handler is a bit heavy, especially if you’re using AJAX on every page load. I am working on a project now that has multiple caching mechanisms and the only way to update the original server is to POST to the server. Since admin-ajax.php invokes the admin_init hook, it loads a lot of unnecessary items for AJAX call. Here’s the light-weight version of admin-ajax that I created to handle my plugin’s AJAX calls. Save this as request.php in your plugin folder.

define('DOING_AJAX', true);

if (!isset( $_POST['action']))
    die('-1');

//relative to where your plugin is located
require_once('../../../../../wp-load.php'); 

//Typical headers
header('Content-Type: text/html');
send_nosniff_header();

//Disable caching
header('Cache-Control: no-cache');
header('Pragma: no-cache');

$action = esc_attr($_POST['action']);

//A bit of security
$allowed_actions = array(
    'action_1',
    'action_2',
    'action_3'
);

if(in_array($action, $allowed_actions)){
    if(is_user_logged_in())
        do_action('plugin_name_ajax_'.$action);
    else    
        do_action('plugin_name_ajax_nopriv_'.$action);
}
else{
    die('-1');
}

To use this you obviously would hook into these actions doing the following:

//For logged in users
add_action('plugin_name_ajax_action_name', 'function_callback_name');

//For logged out users
add_action('plugin_name_ajax_nopriv_action_name', 'function_callback_name');

You will need to craft your AJAX request as follows:

jQuery(document).ready(function($){
    var data={
         action:'action_name',
         otherVar: varValue
    };
    $.post('http://url/to/your/plugin/request.php', data, function(response){
         alert(response);    
    });
});

jQuery in WordPress – The Good, The Bad, The Ugly

When I was an uber noob with jQuery and WordPress, I struggled to get my scripts to work properly. I looked at dozens of plugins and themes and found a varying number of ways others implemented jQuery. The following is my personal opinion from experience using jQuery and WordPress together.

The Good

jQuery(document).ready(function($){
    $('.something').each(function(){
        $(this).doSomething();
    });
});

I’ve found this to be the most elegant jQuery declaration that does not conflict with the WordPress UI or other plugins. Declare the jQuery function to start and feed the dollar sign parameter so the code inside looks neat and clean.

The Bad

$(function(){
    $('.something').each(function(){
        $(this).doSomething();
    });
});

Since several popular Javascript libraries use the dollar sign as their function name, it’s important to not assume the dollar sign is assigned to the jQuery library. By not declaring the jQuery function outright, you are almost certain to break the WordPress UI.

The Ugly

jQuery(function(){
    jQuery('.something').each(function(){
        jQuery(this).doSomething();
    });
});

Technically, this example is absolutely correct, however it’s not pretty. Who wants to write ‘jQuery’ a thousand times in their script? I prefer to declare the jQuery function once and substitute it with the dollar sign. It makes for a better visual and easier read.

The Acceptable

var $i = jQuery.noConflict();
$i(document).ready(function(){
    $i('.something').each(function(){
        $i(this).doSomething();
    });
});

If you’re really struggling to get jQuery working properly, you can use the jQuery.noConflict() function. I steer away from this method because I only use plugins that won’t cause massive conflicts of this nature. I only use this method when I’m backed in a corner with no other options.

FlexSlider

FlexSlider is a fully responsive jQuery slider. It looks awesome, and has cupcakes in the demo. What more could you ever want?