By Dino Esposito
WURFL is a framework that provides device detection capabilities to web sites written in a variety of languages and platforms. WURFL is based on a server-side engine that is available both through a cloud service and as an on-premise configuration. WURFL.js is simply the JavaScript frontend that makes the backend engine available in HTML browser pages. We will take a closer look at WURFL.js and show you some techniques that allow you to test if you are offline and unable to access the WURFL cloud service.
WURFL.js is the name of the HTTP endpoint you invoke from your client pages to have the server-side WURFL engine take a look at the HTTP user agent of the requesting browser. At the end of the analysis, the HTTP endpoint serializes a nice JavaScript object to the output stream. In the context of the browser, this serialized JSON becomes a JavaScript object that carries valuable information about the current device and browser.
"If you are a front-end developer and implementing device detection on the server side is not an option for you, WURFL.js is your savior."
WURFL.js in Action
To use WURFL.js you need only one single line of JavaScript that references the HTTP endpoint of the WURFL server. Here’s an example:
<script type='text/javascript' src="//wurfl.io/wurfl.js"></script>
This code injects a JavaScript object into the current DOM that has three properties: is_mobile, complete_device_name and form_factor. Full details about the values and roles of the properties can be found here.
WURFL.js comes in two flavors. There is a free community edition with the behavior described in the link. In addition, there is WURFL.js Business Edition that offers a JSON object with over 20 properties as well as SLA, SSL support and a bit of extra caching for performance reasons. For more information have a look at the product page.
WURFL.js can be used in many different scenarios. The WURFL.io home page outlines a few examples such as personalization, enhancing analytics and optimizing advertising. Further, if you are a front-end developer and implementing device detection on the server side is not an option for you, WURFL.js is your savior.
For example, determining the URL to some images on the fly to ensure that smaller, or just reworked, images are downloaded on some devices. In this case, you can go with code like this:
<script> if (WURFL.form_factor == "smartphone") { $("#myImage").attr("src", "http://wurfl.io/assets/small_smartphone_pic.jpg"); } </script>
Similarly, you can use the WURFL object to redirect to a specific mobile site if the requesting device looks like a smartphone:
<script> if (WURFL.form_factor == "smartphone") { window.location.href = "http://touch.example.com/"; } </script>
So far so good.
Where’s the JavaScript Actually?
In spite of the name, and the fact that WURFL.js actually injects a JavaScript object in the client page, there’s no JavaScript file you can install on your host environment. By the time the effects of WURFL.js are actually visible, the magic has already been performed. The magic happens on the WURFL Cloud and uses the browser’s HTTP header as input to drive the device analysis.
Hey, wait a moment! WURFL.js is an online service? And how can I keep on developing my web site when I’m offline? Not an issue at all, just read on.
Test Using a Local and Fallback WURFL.js File
The key point to consider is how to be notified of when the internet connection is unavailable. In HTML, you can use the error event for this. In general, the error event is triggered whenever something goes wrong during the download of an external file such as a script file or an image. The error event is widely supported across browsers, but its use seems to be a bit controversial and potentially problematic in some cases. But let me illustrate the solution first and leave issues for later. The code below contains the highlights of the solution.
<script type='text/javascript' src="/Content/jquery-1.9.1.min.js"></script> <script type='text/javascript' src="/Content/WurflJs.Wrapper.js"></script> <script type='text/javascript' src="//wurfl.io/wurfl.js" onerror="WurflWrapper.setOffline()"></script> <script type='text/javascript' > $(document).ready(function() { $("#title").html(WURFL.form_factor); }); </script> <h2 id="title"></h2>
The really relevant parts are those highlighted on a black background. The jQuery link is only functional to the code that displays the form factor. The script block that displays the form factor, and the H2 element, is only the core of such a simple demo. The interesting part is the link to the WURFL.js endpoint and the new script file: wurfl.wrapper.js.
The onerror attribute on the script element that links to WURFL.js points to code that handles any problem during the download. If there’s no connectivity the script bound to the onerror attribute kicks in and takes control of the code. The Wurfl.Wrapper.js file is a local file you keep on your local machine during development. Here’s its content:
// Full source code of Wurfl.Wrapper.js var WurflWrapper = WurflWrapper || {}; WurflWrapper._isOnline = true; WurflWrapper.isOnline = function() { return WurflWrapper._isOnline; } WurflWrapper.setOffline = function () { WurflWrapper._isOnline = false; WURFL = { is_mobile: 'false', form_factor: 'offline', complete_device_name: 'N/A' }; }
The WurflWrapper object has two functions named isOnline and setOffline. Quite simply, the former function tells whether the WURFL object has been downloaded from the WURFL cloud. The setOffline method sets the content of the WURFL object to any content hard-coded in the wrapper file. The combined effect of the above script and WURFL.js is that you get the real user agent information if connectivity works and some hard-coded information if connectivity doesn’t work. Figure 1 shows the effect of the script.
The page remains the same and behaves as usual except that if the WURFL.js endpoint doesn’t respond you get a debug version of the WURFL object instead of a null exception.
Possible Issues with the Error Event
The onerror attribute is a bit controversial and sometimes using it may be problematic. There are two main reasons for it to be controversial.
The first is that it is not validated as XHTML by http://validator.w3.org. If you validate it against HTML5, though, it passes. If W3C markup validation is important for your web site then consider that validation doesn’t pass if you use the onerror attribute, but it does if you bind to the error event instead. You can use addEventListener or jQuery for that.
The second aspect about onerror is that—generally speaking—it can become the carrier of some hijacking attacks. If some hacker manages to inject code as simple as a IMG element that points to a missing image, the presence of onerror can run some external script within the host DOM.
<img src="missing-file.jpg" onerror="some-script()" />
Both issues are worth calling out, but frankly, they are quite unlikely to impact you up to the point of preventing the use of onerror on a web site. The XHTML aspect can be fixed by simply using script code to register an error event handler. As for the hijacking point, it is a real issue if there’s a way for external viewers to type HTML code into the DOM, as it may happen with comments on a blog post or an article. Furthermore, in this particular case the use of the onerror attribute (or the error DOM event) is even more largely acceptable as it can be easily turned off before moving to production.
Further Improvements
Using the WURFL wrapper is an easy two-step procedure. First, you add the wurfl-wrapper.js or write an ad hoc version of it. Second, you add the onerror attribute to the SCRIPT element that links WURFL.js. Looking for improvements, a nice feature to have could be making the offline WURFL object return valid information such as a default user agent configuration (i.e., generic web browser, smartphone). Yet another aspect to improve could be implementing some basic device detection on client—basically just looking for some mobile or tablet keywords with a regex—to help making the default offline configuration to be as close to the real as possible.
There’s really no reason for not trying out WURFL.js online or offline today. Go to http://wurfl.io to read about the documentation and get started.