JavaScript the WordPress Way / Part 1

Two of the most important WordPress functions are often ignored by WordPress theme and plugin developers. This is the fault of the functions themselves, they need to improve their PR and hire better publicists.

It’s also possible your theme or plugin will work perfectly well without these functions on its own. Problems will arise when your theme or plugin both use the same JavaScript library or if Prototype and jQuery are both used on the same site.

These functions are used to add JavaScript to the html, either in the head or the footer.

Introducing wp_register_script and wp_enqueue_script

For the rest of this article I’ll refer to development of your theme. The tutorial applies equally to development of your plugin, but there’s only so many times the phrase “your theme or plugin” can appear in a page.

In this first part, we’ll look at:

The problem defined

Imagine you’ve used a theme on your WordPress site for months or years without a problem. It uses jQuery to add AJAX functionality to your site and it’s called George’s Super Theme.

You decide to add a plugin to your WordPress site and add more AJAXy goodness to your site. This plugin also uses jQuery for the JavaScript and it’s called Richard’s Fabulous Plugin.

You activate the plugin and instead of the super-fabulous result you were looking for you end up with a super-broken site. None of the JavaScript is working and your visitors are stuck on the home page, with nowhere to go.

Looking at the HTML of your WordPress site, you see the following lines:

<script type='text/javascript'
  src='/wp-content/themes/george/jquery-1.4.2.js'></script>
<script type='text/javascript'
  src='/wp-content/plugins/richard/jquery-1.3.2.js'></script>

Both the theme and the plugin are attempting to load the jQuery library. each uses a different version, which further complicates matters.

In this particular case, the theme is expecting jQuery version 1.4.2 and the plugin is replacing it with version 1.3.2. Anytime the theme attempts to use a function added to jQuery in version 1.4 or later, an error occurs preventing the JavaScript from running.

Even if the site was running as expected, it’s a waste of your users’ bandwidth.

Fortunately the WordPress developers envisioned this problem and sort to solve it by including the most common JavaScript libraries with WordPress and developing the functions that are the subject of this tutorial.

Libraries included with WordPress

WordPress comes with a number of JavaScript libraries pre-registered, so you need not include these libraries in your theme. All you need to do is include them as dependencies of your custom JavaScript and WordPress will do the work.

Some of the libraries included with WordPress are:

  • jQuery – with the handle ‘jquery’, runs in no conflict mode
    • WP 2.9.2 includes version 1.3.2 of jQuery
    • WP 3.0 will include version 1.4.2 of jQuery
  • Scriptaculous – with the handle ‘scriptaculous’
  • SWFObject – with the handle ‘swfobject’
  • Prototype – with the handle ‘prototype’
  • A full list of pre-registered script can be found in the codex.

The functions defined

The WordPress codex defines wp_enqueue_script as “a safe way of adding JavaScript to a WordPress generated page”.

wp_register_script is similar and can be thought of as a safe way of introducing JavaScript to WordPress, without adding it to the generated page.

The difference between these functions are fully explained in the sections Registering your scripts and Enqueueing your scripts below.

Both functions take the same five parameters:

$handle
(required for both functions) Name of the script
$source
(required for wp_register_script) – URL of the script. Also required by wp_enqueue_script if the script is unregistered.
$dependancies
(optional) – an array of handles the script depends on
$version
(optional) – version number
$in_footer
(true/false, optional) – if true, place script above the HTML </body> tag, otherwise place the script in the HTML <head>

These functions only work as expected if both wp_head() and wp_footer() are included in header.php and footer.php respectively.

Registering your scripts – wp_register_script

wp_register_script gives WordPress knowledge of your script without adding it to your HTML. Used by itself, it has no effect on your HTML whatsoever.

You can use it if you wish to register your various JavaScript files in one block of php within your theme’s functions.php file, allowing you to update version numbers, dependancies and handles in one place.

If the use of the JavaScript depends on particular conditions being met, such as the user being on a particular post, you can then enqueue your scripts elsewhere without losing track of where you should update version numbers.

If your theme’s JavaScript can be loaded in the footer and relies on the jQuery library, you would register your script with the following code:

wp_register_script (
  'mytheme-custom', /* handle WP will know JS by */
  get_bloginfo('template_url') . '/custom.js', /* source */
  array('jquery'), /* requires jQuery */
  1.0, /* version 1.0 */
  true /* can load in footer */
);

At this stage, this has no effect on your HTML, you need to use wp_enqueue_script to do that.

Enqueueing your scripts – wp_enqueue_script

wp_enqueue_script outputs your JavaScript to the HTML of the page, either as a result of the wp_head() or the wp_footer() call in your PHP. If you have pre-registered your script (as above), the full code is:

if (!is_admin()) {
  wp_enqueue_script('mytheme-custom');
}

Combined with the code above, this line of code will load both jQuery and your theme’s JavaScript. The only reference to jQuery is needed in the dependancies. There is no need to register or enqueue it yourself.

The check that your visitor is outside of the admin area, !is_admin() – is important, as these functions can be used to add JavaScript to both the visitor and admin areas.

More often than not, you’ll want to leave the admin area alone.

A shortcut

It’s possible to enqueue your script without registering it first. This comes in handy if your theme uses a single JavaScript that is loaded on every page, outside the admin area, of your blog.

The code to do this is:

if (!is_admin()) {
  wp_enqueue_script (
    'mytheme-custom', /* handle WP will know JS by */
    get_bloginfo('template_url') . '/custom.js', /* source */
    array('jquery'), /* requires jQuery */
    1.0, /* version 1.0 */
    true /* can load in footer */
  );
}

Again, our custom code requires the jQuery Library.

Aside: noConflict for jQuery and Prototype

As mentioned earlier, jQuery runs in noConflict mode. The reason being that in jQuery’s standard mode it includes the $ variable as an alias. WordPress also includes Prototype, which includes the JavaScript variable $.

Imagine if your theme uses jQuery and you add a WordPress plugin that makes use of Prototype, whichever is loaded second would override the $ variable of the former. Either your theme’s or the WordPress plugin’s JavaScript would crash as a result.

If your theme uses jQuery and you’d still like to make use of the $ alias, it’s possible to do so without breaking the plugin’s JavaScript. In your JavaScript file, just wrap your code between these two lines:

(function($) {
  /* your code */
})(jQuery);

source

Under no circumstances should you reintroduce the $ alias for jQuery, it could lead to problems down the track.

A shorter aside: throughout this post I’m using the example of JavaScript requiring jQuery. The reasons are two-fold: a) it’s the library I use most and, b) as Twitter’s Dustin Diaz said recently of jQuery: ‘they won‘.

Now Available: Part Two

In part 2 of this tutorial we’ll further illustrate dependancies, lower your bandwidth costs and show you how to use similar functions to load your stylesheets.

By Peter Wilson

Peter has worked on the web for twenty years on everything from table based layouts in the 90s to enterprise grade CMS development. Peter’s a big fan of musical theatre and often encourages his industry colleagues to join him for a show or two in New York or in the West End.