Posted on

WordPress 4.5 Breaking JavaScript (aka Where Is My Map?)

Ever since WordPress 4.5 rolled off the press there have been numerous complaints about websites breaking.   Numerous reports are coming into our Store Locator Plus forums and support email telling us “our map broke when they updated our website”.  The problem?  jQuery. To be more specific the problem is not jQuery but  how some plugins and themes implement jQuery in WordPress.

WordPress 4.5 started shipping jQuery version 1.12.3 as the “official” version of jQuery being used  with WordPress core. jQuery 1.12 has more stringent controls than previous versions.   The most obvious, jQuery 1.12 no longer “hides” some of the syntax errors that lay dormant in plugin code.   If there is malformed  or incorrect syntax, jQuery 1.12 will complain.  Your browser will most likely stop executing ALL scripts from that point forward.  As you can imagine, this causes things, like themes and plugins  to break.
Continue reading WordPress 4.5 Breaking JavaScript (aka Where Is My Map?)

Posted on

SLP Zoom Controls

Store Locator Plus 4.4.36 has an adjustment for zoom controls that addresses a change in the Google Maps API.

In older releases of the Google Maps JavaScript API the rendering engine would often render the map with one-or-more pins on the edge of the map. These pins would often be inaccessible as they fell under the Google map controls. Sometimes the info bubble would be cut off. The Store Locator Plus JavaScript interface would adjust for this by pulling the zoom level back one level on anything other than the 3 widest views (global zoom levels) which were not affected by the edge-of-map anomaly.

SLP Google Pins Cut Off (older Google API)
SLP Google Pins Cut Off (older Google API)

In the continued Google Maps JavaScript API improvements the edge-of-map pins stopped happening. It wasn’t until recent customer feedback that we realized this had changed. In Store Locator Plus 4.4.36 the zoom tweak is no longer auto-adjusted for non-global views of the map. Store Locator Plus will now use the Google default bounding boxes which keeps all pins within the map bounds. The info bubbles also auto-adjust to bring the entire bubble into focus on the map to prevent text from being cut-off.

SLP Google Normal Pins
SLP Google Normal Pins
Posted on

Store Locator Plus v. 4.3.18 update, Google Maps JavaScript API information

Google Maps JavaScript API Geocoding issues, Part 2

Following up on the recent updates to Store Locator Plus and the Google Maps APIs, the Store Locator Plus developer found some major changes to the Google Map query structure that is effecting query returns when the geocoding function intiates from the SLP search. SLP 4.3.18 provides support to alleviate this issue while an alternative solution is investigated. For more information on how Google Maps Javascript Application Programming Interface (API) works with Store Locator Plus and the issues please watch Lance’s video, Google Map JavaScript API part 2.

Store Locator Plus 4.3.18

The recent patch to SLP is intended to prevent the endless looping of the geocoding query from your search form to Google. The endless loop may manifest itself as a result of a Google server glitch, and may freeze up your interface, preventing your map from loading at all. This was an issue when the Google server was down and coming back with no results found for locations, thus initiating the query over and over. The recent development is occurring due to changes to the Google Map API and is discussed in the developers video above. 4.3.18 also fixes the default email link that was incorrectly rendering under the results section. Additionally, 4.3.18 adds support for renaming extended data field slugs to improve the Extended Data Manager add-on interface. See the SLP Change Log and the developer’s short video for more information.

Thank you to those forum posters who are working with us when reporting any issues and providing the SLP support team with their Plugin environment.

Change Log

Posted on

WordPress Boolean Options and JavaScript : Handle With Care

JavaScript WordPress Banner

After chasing my tail for the past 5 days I finally uncovered the source of a bug in my code that was causing Store Locator Plus to not initialize properly on fresh installs. The culprit? How WordPress handles booleans. In particular, how WordPress handles the persistent storage and the JavaScript localization of booleans.

The important lesson:

WordPress option storage is done using STRINGS*.
* there is a caveat here: SERIALIZED options are stored with the data type,
single options (non-arrays) are stored as strings

WordPress JavaScript localization uses PHP and JavaScript DATA TYPES.

 

What does this mean for plugin coding?

If you are passing WordPress options that have been fetched from the wp_options table with get_option to JavaScript via the wp_localize_script() method your booleans that are set to true/false will be passed to JavaScript as ‘1’/’0′. On the other hand, if you are setting a PHP variable to true/false and passing that to JavaScript they are set as a JavaScript boolean value of true/false.

The difference is important.

In JavaScript you write this for booleans:

if ( myoption.booleanvar ) { alert('true'); }

However you write this for the string version:

if ( myoption.booleanvar === '1' ) { alert('true'); }

How did this break my code?

When my plugin environment loads for the first time it uses an array to store option defaults. Since the user has not yet set or saved the plugin options the get_option call returns an empty array and those defaults are employed. However my option array looked something like this:

$options = array( 'booleanvar' => true );

