News & Info

Daily Updates and Tech Chatter

Passing Variables To JavaScript In WordPress

We have touched on several complex subjects when it comes to writing plugins for WordPress that make use of JavaScript. In these articles we discuss built-in scripts, custom static scripts, and dynamic scripts. Dynamic scripts are the scripts that need access to information from the WordPress application environment in order to function properly, such as passing in a setting stored in the WordPress database or a variable that is calculated within PHP. There is a simple trick for getting variables into your JavaScript that is quite a bit more elegant than our dynamic scripting approach using the output buffering PHP trick we outlined earlier.

In later versions of WordPress (2.2+ if I recall) there is a function that was originally intended for language translation. It is meant to localize your scripts. You can leverage this feature to load up a variable array in JavaScript which provides an effective mechanism for getting your WordPress variables into the JavaScript environment.

Localize Script Outline

The basic premise for getting data into JavaScript is as follows:

  • Register your script in the wp_enqueue_script() action hook.
  • Localize your script when you render your shortcode.
  • Enqueue your script when you render the footer.

The important part is to use the footer enqueue method to ensure that your variable processing happens ahead of time. If you are doing a simple script you could put the register, localize, and enqueue steps all in the function you write for the wp_enqueue_script action hook. You will want to separate this into the 3 steps outlined above, however.

Register The Script

Here is an example from one of our plugins.

In the main application file, call our hook for the wp_enqueue_scripts action:

add_action('wp_enqueue_scripts',array('SLPlus_Actions','wp_enqueue_scripts'));

In the SLPlus_Actions class:

/*************************************
 * method: wp_enqueue_scripts()
 *
 * This is called whenever the WordPress wp_enqueue_scripts action is called.
 */
 static function wp_enqueue_scripts() {
     //------------------------
     // Register our scripts for later enqueue when needed
     //
     wp_register_script(
       'slplus_map',
       SLPLUS_PLUGINURL.'/core/js/store-locator-map.js',
       array('google_maps')
     );
 }

These steps tell WordPress to keep track of our JavaScript, helping do some version management, cache management, and get the script ready to be rendered. Since WordPress 3.3 will automatically set the “render in footer” flag for any script enqueued after the wp_enqueue_scripts() action hook, we don’t need to set that here.

Pass Our Variables To JavaScript

When we process our shortcode we do two things. We tell WordPress to manipulate the JavaScript rendering engine to pass in a named array of variables we want our script to know about. We also set a global define so that we know our shortcode has been rendered so we can control IF the script is rendered at all when we call our last-stage processing hooks in WordPress.

In our shortcode processing function:

// Lets get some variables into our script
 //
 $scriptData = array(
    'map_domain' => get_option('sl_google_map_domain','maps.google.com'),
    'map_home_icon' => $slplus_home_icon,
    'map_type' => get_option('sl_map_type','G_NORMAL_MAP'),
    'map_typectrl' => (get_option(SLPLUS_PREFIX.'_disable_maptypecontrol')==0),
    'zoom_level' => get_option('sl_zoom_level',4),
);
 wp_localize_script('slplus_map','slplus',$scriptData);
 // Set our flag for later processing
 // of JavaScript files
 //
 if (!defined('SLPLUS_SHORTCODE_RENDERED')) {
 define('SLPLUS_SHORTCODE_RENDERED',true);
 }

Enqueue The Script

Now that we have our script registered and told WordPress to setup our environment we can now render our script. However we only want WordPress to render the script if our shortcode was processed, which is what the global define was for. We also find that some themes skip the footer processing which disables footer scripts, so we are going to force footer scripts to run within our late-stage WordPress action hook.

In our SLPlus_Action Class:

/*************************************
 * method: shutdown()
 *
 * This is called whenever the WordPress shutdown action is called.
 */
 function shutdown() {

 // If we rendered an SLPLUS shortcode...
 //
 if (defined('SLPLUS_SHORTCODE_RENDERED') && SLPLUS_SHORTCODE_RENDERED) {

 // Register Load JavaScript
 //
 wp_enqueue_script('slplus_map');

 // Force our scripts to load for badly behaved themes
 //
 wp_print_footer_scripts();
}

Using The Variables

Now our script only renders on pages where our shortcode appears and we now have our WordPress variables easily accessible from within the script. How do we reference these in our script? That’s the easy part, here is an example:

In our store-locator-map.js file:

/**************************************
 * function: sl_load()
 *
 * Initial map loading, before search is performed.
 *
 */
function sl_load() {
 if (GBrowserIsCompatible()) {
 geocoder = new GClientGeocoder();
 map = new GMap2(document.getElementById('map'));
 if (parseInt(slplus.overview_ctrl)==1) {
 map.addControl(new GOverviewMapControl());
 }
 map.addMapType(G_PHYSICAL_MAP);
 // This is asynchronous, as such we have no idea when it will return
 //
 geocoder.getLatLng(slplus.map_country,
 function(latlng) {
 if (!slplus.load_locations) {
 map.setCenter(latlng, parseInt(slplus.zoom_level), eval(slplus.map_type));
 }

 var customUI = map.getDefaultUI();
 customUI.controls.largemapcontrol3d = slplus.map_3dcontrol;
 customUI.controls.scalecontrol = slplus.map_scalectrl;
 customUI.controls.hierarchicalmaptypecontrol = slplus.map_typectrl;
 map.setUI(customUI);

 if (slplus.disable_scroll) { map.disableScrollWheelZoom(); }

 if (slplus.load_locations) {
 sl_load_locations(map,latlng.lat(),latlng.lng());
 }
 }
 );
 }
}

Obviously our example has variables we culled out of our localize_script section above, but you get the idea. The slplus prefix is based on the 2nd parameter in our wp_localize_script function call in the previous section. The variable name after the slplus prefix is the key of the $scriptData variable that we passed into that function call as the 3rd parameter.

Summary

By using wp_localize_script you can make use of the wp_register_script and wp_enqueue_script WordPress functions to manage your script loading and variable passing. This is a much cleaner environment for managing scripts than using the PHP output buffer tricks discussed earlier.

However, not all plugins play well with each other. Not all themes follow the rules. In many cases the methods we outline here may not work. In our experience, however, the more plugins that use these modern methodologies the more stable and efficient WordPress is. Eventually those plugins and themes that do not play well with others will atrophy and only those that are well crafted and utilizing best methods will survive.

Tags: , , , ,

1 Awesome Comments So Far

Don't be a stranger, join the discussion by leaving your own comment
  1. Andrew Taylor
    June 22, 2012 at 9:53 AM #

    Hey just wanted to let you know as of wordpress 3.3 you can enqueue scripts directly from your shortcode function.

    and example would be

    wp_enqueue_script(‘MY_SCRIPT_NAME’, plugins_url(‘MYSCRIPT.js’, __FILE__), array(‘jquery’), ‘1.0’, true);

    then localize an array of variables

    wp_localize_script(‘MY_SCRIPT_NAME’, ‘my_js_variables’, $MY_VARIABLES);

    WordPress will check dependencies like jQuery and if they do not exist in the already they will get printed in the footer with your script.