This is the final post in the series JavaScript in WordPress. Be sure to read the first article, too!

In the first post in this series, I briefly mentioned that there is a problem with writing JavaScript in WordPress. In boils down to the fact that people are writing JavaScript who don’t truly know jQuery (let alone JavaScript), and that there are lack of standards to follow.

And though I’m not interested in defining the coding standards for JavaScript in WordPress – at least not here – I am interested in sharing four things that I’ve found to be successful in writing maintainable jQuery in WordPress for both individual and team-based projects.

Note, of course, that these are geared towards jQuery. After all, that is WordPress’ JavaScript library of choice.

1. Use a Linter

Generally speaking, a linter is a tool that examines your source code, looks for any potential problems, and makes recommendations for things that could ultimately lead to bugs, and/or that can improve the readability of the code.

For JavaScript, the two most popular Linters are:

  • JSLint is written by Douglas Crockford who is arguably known best for his work in the JavaScript community. It’s strict and can be a pain to make the code adhere to all of its recommendations, but is worth checking out if for nothing else because of the significance of the author.
  • JSHint is a community-driven tool that started as a fork of JSLint. It’s a bit more relaxed than JSLint and doesn’t enforce a specific coding style on to its users.

At any rate, running your code through a linter is one of the easiest things that you can do to help begin formatting your code in a standard way.

2. Minify Your Source

This may not actually contribute to the bottom line of writing better code, but I think it contributes directly to the performance of your theme, plugin, or application. When discussing WordPress Assets, it really boils down to the number of HTTP requests being made and the size of the files being downloaded.

Regardless of where you stand, I believe that lower file size, the better. To that end, I recommend using a minification tool to process that linted JavaScript and then including that version in your project.

For example, I often organize my JavaScript directory such that there is a dev subdirectory and I let CodeKit write out the minified version of the JavaScript files into the root of the js directory.

jQuery in WordPress - Minifying Source Code

Then, I register and enqueue the minified version of the file:

wp_register_style( 'application', get_template_directory_uri() . '/assets/css/application.css', array( 'bootstrap', 'bootstrap-responsive' ) );
wp_enqueue_style( 'application' );

There are a number of different utilities available for minifying JavaScript source, too:

Whichever you choose, I recommend that you and your team use the same one so that minification is also standardized.

3. Load Only When Needed

Some may have a differing opinion that me on this, but I think that we should only load the necessary JavaScript when needed. This may result in a large number of JavaScript files in your project, but each one will be smaller, more maintainable, and will have a single purpose.

The Dashboard

To include JavaScript specifically on a single page of the dashboard, we can take advantage of WordPress get_current_screen function. This gives us the ability to look at which page we’re on and then load only the required files:

if( 'appearance_page_custom-header' == strtolower( $screen->id ) ) {

	wp_register_script( 'admin-header', get_template_directory_uri() . '/js/admin-header.min.js' );
	wp_enqueue_script( 'admin-header' );

} // end if

The Public View

When working with the public view, we don’t have access to the get_current_screen function, so we end up having to come up with alternative ways of registering and enqueing scripts.

Depending on the nature of your project, you may be able to get away with looking at the page ID, looking at the page slug, looking at the page title, the current user ID, the current user role, whether or not the user is logged in, etc.

Whatever method you choose, it’s more important that it’s portable among installations (for example, will all users be using the same permalink structure that you’re expecting?).

One way of doing it, by looking at the current page’s title, looks like this:

if( 'register for site' == strtolower( get_the_title() ) ) {

	wp_register_script( 'site-register', get_template_directory_uri() . '/js/register.min.js' );
	wp_enqueue_script ( 'site-register' );

} // end if

4. Comment. A lot.

I used to think that the code could be its own documentation, but the more code I write and the more projects that I work on, the less and less I believe that.

In fact, one of the things that I tell others during code reviews is that they should be commenting their functions, potentially confusing lines, and every single block of code.

Regardless of how verbose your code is, it’s still code and it’s unlikely that you’re going to be able to decipher your work in a few months, let alone someone else’s in future months.

Here’s one example of a small function that I wrote in a recent project. It uses PHPDoc-style for the method name and then standard inline comments throughout:

 * The callback for when the follow/unfollow request is sent to the server.
 * @param	response	The server response