To further compound the problem, I introduced yet ANOTHER issue by converting what was previously a single-element option to a serialized array in the latest patch release.   Serialized data is MUCH faster.  When you are fetching/setting more than a single option for your plugin.   To be a good WordPress citizen I’ve been slowly migrating all my legacy options to a single serial array.   HOWEVER the update did something like this:

$old_option = get_option('booleanvar');  // singular boolean options are stored as strings '1'/'0'
$options = array ( 'booleanvar' => $old_option ); // $old_option is a string
update_option( 'my_option_setting', $options);
delete_option('booleanvar');

My code is a lot “deeper” than shown here, but the basic idea was to fetch the pre-existing value of the singular option and store it in my options array. I save it back out to persistent storage and blast the old non-serialized option out of the database. THIS conversion for existing sites works well as the singular option variables will store and retrieve boolean data as a STRING. Thus my option comes back as ‘1’/’0′ depending on how the user left it and all is good in JavaScript-land.

HOWEVER, if you note above the NEW DEFAULT is to set booleanvar as a boolean with a default value of true. When storing a compound option (named array) with update_option it stores and retrieves values using the DATA TYPE.

$options = array( 'booleanvar' => true );
update_option( 'my_option_settings', $options );  // serial options are stored as proper data types
$options = get_option( 'my_option_settings');

Here the $options[‘booleanvar’] is set to a proper boolean.

As you can probably guess, this creates inconsistency in the Javascript.

Why? Because my JavaScript has been written for the most common use case which is one where users have set and saved the plugin options at least once. The JavaScript code uses the string comparison code shown above, ( myoption.booleanvar === ‘1’ ). It works as expected every time after the user has saved the options at least once.

Why does it work after options are saved? Because WordPress returns the boolean variable as the string value ‘1’. You can see this for yourself by playing with the update_option() and get_option() functions in WordPress to store/get a boolean true value. Since my code uses the stored values if they are set my booleanvar is not taking on the default true setting after the first save, it is coming back as ‘1’ which is what JavaScript expects to see.

The Lesson?

Use string values of ‘1’ and ‘0’ for your WordPress option values any time you are not using 100% serialized option values. It ensures consistency throughout your application by following the precedence set by the WordPress get_option function.

Yes, you can get away with using boolean true/false values. It even makes the code more readable, IMO. However it can cause issues if you ever decide you need to pass those values along to your JavaScript functions with wp_localize_script() if you are not 100% certain you are using pure non-translated boolean variables throughout.

If you are ever uncertain of your true data types add a gettype($varname) debugging output to your plugin code. Remember that simple print_r statements will convert booleans to strings as well, use gettype to be certain of what flavor variable you have inside PHP.

Posted on

WordPress Add JavaScript to Specific Admin Page

Huh?  “wordpress add javascript to specific admin page”, what the heck is that?   That is the first thing I “googled” when I discovered I was “doing it wrong” so I could learn how to do it right.

As a plugin developer it is one of the more important principles of plugin development.  It is one that took me far too long to learn and based on all the things the break when you install various themes and plugins, I am not alone in that department.

Why It Is Important

Why is this so important?  You load your script on EVERY PAGE in the worst case scenario, or EVERY ADMIN PAGE in the half-right scenario.

Doing it wrong has two notable side effects, neither of which is a good thing:

  1. It slows down page loads unnecessarily.   Think about it?  The server reads a file from disk (slow), loads it into memory, and does nothing.   More stuff in memory = higher chance for paging (putting memory blocks on disk) = more slowness.   Unless you are running a server on solid state drives (SSD) then disk I/O is the worst possible thing you can be doing in terms of performance.
  2. It breaks other scripts.  Not always.  Often.   Your script manipulates the browser JavaScript processing stack. It loads stuff into memory.  It can change the logic flow or the DOM.   Many times it is having unintended consequences and all for a script that will not run in most cases.

What you really want is to only load the JavaScript (or CSS for that matter) onto YOUR admin pages only.

If you are coding plugins DO NOT LOAD YOUR CSS or JavaScript globally!

Use The Hooks

Easy.   There are WordPress hooks specifically designed for this.   The JavaScript-centric hook is called ‘admin_print_scripts-<handle>’.     That <handle> part is important.   It is unique to YOUR admin pages and how you get stuff to happen on JUST your admin page.

For reference, if you are doing CSS stuff there is also an equivalent ‘admin_print_styles-<handle>’ equivalent.

However, I am going to take a slightly different route.    MOST times you are likely adding CSS and JavaScript to your admin page, not one or the other.   As such I don’t want to write TWO hooks to load my stuff, though in a larger system I may do so for clarity.    But I’m a lazy programmer and while I don’t like super-long multi-faceted functions, I feel this case is simple enough to glom the script and CSS together.  So I’m going to use the ‘admin_head-<handle>’ hook instead.   I feel that is a name that makes sense for loading up both together, especially if  my JavaScript is not dependent on styles being in place first.

Curious on how this all hooks into WordPress?

Look in the admin-header.php file in the wp-admin subdirectory.  You will find this call sequence right at the top:

