WordPress just marked it’s 10th Anniversary on May 27, 2013 and it’s little surprising to see even today many WordPress Developers are not using jQuery scripts properly. This is a big problem resulting conflicts in WordPress Themes and Plugins. As a plugin and/or theme developer, it is your responsibility to use jQuery correctly within your projects. So developers, please pay attention: this is how to include scripts in your themes properly. And guess what? It’s really easy.
1. Loading jQuery
The most common mistake that WordPress developers make is loading jQuery by printing the <script>
tag into the header.
<script src="<?php bloginfo('template_url'); ?>/scripts/jquery.min.js" type="text/javascript"></script>
You shouldn’t do this. If you do, any plugin/theme that requires jQuery will be broken as a result of your code. This is because jQuery will be loaded twice, which will throw errors and break stuff. Instead, you need to use Enqueue functions.
/** * Simple way to load jQuery * * @uses wp_enqueue_script action */ function textdomain_load_jquery() { wp_enqueue_script( 'jquery' ); } add_action( 'wp_enqueue_script', 'textdomain_load_jquery' );
So, let’s talk about the following Enqueue Functions to load jQuery:
– wp_register_script()
– wp_deregister_script()
– wp_enqueue_script()
– wp_dequeue_script()
– wp_script_is()
– wp_localize_script()
1.1 wp_register_script
wp_register_script()
function should be used to register your scripts which you will need to load it by using wp_enqueue_script()
function. This function safely handles the scripts dependencies.
Syntax
<?php wp_register_script( $handle, $src, $deps, $ver, $in_footer ); ?>
Arguments
$handle: The name of the script. You need to add the name that is unique. So, always use your plugin/theme textdomain as prefix of the script. For example in Catch Box theme, we use the name for jQuery as catchbox-jquery.
$src: The URL of the script. You should never hardcode URLs to local scripts and use plugins_url()
for plugins and get_template_directory_uri()
for themes. Remote scripts can be specified with a protocol-agnostic URL, e.g. //otherdomain.com/js/their-script.js.
Default: None
$deps: Dependencies (optional, array). The names(s) of other scripts that our scrips depends on; scripts that must be loaded before this script. Set false if there are no dependencies.
Default: array()
$ver: The version number of our script (optional, string). You can choose between providing a string, setting the parameter to null or leaving it empty. If you set it to string, it will be added to the output code like textdomain-script.js?ver=2.0. If you leave the parameter empty, the version of your WordPress installation will be added as the version number. If you set it to null, nothing will be added.
Default: false
$in_footer: Normally when you enqueue this registered script, it will be loaded in the section. If this parameter is true the script is placed at the bottom of the
section.
Default: false
1.2. wp_enqueue_script
Now you know how to register the script but your registered script will not be loaded automatically. So, to load the script you need to use
wp_enqueue_script()
function. This function check if the script that you are trying to enqueue has already been loaded and will not load the same scripts more than once. So, if you see any website loading jQuery multiple times, you now know that they have not enqueued the script properly.
Syntax
<?php wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer ); ?>
Arguments
wp_enqueue_script()
takes the same arguments as wp_register_script()
, but if you register your scripts first, you can just call them by the handle in wp_enqueue_script.
1.3 wp_register_script vs. wp_enqueue_script
wp_register_script()
function makes your scripts available for use while wp_enqueue_script()
functions loads the script to the theme/plugin.
You can register without enqueuing. But to load the script on the page, you need to enqueue. If you register the script, you can then enqueue it by its handle alone. If you don’t register it ahead of time, you will need to provide the full parameters in the enqueue function.
You can skip the register function for the scripts that you are going to enqueue right away. Also, you don’t need to register scripts which are included in WordPress See the list here.
1.4. wp_deregister_script
wp_deregister_script()
function is used to remove a registered script(s). This function is used if you want to remove WordPress default script and register your own script instead.
Syntax
<?php wp_deregister_script( $handle ); ?>
Arguments
$handle: The name of the script handle that you want to remove.
Example: Deregister WordPress default jQuery and load jQuery from Google CDN:
/** * Deregister WordPress default jQuery * Register and Enqueue Google CDN jQuery */ function textdomain_jquery_enqueue() { wp_deregister_script( 'jquery' ); wp_register_script( 'jquery', "http" . ($_SERVER['SERVER_PORT'] == 443 ? "s" : "") . "://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js", false, null ); wp_enqueue_script( 'jquery' ); } if ( !is_admin() ) { add_action( 'wp_enqueue_scripts', 'textdomain_jquery_enqueue', 11 ); }
1.5. wp_dequeue_script
wp_dequeue_script()
function dequeue the script that has been enqueued before using wp_enqueue_script()
fucntion. But to dequeue the script, the function has to be hooked to where WordPress prints scripts. If dequeue action is executed before the script is enqueued, the function will only eat up resources to no avail.
Syntax
<?php wp_dequeue_script( $handle ); ?>
Arguments
$handle: The name of the script handle that you want to dequeue.
1.6. wp_script_is
wp_script_is() function is used to determine if a script has been registered, queued, printed, or is waiting to be printed. It returns the value as True or false.
Syntax
<?php wp_script_is( $handle, $list = 'enqueued' ); ?>
Arguments
$handle: The name of the script handle that you want to check.
Default: None
$list: This is optional and you can use the following list to query.
registered – script was registered through wp_register_script()
enqueued / queue – script was enqueued
done – script has been printed
to_do – script has not yet been printed
Default: enqueued
1.7. wp_localize_script
The wp_localize_script
functions is really cool and can be used for 2 different purposes. 1. Primarily, it can be used to make your JavaScript file translation ready. Thus the name “localize” is used. 2. But it can be used for passing configuration options from PHP to JavaScript.
Syntax
<?php wp_localize_script( $handle, $object_name, $l10n ); ?>
Arguments
$handle: The name of the script that you are attaching the data for.
Note: wp_localize_script()
must be called after the script it’s being attached to has been enqueued or registered. It doesn’t put the localized script in a queue for later scripts.
Default: None
$object_name: The name of for the JavaScript object which will contain the data. You need to add the name that is unique. So, always use your plugin/theme textdomain as prefix of the script.
Default: None
$l10n: The data itself and it can be either a single or multi-dimensional array. Each key in the array will be setup as an item in our JavaScript object.
Default: None
Example: Making “Some string to translate” text translation ready:
<?php wp_enqueue_script( 'some_handle' ); $translation_array = array( 'some_string' => __( 'Some string to translate' ), 'textdomain', 'a_value' => '10' ); wp_localize_script( 'some_handle', 'object_name', $translation_array ); ?>
Example: Making text message of click button translation ready.
<?php /** * Function to Make to make the alert text translation ready */ function textdomain_load_script() { wp_enqueue_script( 'textdomain-alert-script', get_template_directory_uri() . '/js/alert-script.js'); wp_localize_script('textdomain-alert-script', 'textdomain_script_vars', array( 'alert' => __( 'Thanks for clicking me. Have a nice day', 'textdomain' ) ) ); } add_action( 'wp_enqueue_scripts', 'textdomain_load_script' );
/*! * JS file to show the alert message * This is alert-script.js file which is enqueue in textdomain_load_script() function above */ jQuery(document).read(function($) { $('#nice_button').on('click', function() { alert( textdomain_script_vars.alert ); }); });
Example: Passing configuration options from PHP to JavaScript.
Here I would like to take an example of Catch Evolution Free theme slider code.
First, you will see the function catchevolution_scripts_method()
and catchevolution_pass_slider_value()
in file catchevolution-functions.php
. catchevolution_scripts_method()
function properly register and enqueue catchevolution.slider.js
file and it’s dependents. catchevolution_pass_slider_value()
will get the data from Theme Options panel and uses wp_localize_script
to store the data in js_value which you can call later in your JS file.
/** * Register & Enqueue scripts * * hooks action wp_enqueue_scripts */ function catchevolution_scripts_method() { global $post, $wp_query, $catchevolution_options_settings; $options = $catchevolution_options_settings; // Register jQuery cycle all and JQuery set up as dependent on Jquery-cycle wp_register_script( 'jquery-cycle', get_template_directory_uri() . '/js/jquery.cycle.all.min.js', array( 'jquery' ), '2.9999.5', true ); // Enqueue Slider script wp_enqueue_script( 'catchevolution-slider', get_template_directory_uri() . '/js/catchevolution.slider.js', array( 'jquery-cycle' ), '1.0', true ); } } // catchevolution_scripts_method add_action( 'wp_enqueue_scripts', 'catchevolution_scripts_method' ); /** * Function to pass the variables for php to js file. * This function passes the slider effect variables. */ function catchevolution_pass_slider_value() { // Get ready to load the Theme Options panel values global $catchevolution_options_settings; $options = $catchevolution_options_settings; // Get slider effect option value from Theme Options panel $transition_effect = $options[ 'transition_effect' ]; $transition_delay = $options[ 'transition_delay' ] * 1000; $transition_duration = $options[ 'transition_duration' ] * 1000; // Run localize script to pass php value in js_value wp_localize_script( 'catchevolution-slider', 'js_value', array( 'transition_effect' => $transition_effect, 'transition_delay' => $transition_delay, 'transition_duration' => $transition_duration ) ); }//catchevolution_pass_slider_value
Finally, you will see the catchevolution.slider.js
file where it loads the dynamic value pass from wp_localize_script
/*! * Custom scripts for jQuery Cycle set up * Adding the js_value from function catchevolution_pass_slider_value */ jQuery(window).load(function() { var transition_effect = js_value.transition_effect; var transition_delay = js_value.transition_delay; var transition_duration = js_value.transition_duration; jQuery('#slider-wrap').cycle({ fx: 'transition_effect, // name of transition effect (or comma separated names, ex: 'fade,scrollUp,shuffle') pager: '#controllers', // element, jQuery object, or jQuery selector string for the element to use as pager container activePagerClass: 'active', // class name used for the active pager element next: '#nav-slider .nav-next', // advances slideshow to next slide prev: '#nav-slider .nav-previous', // advances slideshow to previous slide timeout: transition_delay, // milliseconds between slide transitions (0 to disable auto advance) speed: transition_duration, // speed of the transition (any valid fx speed value) pause: 1, // true to enable "pause on hover" pauseOnPagerHover: 1, // true to pause when hovering over pager link width: '100%', containerResize: 0, // resize container to fit largest slide fit: 1, after: function (){ jQuery(this).parent().css("height", jQuery(this).height()); } }); });
2. Using No Conflict Mode
The jQuery library included with WordPress is set to the noConflict()
mode (see wp-includes/js/jquery/jquery.js). This is to prevent compatibility problems with other JavaScript libraries that WordPress can link. So, it is important that we code our jQuery dependent scripts correctly to accommodate it.
This is really simple. You just need to replace your global $ shortcut to jQuery as in the noConflict()
mode, the global $ shortcut in not available. See the example below
/*! * Coding jQuery Proper Way * using jQuery instead of $ */ jQuery(document).ready(function(){ jQuery(#somefunction) ... });
But we can see jQuery coded using $ shortcut which will throw an error, or use the $ shortcut as assigned by other library. No don’t use it like below:
/*! * Coding jQuery Wrong Way * using $ shortcut without wrapper */ $(document).ready(function(){ $(#somefunction) ... });
However, if you really like to use $ shortcut instead of jQuery then you can use the wrapper around the code.
See the following examples
/*! * Coding jQuery Proper Way * using wrapper * to be executed after the document has been loaded */ jQuery(document).ready(function($) { // Inside of this function, $() will work as an alias for jQuery() // and other libraries also using $ will not be accessible under this shortcut });
/*! * Coding jQuery Proper Way * using wrapper * to be executed in an anonymous function */ (function($) { // Inside of this function, $() will work as an alias for jQuery() // and other libraries also using $ will not be accessible under this shortcut })(jQuery);
There is one more alternative, that is assigning jQuery to another shortcut of your choice. See the example below:
/*! * Coding jQuery Proper Way * Assign jQuery to $s */ var $j = jQuery; $j(document).ready(function(){ $j(#somefunction) ... });
I am using:
var $=jQuery.noConflict();
This works fine.
Any reason why not to use this?
You didnt explain anything here on how to add custom js scripts……………..useless.
On my website, the width of the header is not suited to the width of the menu.
It gives me the below error “.”
What can I do
Thank you
Tomàs