Part 2: Lazy load 3rd party deps and make plugin extensible


Let's now try to make our plugin better. We started with the assumption that a 3rd party dependency - the HERE Maps API - is included in the document with a script tag.

However, in order to make life easier for people that use your plugin we can go a little beyond that. To simplify life for others, sometimes you have to complicate yours. But that is the fun part.

Let's keep making life easy for users of our plugin: we are wrapping a 3rd party library, 'cause their API is really hard to use. Why should developers bother to drop a script tag to load the 3rd party library, and take care of keeping it up to date? Can't we do it within our plugin instead?

The first thing we can try to do is dropping into our plugin some code that does the following:

  1. creates a script DOM Element
  2. sets the source attribute to the 3rd-party dependency's URL
  3. adds an onload callback that only initializes the plugin only when the script has loaded and we append the element to the page

This does not work very well. The 3rd party script is loaded asynchronously, therefore if we chain method calls right after the plugin initialization:

$('.selector').miniHERE({}).miniHERE('zoom', 16).miniHERE('center', [lat, lon]);
the plugin will try to execute them immediately, before the external script has loaded, and will therefore fail as objects and method will not be there.

We can solve this problem by taking advantage of jQuery's Deferred object.

The Deferred Object can register multiple callbacks into callback queues, invoke callback queues, and relay the success or failure state of any synchronous or asynchronous function.

In jHERE I creaded a script loader that uses deferreds to enqueue methods calls. Only once the Deferred is resolved the initialization happens and all the methods are call in the order they were enqueued.

After I released the first version of jHERE, I realized there were some features that were missing. Features that aren't useful all the times, but that can be nice to have sometimes: routing, shapes, or geocoding/reverse geocoding helpers.

Rather than just dropping all those features into the codebase – which will make the plugin bigger and harder to maintain –, I looked for a way to make the plugin extensible.

Luckily, beacuse of the way the plugin is structured, we can just expose the plugin's prototype via a static method. This makes very easy to add extensions that make new methods available via the plugin's jQuery UI-like interface.

Have a look at how that is done in jHERE's source code.