</p>
<p dir="ltr" style="padding-left: 30px;">do_action('admin_enqueue_scripts', $hook_suffix);</p>
<p dir="ltr" style="padding-left: 30px;">do_action("admin_print_styles-$hook_suffix");</p>
<p dir="ltr" style="padding-left: 30px;">do_action('admin_print_styles');</p>
<p dir="ltr" style="padding-left: 30px;">do_action("admin_print_scripts-$hook_suffix");</p>
<p dir="ltr" style="padding-left: 30px;">do_action('admin_print_scripts');</p>
<p dir="ltr" style="padding-left: 30px;">do_action("admin_head-$hook_suffix");</p>
<p dir="ltr" style="padding-left: 30px;">do_action('admin_head');</p>
<p style="padding-left: 30px;"> 

General Rules

Some general rules first.

NEVER use hard-coded output of JavaScript in your apps.   Create a .js file and enqueue it.   Use wp_localize_script to pass in variables from  your PHP script.

Always develop with debug mode on.

Always get a page handle when creating an admin page, you need to that to invoke the hook.

Always develop with debug mode on.

Always use classes.  Do not use procedural code.  It sucks.

Always develop with debug mode on.

Seriously.  Turn on full debugging in your development environment.  There are far too many (90% I’d guess) plugins out there that are barfing warnings all over sever logs every day.   Multiple by millions of installs.   Times thousands of visitors.   You’ve got billions of lines of warning messaging spewing forth all over the Internet and server logs every day.   No wonder my Internet connection is slow as hell some days.

The Simplified Version

While this technique may not be perfect, it gives you the general construct you need to do it right.   The short version shows you the concept, it is not cut-and-paste code.  Go to the WordPress Codex and look this stuff up.

This is the “down and dirty” version using a class construct as a namespace only.   In the real world you will want to invoke the class as an object and avoid the static declarations and direct calls, but hey… its another step toward “don’t pollute other plugins or core WordPress with my crap” nirvana.

<pre>class MyPlugin {   
    static function add_my_pages() {
       $handle = add_options_page(...);   
       add_action("admin_head-$handle",array('MyPlugin','loadMyJS'));
   }

   static function loadMyJS() {
       wp_enqueue_script('myjs',plugin_dir_path(__FILE__).'/my.js');
   }
}
add_action('admin_menu', array('MyPlugin','add_my_pages'));</pre>

So that is the “quick and dirty” version.

The whole thing starts with the add_action(‘admin_menu’) call.   This runs whenever the WordPress dashboard loads up the admin pages.

It then calls the add_my_pages function within the MyPlugin class.

MyPlugin::add_my_pages() will build our admin page by using the add_options_page() function of WordPress.  If you look that up you will discover what parameters to pass to make it build your admin page.  You will likely be adding a “createAdminPage()” method to the MyPlugin class, but that is beyond the scope of this article.   The important point here is that when WordPress does connect your plugin admin page to the system it will return back a unique handle for that page.  You need this for the next step.

MyPlugin::add_my_pages() then tells WordPress that whenever your admin page loads, fire off the loadMyJS() method for your plugin.   How?   WordPress has a special hook called admin_head-<something>.  That SOMETHING is the handle that you got from the add_options_page() call.    That hook is ONLY called when your admin page loads.    Which means the next step ONLY happens when your admin page renders, not every single page on the site.

When your admin page loads, the MyPlugin::loadMyJS() fires.   This uses the standard WordPress enqueue scripts method to load up your JavaScript and put it in the header of the admin page.    This ensure your JavaScript only loads when you need it.

Perfect.

So that is the general process.   Go forth and learn how to incorporate this in your plugins.  Then teach others.

The entire WordPress community thanks you for it.

Oh… and the CSS stuff I mentioned?  Rename “loadMyJS” to “loadMyJSandCSS” for clarity, then throw in the wp_enqueue_style() calls.

Posted on

Passing PHP Variables to JavaScript

One of the things we do fairly frequently in our WordPress plugins is pass PHP variables to JavaScript.   We use this methodology to send a number of dynamic elements to the JavaScript processor without having to do AJAX or JSONP calls after the script has loaded.  Pre-processing and passing variables into JavaScript when the script is loaded is a far simpler mechanism.

 WordPress provides a simple, yet oft overlooked, method for getting your PHP data into JavaScript.   Using wp_localize_script() quickly maps a PHP named array to similar structure in JavaScript.    To do so you follow two simple steps:

1) Register or Enqueue your script.
see: http://codex.wordpress.org/Function_Reference/wp_enqueue_script

2) Localize your script.
see: http://codex.wordpress.org/Function_Reference/wp_localize_script

We have found some caveats for some themes.   Most importantly, make sure you select for “late loading” or “load in footer” so the script can be localized BEFORE it is rendered in the browser.  The other option is to register the script using wp_register_scripts() in the wp_enqueue_scripts hook then later load the script in a wp_footer hook using wp_enqueue_scripts().     Just keep in mind that not all themes support wp_footer().

Posted on

SLP Maps and Late Loading Scripts

Since the Store Locator Plus 3.2 release, our SLP plugin now defaults to the less efficient “Early Loading” mechanism for rendering our required JavaScript.  This adds a lot of unnecessary overhead for other pages on the site but works with more themes.

