There has been a lot of talk over the last two days about loading scripts, particularly jQuery, correctly in WordPress themes and plugins, and anyone who follows me on Twitter probably knows that this is an issue I bring up a lot. When providing support for my plugins, I discover themes (and plugins) that are loading jQuery incorrectly and thus causing a conflict with my plugin all the time. It is, unfortunately, a very common issue, so now I’m going to show you how NOT to load scripts in the WordPress admin, and also walk you through the correct way of doing it.
A lot of WordPress plugins use jQuery scripts in their settings or other admin pages, and a lot of them do it incorrectly. While I don’t often see this, here is an example of how you absolutely should never do it:
1 2 3 4 | function pw_loading_scripts_wrong() { echo '<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>'; } add_action('admin_head', 'pw_loading_scripts_wrong'); |
Using a function like this will cause a second version of jQuery to be loaded into the head section of every single page in the WordPress admin. Not only will this place the extra jQuery library everywhere it is not needed, it will also most likely break most WordPress interfaces that rely on jQuery.
What about if you want to load a custom jQuery script, but not jQuery itself? You could do this:
1 2 3 4 | function pw_loading_scripts_wrong() { echo '<script type="text/javascript" src="https://yoursite.com/path/to/custom.js"></script>'; } add_action('admin_head', 'pw_loading_scripts_wrong'); |
However, if you do this, you will mostly likely be ensuing the wrath of plugin developers when they find you are breaking their correctly coded systems.
These two examples are not, however, the only incorrect ways to load jQuery and custom JS scripts. Here is another:
1 2 3 4 | function pw_loading_scripts_wrong_again() { wp_enqueue_script('custom-js', 'wp-content/my-plugin-dir/js/custom.js'); } add_action('admin_init', 'pw_loading_scripts_wrong_again'); |
You may ask why this is wrong, especially as it might look like the function does everything in an okay manner, but it doesn’t.
The first reason it is incorrect is that it is using the “admin_init” hook to load the scripts, which is not the correct hook to use. Instead the admin_enqueue_scripts hook should be used in order to ensure that the scripts are loaded at the right time.
The second reason it is incorrect is that, just like in the first two examples, the custom.js file is loaded into every single admin page in WordPress. You should never, ever do this. Always do your best to make sure your plugin is as efficient as possible and is only loading resources when those resources are needed.
And the third reason it is incorrect is because it is using a relative path for the custom.js file. It might load the file correctly in some WP installs, but it will fail in others. You should always load scripts through a complete path.
How do we fix the three problems with this example? Well, let’s start by using the correct hook:
1 2 3 4 | function pw_load_scripts() { wp_enqueue_script('custom-js', 'wp-content/my-plugin-dir/js/custom.js'); } add_action('admin_enqueue_scripts', 'pw_load_scripts'); |
That’s a little better, but not quite. Let’s now fix the problem of the script being loaded through a relative path. To do this, we should use a function that outputs the exact URL to the directory the file is stored in. When writing plugins, the best function to use for this is plugins_url(). Assuming our custom.js file exists inside of a folder called js that is in our plugin’s main folder, the exact function will look like this:
plugins_url( 'js/custom.js' , dirname(__FILE__) ) |
Add this into our function and we have this:
1 2 3 4 | function pw_load_scripts() { wp_enqueue_script( 'custom-js', plugins_url( 'js/custom.js' , dirname(__FILE__) ) ); } add_action('admin_enqueue_scripts', 'pw_load_scripts'); |
This is getting much closer to being correct, but we still have the problem of our script being loaded on all pages. How do we take care of that?
Luckily, the admin_enqueue_scripts hooks allows us to pass a variable called $hook to our pw_load_scripts() function. This $hook will contain the name, or hook, of the current admin page, which we can then use to conditionally load our scripts.
For this first example, let’s assume that we want to load some extra JS into the edit.php page, which is the primary page/file loaded when viewing a list of any post type, such as the Posts or Pages page.
1 2 3 4 5 6 7 8 | function pw_load_scripts($hook) { if( $hook != 'edit.php' ) return; wp_enqueue_script( 'custom-js', plugins_url( 'js/custom.js' , dirname(__FILE__) ) ); } add_action('admin_enqueue_scripts', 'pw_load_scripts'); |
This says the following: “if we are NOT on the edit.php page, get out of here and do not continue this function”, which means that our “custom.js” file will only be loaded if we ARE on the edit.php page. Pretty cool right?
What about some of the other pages? Perhaps you want to load scripts anytime a post list, a new post, or an edit post page are displayed? Then we can do this:
1 2 3 4 5 6 7 8 | function pw_load_scripts($hook) { if( $hook != 'edit.php' && $hook != 'post.php' && $hook != 'post-new.php' ) return; wp_enqueue_script( 'custom-js', plugins_url( 'js/custom.js' , dirname(__FILE__) ) ); } add_action('admin_enqueue_scripts', 'pw_load_scripts'); |
You can do the same thing for any page in the WordPress admin, and here is a list of some of the other pages:
- index.php – the Dashboard
- upload.php – the Media library
- link-manager.php – the Links page
- edit-comments.php – the Comments list page
- comment.php – editing a specific comment
- themes.php – Appearance
- widgets.php – Appearance > Widgets
- nav-menus.php – Appearance > Menus
- plugins.php – Plugins
- users.php – Users
- options-general.php – Settings > General
- options-writing.php – Settings > Writing
Most pages are named pretty straight forward, so it’s easy to figure out which files display which pages, but what about custom admin pages? Many (if not most) plugins create custom settings pages in the WordPress admin. How do we go about only loading JS files on those pages? It’s actually quite easy. There are multiple ways to do it actually, but the way I want to show you also assumes you have created your settings page correctly.
Settings pages are created like this:
1 2 3 4 5 | function pw_create_settings_page() { global $pw_settings_page; $pw_settings_page = add_options_page(__('My Plugin Settings', 'my-domain'), __('Plugin Settings', 'my-domain'), 'manage_options', 'my-page-slug', 'pw_callback_function'); } add_action('admin_menu', 'pw_create_settings_page'); |
The settings page is stored in a global variable called $pw_settings_pages (yours will be named differently). This variable will then be equal to the $hook variable in our admin_enqueue_scripts function, and since it is a global variable, we can access it, like so:
1 2 3 4 5 6 7 8 9 10 | function pw_load_scripts($hook) { global $pw_settings_page; if( $hook != $pw_settings_page ) return; wp_enqueue_script( 'custom-js', plugins_url( 'js/custom.js' , dirname(__FILE__) ) ); } add_action('admin_enqueue_scripts', 'pw_load_scripts'); |
We have now successfully loaded our custom script into our plugin’s settings page AND avoided loading it anywhere else within the WordPress admin. Awesome.
The process itself is quite simple and there is not a single reason you shouldn’t be doing it this way.
Very useful tutorial, thanks for posting! 🙂
I hope this can help us too! Thanks
I loved this. It worked perfectly.
Eu queria adicionar o javascript somente à página do meu plugin.
Obrigado.
Hello,
I use the function below to customize my options theme panel.
This code is working correctly but I have one little problem, so when I use this function WordPress doesn’t display this message after form update :
Well Done ! Options saved successfully
The function :
function mc_enqueue_admin_styles(){
wp_register_style(‘mc_admin_bootstrap’, get_template_directory_uri() . ‘/css/bootstrap.min.css’);
wp_enqueue_style( ‘mc_admin_bootstrap’);
}
add_action(‘admin_enqueue_scripts’,’mc_enqueue_admin_styles’ );
SomeOne can help me ?
Thanks in advance