Introduction

I created some web widgets for the London’s Design
Museum and learned a few useful things in the
process. Although all the necessary information can be found on the web, I
couldn’t find a really comprehensive guide about doing this with
jQuery so I decided to write this one. I’ll cover only techniques which are
specific to web widgets so you should already be familiar with
JavaScript, jQuery and web development if you want to follow easily.

The interesting points will be:

ensure the widget’s code doesn’t accidentally mess up with the rest of
the page,

dynamically load external CSS and JavaScript files,

bypass browsers’ single-origin policy using JSONP.

Don’t worry if all this doesn’t make sense to you yet, we’ll see in details
what these techniques are used for in the context of building web widgets.

What is a web widget?

A web widget is a component, a “chunk of web page” that you provide for other people to display data coming from
your site on their own pages. A widget typically contains a slightly
complex mixture of HTML, CSS and JavaScript. You will want to hide that complexity
and make it as easy as possible for people to include your widget on their
pages.

Widget usage

The widget developed in this tutorial can be embedded in a web page with just
two HTML tags: one script tag to load the widget and one container tag
(usually a div) to indicate where we want to put the widget on the page:

That’s really all that a web site owner would need to include our widget on her
pages. The code referenced with the script tag will take care of downloading
the different assets composing the widget and update the content of the
container.

Can’t it be even simpler?

It is technically possible to create a widget that doesn’t require a
destination container by using document.write() within the widget’s
code. Although some widget providers do use that approach, and it can reduce
the code necessary on the host page to just one script tag, we believe it’s not
worth it because:

document.write() cannot be called once a page has loaded. This means our
widget’s code would have to run immediately when the browser finds the script
tag. Since we want this code to fetch data from our server, that could cause
page loading to be interrupted for a while and it would make the page feel
slow,

by using a separate tag which will contain the widget on the page, we are free to place our script tag anywhere. We can for instance put it at the bottom of the page, which is a recommended practice.

Code isolation

Because you can’t predict what JavaScript code will be running on the page which
uses our widget, we need a way to ensure that it doesn’t clash
with any other JavaScript code included on the host page. To do that, we just
enclose all our code within an
anonymous function and we call that function. The variables we create in our
functions won’t interfere with the rest of the page.

You can view the result in your browser. As
you can see the foo variable defined in an anonymous function doesn’t clash with the global foo variable.

Always declare variables with var

In order to avoid tampering with JavaScript variables defined outside of our
widget, we must declare all our variables with the var keyword, otherwise
we might be updating existing variables instead of creating our own. It’s anyway
a good practice to use var
every time you create a variable.

Loading JavaScript libraries

If your widget will use a fair amount of JavaScript, you’ll likely want to
use a JavaScript framework such as jQuery. Since we can’t rely on having
jQuery loaded on the host page, we’re going to load jQuery dynamically using JavaScript:

First we create a local variable which will hold our version of jQuery. Then we
check for the presence of the version of jQuery we need, so that we don’t
download it again if by chance it’s already there on the host page. Here we’re
being strict about the version number, but if you’ve tested your code with
several versions, you can allow these versions as well, or even use a regular
expression to match a major version number. To load the library, we then simply
create a script element which points to the URL of the library file. In case
we’re dealing with a poorly written page which doesn’t have a head, we
simply append our script tag to the document element.

Of course, we want to use the library in our code, but before we do so, we must
be sure that the library has loaded completely. We do that by defining a
scriptLoadHandler function which will be called once the library has loaded.
For most browsers (Firefox, Safari, Opera, Chrome, etc.) we just need to assign
that function to the onload attribute of the script element. Internet
Explorer before version 9, as often, has its own way. Here it requires us to
register an onreadystatechange handler which will call our main function when
the ready state is either complete or loaded. As people helpfully pointed out
in the comments, IE9 and Opera support onload, but also still support
onreadystatechange, so we make sure that we use only one of them by testing
the presence of a readyState attribute on the script tag, in
order to avoid calling our load handler twice.

Why test for two states in Internet Explorer’s old onreadystatechange handler?

Once the script is ready to use, Internet Explorer will set readyState to
either complete or loaded, depending if it’s loaded from the cache or
downloaded from the network. For instance, if you test only for loaded, the
main function won’t be called if you navigate away from the page by clicking a
link and then come back to it using the back button of your browser.

Before this line gets executed, window.jQuery points to our own version of jQuery which
would have overwritten any older version of the library. Calling
window.jQuery.noConflict(true) restores window.jQuery to its old value and
returns a reference to our freshly loaded version, which we store in our local
variable. It also restores the $ variable to its old value, so that we can
still use another library such as Prototype.

Finally, scriptLoadHandler calls our main function in which we can use
our version of jQuery and build our widget.

Now that we’ve dealt with the underlying plumbing, we can finally get to the interesting
part.

Loading data from our site

Since our widget is going to display data on the host page as HTML, there is
probably no need to use an intermediate format such as XML or JSON to get data
from our server. We can directly get HTML and update the content of the widget
container using that HTML.

Let’s say our widget is going to display a list of headlines. The server can
output a chunk of HTML such as:

If the host page was located in the same domain we could just use regular AJAX (or to
be pedantic in this case AHAH) to get
this HTML and update the DOM. But in the context of a web widget, the host page and
the server providing the widget’s data will usually be in different domains and browsers
will simply not allow an AJAX request to be made to a different domain than the
one which has served the page. This security restriction is know as the
Same Origin
Policy.

Luckily, there is a way around this: browsers allow to use script tags to
include scripts from other domains. We can use this open door to get data from
our server using a simple technique known as
JSONP. The idea of JSONP is to
create a script tag which will fetch JSON data wrapped into a function.
If we create a script tag such as:

We then define the
function which will get the JSON data as a parameter:

functionour_callback(json_data) {
// do stuff with json_data
}

Now the good news is that jQuery supports JSONP
natively
and will take care for us of creating a script tag, creating a callback function
and pass the name of that callback to the server as a parameter. In this case
the only data we’re interested in is the piece of HTML we want to insert in the
widget container. On the server side, we will use that parameter to build a
piece of JSONP such as:

Of course, real world widgets will be much more complex, both on the client and
on the server, but hopefully you now have a better understanding of the basic
steps involved.

Dealing with errors on host pages

Although the code above will work in a lot of cases, Shyam Subramanyan from Listly has
reported an issue with using jQuery(document).ready in the main function.
The problem can happen when the host page already has loaded jQuery and has its own
jQuery(document).ready hooks. If there are any errors in any of the host page
jQuery hooks, the one inside the widget main function will never get executed.

The solution Shyam suggests is to write custom code to test if the page is
ready to host the widget. Instead of waiting for the whole document to be ready,
only check for the presence of DOM elements or other JavaScript objects that your widget depends on. The code he’s been successfully using for Listly looks like this:

Conclusion

Another question that comes often is how can you make your widget configurable.
As suggested in the comments, if you want to minimize markup you could use the
query string of your widget URL and add an id to the script tag. By doing this
your script would be able to locate its own script tag, parse the query string
of its own URL and configure itself. A more straightforward approach could be to
simply add some invisible markup to the embed code of your widget. That’s how
social sharing buttons typically do it.

I hope this tutorial has been of interest. Thank you everyone for reading and special thanks to Corey Hart for his valuable help
with dynamic loading of jQuery. Make sure you browse the comments as some of them
contain useful advice about how to make your widget customizable, how to
reduce even further the size of the embed code, etc.

If you want to dig deeper into the topic, I highly recommend the book Third-Party JavaScript. I found it to be a very pleasant and informative read.