Pro Pack users have an option to turn off “early loading” with the “force load javascript” checkbox on the main settings page.   Turn this off if your theme and plugins are “late loading friendly”.  Your site will just a little faster on all the non-SLP pages.

The Discussion

We often run into sites that do not load the Store Locator Plus map ever since our version 3.X update that uses late loading to be more intelligent about how scripts are loaded.   Here is an excerpt from an investigation with a client installation related to this issue that will shed some light on the problem.

 

 I need to create an option for “early loading” and “late loading” of scripts.  There are simply too many themes or plugins that break late-loading plugins.

 Late loading is WAAAAYYYY more efficient.   What it means is we can detect “hey, this page is showing a SLP map” and only then load all the heavy javascript to support it (google maps API, our scripts, etc.).
 
Early loading means we load all of our scripts on every single page, regardless of whether the page needs it or not.  The bonus… it always works.    The downside, it is slower.  Especially on very busy sites.
 
However, in the past 6 months since we changed to the smarter model we have come to realize there are THOUSANDS of plugins or themes that are just not well engineered.   Thus we realize we must engineer our plugin to be even smarter.
 
With version 3.2 Store Locator Plus will default to “early loading” and always load our scripts.  It will work on more sites but be slower.    The Pro Pack will have an option to turn on “late loading”, removing the early loading and making the plugin more efficient.  If it doesn’t work (like on your site) you simply uncheck the box and go back to the slow but working method.
 
In the long run you are better off using only themes and plugins that do not break plugins that take advantage of the late loading feature available since WordPress 3.2.  Your site will load faster as more & more plugins start using this methodology.
 
The short version, it is going to take quite a bit more effort but this is the best solution.   The fix for your site is to select a theme & plugins that are well engineered.  Your new site is not working because the theme is not calling the proper WordPress 3.2+ action hook sequence.
The bottom line of all this.  Some plugins and themes are not well engineered.  When we release version 3.2 of SLP we will provide an option to “be slow and work around bad plugins/themes” or “be fast, I am using a great theme and well designed plugins”.

Update

After days of looking for workarounds to the problem we have discovered that a key element for Store Locator Plus to function efficiently is the use of wp_localize_script.  This is the cleanest and most efficient way to get PHP variables, like your map settings, into the JavaScript engine for Google Maps.
Some themes, it turns out, do not properly support late loading scripts.  In order for wp_localize_script to work after a shortcode has been rendered the script must be loaded in the footer, or “late loaded”.
We do this to ensure that any attributes you add to the shortcode are passed to the JavaScript engine.  This is the only way to override map defaults on a per-page basis.   Thus, if your theme does not support late loading scripts (which is a WordPress 3.x+ standard) then Store Locator Plus may not work on your site.
The first thing to do is ask your theme provider to update their theme to properly support late loading and localized scripts.   Then check back here for updates.  We are working hard to make our plugin compatible across as many themes and plugins as possible.

Update #2

A follow-on discussion with our client about why we do late loading and why “other plugins don’t seem to break but SLP does”.
Most plugins will not have a problem because they are not nearly as complex as Store Locator Plus.
We use 3 very inter-dependent elements of WordPress and JavaScript to make the plugin as efficient as possible and not slow down your site.   All 3 pieces need to fire at the right time and the process cannot be interrupted.
1) Register the script early in the WordPress process.
2) Localize the script (very few plugins do this, less than 0.1%).  This is the best method for getting WordPress settings into JavaScript.   It is relatively new, very few developers know about it.  As such almost no plugins do this.  It is sad because WordPress promotes this as THE WAY to get JavaScript & WordPress talking efficiently.
3) Enqueue the script.
99.9% of plugins will never break because they don’t localize scripts.  Instead they do the old inefficient (and insecure I might add) way of getting WordPress data into JavaScript.    Sadly since 99.9% of plugins that need WordPress data in JavaScript just copy what someone else did, instead of learning how to do it properly, the problem gets replicated more than TWO YEARS after WordPress provided a better solution.
I know because I did the same thing 2 years ago until I discovered localization of scripts and spent time learning how it works and why it is better.
So the short version… it does not surprise me that other plugins don’t break when someone (Media Grid) inadvertently short-circuits late loading JavaScript like that found in SLP.
The checkbox, BTW, turns OFF late loading JavaScript. SLP does not break but every page load is going to be slightly slower on your site as long as the box is checked.
For “fun” you should look at a random page and see all the CSS and JavaScript that loads.   80% of it is never needed/used for the page you are looking at.   That is because 99.99% of plugins don’t care they just force their stuff to load ALL THE TIME whether it is needed or not (early loading).   We explicitly try to NOT do that mostly because we need to talk to Google.  Run your site on a slow Internet connection and you’ll see why we try to only load up our stuff when absolutely necessary.
Posted on

Mobile Cross Platform Development : Cordova

Apache CordovaApache Cordova (aka Phonegap).