function relationshipCallback(response) {
	"use strict";

	// If the follow was a success, then we can hide the 'Follow' button
	// and display the 'Unfollow' button
	if (1 === parseInt(response, 10)) {

		// Now refersh the page fragments so we can unfollow them
		$('#async-user-container').load(window.location.href + '/#goals #user-buttons', attachEventHandlers);

		// And refresh the page fragment for the following / follower count
		$('#async-following-container').load(window.location.href + '/#goals #friend-stats', attachEventHandlers);

	} // end if

} // end relationshipCallback

Speaking from experience, I know that in the next few months this will be easier to follow than without the comments.

5. Adopt WordPress Coding Standards

Finally, try to adopt the WordPress Coding Standards in your JavaScript as much as possible. Sometimes, you’re going to find that linting utilities will enforce their own rules – and that’s good! – but when they don’t, try to default to the WordPress suggestions.

For example:

  • Yoda Conditions are one of my favorite part of the WordPress Coding Standards. I use them all in the time when writing jQuery in WordPress and linters don’t care about them at all.
  • Brace Style. I’m a fan of using braces 100% of the time even if the evaluation of the condition is a single line. It’s verbose and shows exactly what I’m trying to wrap in conditionals.
  • Clever Code. Sure, as programmers, we love trying to wrap as much stuff into as few lines as possible, but, again, in a few months, do we really want others to have to map out what we’re doing to try to make sense of it? Hopefully no – I wouldn’t want them doing that to me.

The bottom line is that if a lint utility doesn’t catch a problem and you’re wondering how best to proceed with writing a certain bit of code, try defaulting to the WordPress Coding Standards.

As I’ve said throughout these two posts, I’m not looking to define the coding standards for WordPress – I’m simply trying to offer suggestions for a significant problem that’s so pervasive across the development.

Surely I’m not the only one with an opinion on this, so feel free to share your thoughts, too.


Join the conversation! 7 Comments

  1. Is register script just used for DRYing out the code? Can’t you register and enqueue in the same wp_enque function? I assume you would register it if you enqueueing on a conditional basis? For example, you would register all your styles and scripts in the top of your plugin, then conditional enqueue them for different situations?

    Also a good guide to performance tuning JS selectors.

    • From the Codex:

      A safe way of regisetring javascripts in WordPress for later use with wp_enqueue_script().

      All while it’s totally acceptable to just use wp_enqueue_scripts (and I know plenty of developers who do!), I’ve always been on the aggressive side so I tend to play it safe.

    • I like to always register first for sanity sake. That way I can just enqueue w/ the handle. It’s not really necessary, but if all scripts are registered in a central location, they can then be enqueued conditionally in the same place (on the wp_enqueue_scripts hook) or in template files or whatever in a theme (since WP 3.3ish?). Anyway, just makes life easier for me when I work on a lot of sites.

  2. Great post Tom! I hadn’t come across those linters before – do you know if they look for bugs that would appear in IE7,8? (This would save me a lot of trouble!).

    In my opinion shipping bug-free javascript is really vital. I’ve had countless ‘bug’ reports for my plug-ins because a theme / another plug-in had a bug in their javascript, causing my plug-in not work (or plug-in’s simply running javascript when it shouldn’t be).

    I agree with Brian here – I register the scripts in one location and then I can just call wp_enqueue_script() whenever I need it (e.g. template files, widgets, shortcodes).

    @Brian – yes its 3.3.

    For admin pages I tend to use the load-* hook – it’s not fool proof, as sometimes you still need to check the screen ID, but works well for custom admin pages.

    Keeping ‘dev’ versions of the script is a good idea. For core scripts WordPress checks the constant SCRIPT_DEBUG and conditionally loads the dev versions – I like to do the same for my plug-in scripts.

    • Stephen – in my experience, JSLint is so strict that does it does a pretty good job of enforce standards and rules on JavaScript that should work with older browsers. I don’t do much work with anything less than IE8 so I can’t say that definitively, though.

      Also, I’ve recently begun using SCRIPT_DEBUG myself. I started when I was working on a couple of patches to core and have since kept doing so (especially since I’ve begun linting and minifying my script files during development).

  3. I have not heard of Yoda Conditions until this post.

    When reviewing your code for Standard, I never understood why you wrote conditionals that way. It drove me a bit crazy, to be honest. But, now I know, and now I appreciate it. :)

Leave a Reply