Justin Tadlock

How to load JavaScript in the WordPress admin

One of the things that often frustrates plugin and theme developers is other plugins and themes not properly loading JavaScript in the WordPress admin. The majority of the plugins and themes (especially themes) that load JavaScript load it on every single page in the admin.

This is not good.

The problem with loading JavaScript like this is that it creates conflicts with other plugins and even WordPress itself. And, quite frankly, I’m tired of my number one support question response being, “Please deactivate all your plugins to see if this corrects the issue.”

In this tutorial, I will walk you through the steps of loading your JavaScript only on the pages that are specific to your plugin.

Do you need JavaScript?

Before moving on, you should ask yourself if you plugin/theme actually needs JavaScript in the admin. If you’re trying to create some fancy-schmancy tabbed interface that doesn’t use the WordPress standard UI, you’re doing it wrong.

The only time you need to load JavaScript in the WordPress admin is when it’s absolutely necessary for what your plugin or theme is doing. In most cases, you simply need to be using the standard functions already built for you in the Settings API. This requires no JavaScript whatsoever.

There are cases when additional JavaScript is necessary. That’s what this tutorial is about — appropriately loading JavaScript on your plugin pages when JavaScript is crucial to your plugin’s functionality.

The proper hooks

Forget every other bit of code you’ve seen that loads JavaScript in the admin. There’s two hooks that you can use:

  • admin_enqueue_scripts: For enqueuing JavaScript files.
  • admin_head-$pagename: For printing code directly to the header.

Those are the only two hooks you need to worry yourself with. Under no circumstances should you use admin_init or admin_menu (as many plugins/themes do) to load JavaScript. You should also never load scripts without a hook, which is extremely common in themes.

Loading JavaScript files

First, let’s take a look at adding a standard options page for a plugin. Your code would look something like the following.

add_action( 'admin_menu', 'my_example_settings_page' );

function my_example_settings_page() {
    add_options_page( 'DevPress Example', 'DevPress Example', 'manage_options', 'my-example-page-name', 'my_callback_function' );
}

This is fairly standard for most developers. The trick is to figure out how to load JavaScript only on that page.

Let’s assume you need to load a JavaScript file using the wp_enqueue_script() function. Your code would look like the following.

add_action( 'admin_menu', 'my_example_settings_page' );

function my_example_settings_page() {
    global $my_settings_page;

    $my_settings_page = add_options_page( 'DevPress Example', 'DevPress Example', 'manage_options', 'my-example-page-name', 'my_callback_function' );

    add_action( 'admin_enqueue_scripts', 'my_admin_enqueue_scripts' );
}

function my_admin_enqueue_scripts( $hook_suffix ) {
    global $my_settings_page;

    if ( $my_settings_page == $hook_suffix )
        wp_enqueue_script( 'my-example' );
}

When you add an action to the admin_enqueue_scripts hook, your action (function) gets passed the parameter of $hook_suffix. What this allows you to do is check if $hook_suffix matches the name of the plugin’s settings page. $hook_suffix will change depending on the page that’s currently being viewed in the admin. Therefore, your script will only load when it’s needed.

Printing JavaScript in the admin <head>

Let’s suppose you’re just adding an extremely small snippet of code to the admin <head> area. Again, you don’t want to load this on all pages in the admin, even if it’s just a couple of lines. It can still conflict with other plugins. So, let’s build off your original settings page function. Your code would look like the following.

add_action( 'admin_menu', 'my_example_settings_page' );

function my_example_settings_page() {

    $my_settings_page = add_options_page( 'DevPress Example', 'DevPress Example', 'manage_options', 'my-example-page-name', 'my_callback_function' );

    add_action( "admin_head-{$my_settings_page}", 'my_admin_head_script' );
}

function my_admin_head_script() { ?>

<script type="text/javascript"></script>

<?php }

What we’ve done here is use the admin_head-$pagename hook to load a custom script only in the header for the plugin’s settings page. $pagename is just the name of the page currently being viewed in the admin.

Not just for scripts

This isn’t too hard. I’m not asking that you learn how to program nuclear missiles for launch. If you’re knowledgeable enough to add a custom settings page and add JavaScript in the WordPress admin, it should take you all of 30 seconds to appropriately load your scripts so that they don’t load on other admin pages.

Don’t stop with JavaScript though. The exact same rules apply for custom stylesheets too. You should even use the same hooks.