A little clarification on the name.  The NEW name will be Apache Cordova.   After Adobe bought the development firm that was working on Phonegap the Phonegap project itself was given to Apache Software Foundation to maintain its open source roots and continue development.  As of this writing the transition is still underway with MOST, but not all, elements haven taken on the Apache Cordova persona.

Our First App On Cordova

Our first app that we wrote using Cordova was the Abundascan application for Abundatrade.   The first release is a simple app that uses the camera to scan a barcode then sends the UPC to the Abundatrade server to get real-time prices that they will pay for used books, CDs, DVDs, and video games.    Functionally the app is simple and works well.    However one key element here is the primary reason we started with Cordova over other cross-platform tools like Corona, the camera.

Turns out that many of the cross-platform tools do NOT support the camera interface. That shot down Corona right away, which otherwise looked promising.

Cordova And Cameras

The nice part about Cordova is that the system is basically a wrapper for the native web browser.  That means coding in HTML5, CSS, and JavaScript.  It also has a number of third party plugins that hook native mobile functionality (via Java or Objective-C) to a JavaScript class.   In theory that sounds great.

Luckily there is a good camera scanner app that reads UPC,and other machine-enabled codes like QR, codes created by Google released in the ZXing project.  The ZXing applet is ported and ready to use for Cordova as a plugin.

Cordova Camera Caveats

The problem is that theory does not work out in reality.   The plugin for Android works wonderfully.  The plugin on OS-X, not so much.  Not surprising that a Google app talking through JavaScript to an Apple owned OS and development environment doesn’t work well.  Apple really does go through a lot of effort to put a stranglehold on their development pipeline.

The bottom line, we have yet to get the camera plugin to work on IOS4 or higher devices.   In theory the demo app works, but we’ve yet to see it on our iPod Touch or newer iPhones.

The Android Version of Abundascan is out, but we still are having issues with Cordova on IOS.

Our Second App

Our second app is a little less ambitious as it is testing the waters for a larger project.  This app is simply a screen that shows your current GPS location with exact latitude and longitude.   Where Am I Standing? is a free app that does just that.   To make it a little more interesting we wanted to add an info page with our name and logo and a little bit of graphic “window dressing”.

Again, here we ran into multiple issues.  This time noticeable right on the Android before we even attempted the iPhone release.    We want a simple app with no glitches yet there are several things that still aren’t right.  We can spend a good bit more time addressing in convoluted code to workaround quirky UI elements.  Others are as-yet un-fixable.

Technically it was easy & works well. Aesthetically it is NOT of the caliber I want it to be at.    As I dug deeper into this I uncovered a lot of hidden secrets about mobile app development and why 99.99% of these cross-platform tooks like Cordova fail.

The Compromises

Here are the “little details” that are compromises I don’t want to make.  I want to build QUALITY apps.  That means making them as perfect as we can, and this stuff is far from it:

Swipe Right / Left : I wanted to be able to simply swipe the main screen to see the info screen (“created by Cyber Sprocket”).     One swipe works, then it breaks.  This is a fundamental issue in the browser kit Cordova uses as the foundation for their solution.   Google developers refuse to address it saying it is “as designed”.

Vertical Page Scrolling : I don’t want ANY page scrolling, jitter, etc.   The pages are too “tall” and are scrollable if you swipe up or down.  This can be fixed but takes extra coding to do so.   What a pain.

Button Highlighting : Sometimes the highlights on the info/home buttons “stick”.  This is a built-in feature of jQuery Mobile and Cordova.  It is wonky at best.

Screen Hesitation: Even on a mid-range phone with just about the simplest app possible, sometimes going to the “info” page hesitates, same with going back to home.

Navigation History : Go to info, then back to home.   Each time you do this is adds to the “history”.  Do it a few times and your back button is loaded up with a bazillion loops of home/info/home.   Again, fixable with code (mostly) but why?

Summary

While Apache Cordova will help you build apps using technologies you likely already know like HTML5 and JavaScript, the implementation is far from simple.  Getting stuff to work on more than one platform requires extensive knowledge of all the quirks.  Like IOS requires a special onDeviceReady hook or it won’t even load properly.   The apps also feel “heavy”.    The UI is not responsive and, depending on the hardware, often misbehaves.

While Apache Cordova may be a great tools for building a functional prototype or possibly building corporate apps where users may value function over form, in my opinion Cordova is a compromise.

Yes,  you can probably build a well-polished UI.   But it takes a LOT of extra effort because you are hamstrung by the JavaScript/web interface.  Of course you can write custom Java or Objective-C hooks and/or make your own plugin, but isn’t that point to get away from native custom code?    You can also get around *some* of the quirks with a good bit more coding, but how you get around which quirks often requires intimate knowledge of the quirks for the particular mobile OS that is giving you problems.

I’m sure we can build quality apps with Apache Cordova, but this is not about CAN we do that, it is about what are the benefits of doing so.  From a business perspective there appears to be little gained here over a process that includes solid architecture, documentation, code design, and good old-fashioned cross-platform awareness and porting.

Posted on

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.

Posted on

WordPress/JavaScript : Selective Enqueue

In the past couple of articles about WordPress and JavaScript we touched on several methods for managing JavaScript in WordPress. For simple “static” scripts or built-in WordPress scripts, such as jQuery, the standard register and enqueue methods provide all the control you need to invoke your scripts.

However there are several issues that come up when you decide you only want scripts to load when you render a specific shortcode. Here we touch on these issues and how we resolve them in our plugin. There are other methodologies as well, but here are the methods that worked for us.

Load Script For Shortcode Pages

One of the issues we’ve run into is loading the JavaScript only on pages where the shortcode is rendered. The problem is that for this trick to work you must load the scripts in the footer of the rendered page. WordPress (since v2.6) does provide a “load in footer” flag when registering or enqueing a script. As we learned, however, this is fatally flawed in all releases prior to WordPress version 3.3.

In versions prior to WordPress 3.3, the “load in footer” flag will actually render your scripts immediately after rendering the page content. There are no actions you can hook to between the time your shortcode is rendered and the point that the scripts are rendered. This causes a number of issues when you are trying to selectively load your scripts when your shortcode is rendered.

Post 3.3 Process

For sites running WordPress 3.3+ the best practice for selectively loading scripts, as described in our previous posts, is:

    • Register your script via the wp_enqueue_scripts() action hook.
    • Enqueue your script via your shortcode rendering script
      -OR-
    • Set a global flag when rendering the shortcode, then enqueue your script with the shutdown() action hook

As we found, not all themes play well with rendering scripts in the footer of a page.  Thus, our preferred method is to set a global flag when we render our shortcode and then create a custom shutdown hook.   This way we can force footer scripts to be rendered immediately after we enqueue any scripts we need to make our shortcode work.

For example, in our main plugin PHP file:

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

Then in our SLPlus_Actions Class file:

/*************************************
 * 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('google_maps');
wp_enqueue_script('slplus_map');

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

This works wonderfully in our WordPress 3.3+ installations.

However, in version prior to 3.3 the enqueued scripts are completely ignored at this point in the page rendering process.

Pre WordPress 3.3 Methods

There are several methods we tried in versions prior to WordPress 3.3, none of which are a great solution.  In these earlier versions of WordPress you MUST enqueue your scripts via the wp_enqueue_scripts() method, so they are rendered in the header of the page.   In versions greater than 2.6 these scripts will appear in the “footer” (which is really not the footer, but post-content rendering) but you still must enqueue them in the wp_enqueue_scripts() action. BTW, as a side note, do NOT enqueue in the init hook.  This is an old school method that we found does not work properly in all cases.

As we found, however, you cannot turn the script on/off at that point even if you selected the “load in footer” flag.    Some things we tried:

  • Deregister/denqueue the script if our shortcode was NOT rendered.
    The problem is that there is no hook that runs between content rendering and script rendering, so you can’t test your “shortcode rendered/not rendered” flag.
  • Register only in wp_enqueue_scripts(), then enqueue in the shortcode rendering.
    These mid-page enqueues are ignored.  WordPress changed this in 3.3 so it will render scripts in the footer, but pre 3.3 this does not work.
  • Register only in wp_enqueue_scripts(), then enqueue in the shutdown/footer/post-content-action-of-any-kind hook.
    Same problem as above.

In short if you don’t enqueue  in the header with wp_enqueue_scripts() on pre 3.3 versions of WordPress you will get inconsistent results.

Selectively Enqueue Scripts 3.3 and Pre-3.3

So how do we address pre-3.3 and 3.3+ versions of WordPress?   We certainly want to eliminate all the overhead we can and make our plugin as efficient as possible.     In 3.3+ we don’t want the script to render at all, but this is not compatible with pre 3.3 release.   Here is what we do today that is a compromise between both worlds:

  • Enqueue the script in the wp_enqueue_scripts() action hook with the footer flag set.
  • Set a global flag when we render the shortcode.
  • If the global flag is NOT set, deregister/deenqueue the script via a wp_footer() or wp_shutdown() action hook.

By using this methodology, WordPress 3.3+ will prepare the scripts to be enqueued in the footer.  Since they really do enqueue in the footer now, we can now intercept the process PRIOR to the rendering via the late-stage action hooks like wp_footer or wp_shutdown.    So in version 3.3+ the deenqueue call will stop the script from being rendered via  last minute “woah, don’t do this” request.

In versions prior to 3.3 the script will always be rendered on every page.   Unfortunately that is the price to pay for pre version 3.3 users if we are trying to be as efficient as possible for users of the latest releases of WordPress.  Yes there are other methods that work, but at the price of slowing down everyone that uses the latest version of WordPress.

Don’t Enqueue Pre 3.3

Since we mentioned it, here is the basic premise if you want to use the above methodology and not enqueue for version 3.2:

  • Add a hook to wp_enqueue_scripts() as per above.
  • In that hook, get the current post ID.
  • Grep the content of that page and check for your shortcode (WordPress has a function that returns your shortcode regex).
  • Only if the content has the shortcode do you enqueue.

The reason we don’t like to do this is there is extra processing involved.  For larger pages this can be fairly intensive.  On a low-traffic site your users will never notice the extra half-second or less, but on large traffic sites or sites with a longer pages this can be a big hit on server resources.

Summary

As we have found, getting scripts to only load when you want them can be a chore.  The simple solution is just enqueue your scripts for your shortcodes all the time.  Your plugin will always work, however this comes at the expense of the overall site performance for your plugin users.    In our case we don’t want to load up the Google Maps API JavaScript on ever page and post on our client sites.   We only want the scripts to load when they are showing the location map.

Unfortunately not all themes play nice with the header and footer actions in WordPress.   In addition, WordPress 3.3 is the first release that actually gives us the level of control we need to render scripts in a proper controlled fashion.

Posted on

WordPress and JavaScript Part 2

WordPress

This is our second article in a series about working efficiently with JavaScript in WordPress. There are a lot of sites and lots of examples on how to implement JavaScript in WordPress. Many of the articles we came across were incorrect or outdated. What was once the viable, or possibly the only available, method for implementing JavaScript hooks a few years ago with WordPress version 2.X are not the most efficient methods today. In our second article we touch on this point and continue to distill the information we’ve uncovered that have helped us create better JavaScript hooks in our plugins.

This follow-on to the first article unveils some key points about using JavaScript in WordPress:

  1. Not all plugins follow best practices.
  2. Some very popular plugins (one of which has 6,000,000 downloads) completely bypasses wp_register_script and wp_enqueue_script, instead doing print <script src="blah"> right in the HTML output header.
  3. These plugins, and themes for that matter, thwart any attempts to abide by best practices in your own plugin.

What we found when working on various client sites is the techniques in our last article are not foolproof.

The main issues we discovered:

  • Some scripts force an archaic version of jQuery to be used, in our case v1.4.X when the current WordPress version of jQuery is 1.7.1. Our plugin, for one, requires jQuery 1.7 or higher as we follow best practices for jQuery and use the .on() method for invoking actions.
  • Some plugins kill the wp_enqueue_script process well before the WordPress action stack has exited. In our case it was being shut down well before the content, and thus shortcodes, were rendered.

Our workaround:

– Register AND Enqueue the scripts in the wp_enqueue_script action.

But…

This loads your scripts on EVERY PAGE. Exactly what we want to avoid.

The solution that gets around “mis-behaving” plugins? Use the much-hated, at least by me, filter to check if the current post has your shortcode.

However, unlike other archaic methods for implementing this test with a direct database query, you can use the built-ins of WordPress to make this run a bit faster. It still accesses the database so it is slower than simply firing enqueue when the shortcode is rendered but it is a price we have to pay if we want to live in the same neighborhood with our miscreant neighbors.

How to filter your enqueue script:

function setup_scripts_for_plugin() {
   global $post;
   $pattern = get_shortcode_regex();
   if ( preg_match_all('/'.$pattern.'/s',$post->content,$matches) &&
        array_key_exists(2,$matches) &&
        in_array('our_shortcode', $matches[2])       ) {     wp_register_script('jquery');   wp_enqueue_script('jquery'); }

Summary

That’s it. Now your scripts will be loaded only on the page with the shortcode you specified in the in_array() call.

In our example we are registering the jQuery built-in, but this works just as well with any script, including your own custom static or dynamic scripts. Speaking of dynamic scripts, we have a new trick for that too… coming up next…

The corresponding presentation for this discussion is available here:

Adobe PDFWordPress Plugin Tips & Tricks Apr 2012

Posted on

WordPress and JavaScript Part 1

WordPressIntroduction

For those that were not present, we had a discussion that was about wpCSL and using JavaScript in a WordPress plugin.

The part of the discussion that would be of interest to the general public revolved around the use of wp_register_script and wp_enqueue_script and the best practices for implementing scripts.

WoAdobe PDFrdPress Plugin Tips & Tricks Mar 2012

 The Key Points

  1. Call your function to REGISTER scripts early in the action stack for WordPress. Typically hooking into the wp_enqueue_scripts action.
  2. Call your function to ENQUEUE the scripts when you know you’ll need them. Typically this should be when the shortcode is rendered. This prevents your scripts from loading on EVERY page in Wordpress.
  3. There are three basic script types, per my definition of scripts, that are important:
    1. Built-in ScriptsWordPress has approximately 30 scripts that ship with or are directly accessible from within WordPress.
    2. Static Scripts: your custom javascript that depends on no external PHP variables or data from the database
    3. Dynamic Scripts: custom javascript that references PHP variables or data from the database
  4. Dynamic scripts can use the ob_start()/ob_content() feature of PHP to render the JavaScript.
  5. Hook dynamic scripts in LATE in the action stack of WordPress, I prefer wp_print_footer_scripts.
  6. Dynamic scripts implemented this way should use a global flag (a property of our wpCSL driver class in our case) to only render the script when the shortcode was rendered. Unlike enqueue_script this footer action hook is called for ALL pages.

Summary

There are a couple of follow up discussion based on findings from working “in the field” on client systems. Those will be posted next.

Posted on

Upgrade Issues from MooTools 1.2.4 to Mootools 1.3.2

This past week we worked on some site updates for Abundatrade.  During the updates we attempted to upgrade Mootools from 1.2.4 to 1.3.2.  Unfortunately this did not go as well as expected.  After 8 hours of trying to get it to work we ended up rolling back to Mootools Core 1.2.4 with Mootools More 1.2.5.1.   Here are some of the pitfalls.

$empty Is Not Defined

The first problem was with the FormCheck library from floor.ch.   The library requires the “old-school” $empty function definition from MooTools.   This has been deprecated in later versions.   It also turns out it is a pain to replicate, though we were able to patch around this by adding a this.$empty function() {} definition to the JavaScript library.    After doing so we ran into more problems with undefined methods so we gave up and ended up loading MooTools Core 1.3.2 with compatibility.  That resolved both the $empty definition problem as well as some other issues we had with failing code.

Unintended Recursion

The bigger problem that forced us back to v1.2.4 was an unintended recursion problem in one of our AJAX calls that queues and consumes requests to/from a back-end server script that feeds JSON back into the main web document. With all versions up to 1.3.X the system works as we expect, you put in a UPC, click “Add Item”, it is sent to the back-end for real time pricing lookups, and a single row is added to an on-page table showing the item and the offer price. With version 1.3.2 the call to the back-end system is now working as a factorial function.  The first time you add an item you get one call to the back-end. The second time you get 2 calls, by the 6th added item you have a table full of duplicates that is growing exponentially. Not good.

We dug around for answers for most of the day yesterday, but nothing obvious was uncovered. The basic culprit is a form submit handler that eventually does something like this:

function MyHandler() {
… this.set(‘send’,func () { do stuff; });
this.send();
}

The first time through it works perfectly. Subsequent iterations are looping through the this.set call, as if this is now an array of handler objects.  There must be a way to reset the form handler stack to be a single instance, but damned if we can find it. The problem appears to be triggered by a change in the MooTools library that now handles the anonymous function definition differently as it is no “array aware”.

MooTools 1.2.X Problems

Unfortunately, staying with MooTools 1.2.4 presents another problem.  The spinner class breaks for Internet Explorer 9.  With the spinner class in place the submit form handler fails.   Thus for MooTools 1.2.4 we are stuck with a subset of the UX.

The failing code:

        document.id('top_content').set('spinner',
            {
                hideOnClick:true
            }
            );
        document.id('top_content').spin();

 

Summary

There is probably a design flaw in our code, but it is not easy to unwrap and simply turning on MooTools 1.3.2 with compatibility mode is not fixing it.  So much for the easy way out.  For now we’re back to MooTools 1.2.X and moving on.  Other projects await.   If you have any hints on what the issue may be please share.

Posted on

Code to Read

A few days ago, Richard and I were talking about code to read. I think that you can learn a lot as a programmer by simply reading the code of others, in much the same way writers improve their craft by reading the works of their peers. So the obvious question, then, is what to read? There is obviously a lot of shit code out there, and if you decide to read some bad code with the intent of honing your own skills, it may very well have the opposite effect.

So below are some of my thoughts on code that is worth reading, broken up by language. I have restricted this to languages we use here at Cyber Sprocket, but I urge everyone to contribute anything useful they can think of, regardless of whether or not it’s written in a language we use.

JavaScript

The source code for my browser of choice, Conkeror (http://conkeror.org), is fantastic. It is based on the same XULRunner platform that is the foundation for Firefox, and our own ColorFish application. The code for Conkeror has no hesitations about using the more esoteric, non-standard features of XULRunner’s JavaScript support. I’m talking about things like using `get` and `set` to create getters and setters, and `let` within arbitrary blocks to create closures over variable bindings.

The Conkeror code can show you some cool ways to take advantage of Mozilla’s JavaScript engine, which can benefit you directly at Cyber Sprocket. Not because we always have the luxury of *exclusively* targeting Firefox, but Conkeror can also show you things you can’t do if you want to be cross- platform.

Python

If you want to learn some advanced Python, like how to use meta classes in a real-world situation, then look at the code for Django. Specifically the code for django.db.models.ModelBase. It can really show you the differences between things like __new__() versus __init__() for creating classes. Keep in mind that Django uses Python 2, and there are notable differences in Python 3. Right now I don’t know of a killer app in Python 3 that I could recommend to you.

PHP

Grab the code for PHPUnit (http://www.phpunit.de) and check it out. It is a fantastic example of well-structure PHP code. The gritty details of the style are not the best, which is to say that it breaks a number of our internal standards. But the logic of PHPUnit is very sound. And on top of that, it really makes good use of PHP’s object system by taking full advantage of things like standard library interfaces (e.g. `Countable`).

And besides, how many PHP applications do you see use type hinting in function declarations? Really? PHPUnit is great through-and-through. Also—we should use PHPUnit for unit testing our PHP applications, in my opinion. But that’s another discussion for some other time, like a standards meeting.