Chapter 8. Creating Rich, Interactive UIs

JavaScript is a browser-based programming language that allows front-end developers to build everything from simple enhancements to full-blown applications. In this chapter, we will explore the use of JavaScript to enhance web applications and integrate them with Django. These enhancements include:

  • Writing effective, clean JavaScript
  • Serializing Django models into JSON
  • Utilizing JavaScript framework utilities
  • Progressive enhancement
  • Building an AJAX rating tool

The history of JavaScript implementations has been bumpy and inconsistent. We will spend the first part of this chapter reviewing some JavaScript basics and highlighting some of the language's peculiarities. Despite these problems, JavaScript is an exciting, powerful programming language that has grown from providing simple HTML enhancements to powering large, browser-based UIs.

JavaScript: A quick overview

The foundation of JavaScript includes features and philosophies from a variety of programming paradigms. It has a syntax that resembles C, advanced features derived from functional programming, and it's own, extremely powerful event-driven programming interface.

There are many web developers programming in JavaScript, but unfortunately there are a lot of bad habits around and language ignorance exists. Developers are often required to write JavaScript without adequate training or resources. This is further exacerbated by the practice of snippet programming, which is very prevalent amongst some web developers.

Understanding event-driven programming and the close relationship between JavaScript events and the browser are key to developing in the language. An event-driven language focuses on handler functions that execute only when the environment enters a certain state (called an event). Browsers fire events for almost everything that happens: when the mouse moves, when a link is clicked, or when a form is submitted.

We program in JavaScript by writing handler functions and attaching them to events. These are called listeners and there can be many listeners operating on the same event types. An important source of frustration for most developers is the inconsistency of event handling between browsers. This is the source of JavaScript's somewhat unfair reputation as a bug-prone language. Because the specific event API was not standardized early in web browser development, some browsers exhibit vastly different behaviors (or no behavior at all) for the same state or event.

As in many other web technologies, early Internet Explorer versions implemented drastically different versions than their competitors. These problems, which originated almost a decade ago, persist to this day because of the number of users who are still using old versions of this browser.

Fortunately there are numerous solutions that now exist to handle these cross-browser problems. The best is to employ a JavaScript framework. These frameworks have been designed to handle all of the special-case situations that are browser dependent, without the developer needing to think, or even know, about them. At the time of this writing, the most popular frameworks include jQuery YUI, Dojo, and dozens of others.

In Django 1.2, jQuery is included with the framework as part of the media files in the automatic admin module, django.contrib.admin. This gives jQuery a somewhat special status as far as JavaScript frameworks and Django are concerned. In the future it will likely be used to provide enhanced UI functionality in the built-in admin interface. Despite this blessing by the Django team, developers remain free to use whatever JavaScript framework they want in their own applications.

By using a framework, developers can write better, faster, more compatible JavaScript, and focus on the specific tasks at hand, not squashing browser-based bugs.

In addition to event-driven programming, JavaScript has a few other odd features that cause problems for many developers. One is the lack of modules, namespaces, and other methods of organizing code. All functions and objects defined in a JavaScript file enter the browser's global namespace. This can cause major headaches and extremely difficult debugging scenarios.

This lack of modularity has many workarounds. Some frameworks, like YUI, provide a single global object to which developers can attach their own objects and functions. Other times, developers will wrap their JavaScript files in an anonymous function that will prevent exposing local variables to the global namespace. This looks like the following snippet:

(function() {
// Javascript code 

}());

The other major practical consideration most developers encounter is the division of code amongst files. Using a typical development approach, it would be easy to segment your JavaScript application into a half-dozen or more .js files. This is good practice in any language, including JavaScript, but when it comes time for deployment a major problem looms.

JavaScript files must be embedded in the web pages they will be used. The addition of six .js files to a web page will incur a significant performance hit in the form of six additional client-server HTTP requests, download times for each file, and the separate parsing of each by the browser.

Arguably, the biggest issue here is actually the multiple server requests. Many web applications will not have a need to optimize to this level, but if you do, a six-fold increase in the number of requests needed for your JavaScript files is probably unacceptable.

What is needed is a JavaScript build tool. Often these are custom, hand-written scripts specific to the project at hand, but they almost always seek to do two things: concatenate and minify.

Concatenating JavaScript files is exactly what it sounds like: taking several files and stringing them together to form a single, larger file. This single file is then served to each web page, instead of each individual file. This has the advantage of allowing developers to segment their code in a manageable way, but avoids the performance penalties when deploying to the server.

Minification is a process by which the JavaScript is shrunk. Similar to with compression, when a .js file is minified a variety of tactics are used. Whitespace is usually removed; long variable and function names are replaced by shortened, single character names, and so on. The original minification process was developed by Douglas Crockford and is called jsmin.c. It has since been ported to a variety of languages and used as the basis for other development tools, like Packer and YUI Compress.

Minification occurs in addition to any client-server compression in use with our web servers. It also has one major disadvantage: minified code is almost unreadable and effectively impossible to debug. Still, the performance and bandwidth benefits are worth it and most serious web applications should take advantage of both concatenation and minification in their build process.

JavaScript Object Notation

Another key component to modern JavaScript development is JSON, which stands for JavaScript Object Notation. JSON is a data format typically used for transmitting data over the wire from a web application's back-end to client JavaScript running in the browser. It has other uses too: it can be used as a general purpose data format, a configuration file format, and more. Usually, though, it is used in dynamic web applications.

JSON's use has grown rapidly in some web development communities. It is now preferred by many developers for data exchange and largely takes the role formerly occupied by XML in many development shops. XML was a key component in AJAX programming, which is still the commonly used acronym for these types of dynamic JavaScript applications. However, many developers have recently begun abandoning the XML portion of AJAX for JSON due to its lighter weight, direct translation path into JavaScript objects, and generally simpler implementation requirements.

In fact, JSON is essentially JavaScript's built-in object notation with some additional rules to ensure it can be properly transmitted between machines. JSON also bears a lot of resemblance to object syntax in other languages. Specifically, it looks very similar to a Python dictionary. By sticking to a simple, common syntax, JSON avoids XML's angled bracket tax that sometimes makes reading and writing XML data more tedious.

Python and Django include special modules for converting Python objects into JSON strings. We saw how this could be done in our discussion of django-piston and the API design in Chapter 7, Data and Report Generation.

Event-driven programming

Event-driven programming is a programming technique geared around the idea of events and listeners. An applications behavior is controlled in a non-linear fashion: when the user takes action, it results in an event. That event can have one or more functions listening to it and when it fires, those listeners go in to action.

For example, all <a> tags in modern browsers support a click event. This is fired when the user clicks a link embedded in the web page. Using JavaScript, developers can write a listener function that responds whenever a link in an <a> tag is clicked.

Usually a browser will follow a link by loading the referenced URL as a fresh page in the browser. By listening for click events, however, we can prevent this default behavior or enhance it in some way. This is useful when developing interactive tools because we can design a user interface using <a> tags that have no href attribute, listen for clicks on them, and perform updates to the UI as necessary.

Web browsers provide event hooks for almost every-minute detail of user interaction. We can detect when the user pushes down a keyboard key and when they release. We can listen for mouse movements as well as mouse button clicks. Events are fired when the browser window is changed in some way, like being resized or when the back button is pressed.

By hooking into these events we can build very powerful applications that do almost anything inside the browser that we could imagine. Event-driven programming is at the heart of JavaScript. Not all browsers support all events the same way, so it's recommended that developers working in JavaScript test their code across several browsers. There are also many references online and in book form. A particularly useful website is QuirksMode.org.

JavaScript frameworks: YUI

We will briefly introduce two JavaScript frameworks in this chapter. The first is YUI, which was developed by Yahoo! and is used in web applications throughout the Yahoo! website. It is a very extensive, very centralized, and professional framework. Its official homepage is: http://developer.yahoo.com/yui/.

YUI includes more than just JavaScript tools; it also provides a CSS framework that standardizes font sizes and other settings across all browsers, including a reset.css that sets the same set of defaults across all browsers. In addition, you currently have a choice between YUI versions 2 and 3. The two are similar, but version 3 differs enough from its predecessor that tutorials and other web-based resources are not completely caught up.

YUI takes a more kitchen sink approach than some libraries. It includes a lot of very powerful built-in utilities, as opposed to using extension plugins. These utilities include everything from standardized event listener routines to full UI widgets, such as auto-complete fields, dialog panels, and data tables. It also includes very high-quality, extensive documentation.

As mentioned earlier, concatenating and minifying JavaScript is important to improve script performance and simplify development. YUI includes a configurator tool that automatically constructs the appropriate .js file for use in our web application's <link> tag. This tool lets us choose individual components and rolls them up into a single file, which can be served directly from the YUI site.

JavaScript frameworks: jQuery

JQuery is another excellent JavaScript framework. It takes a slightly different approach from YUI in that many of the utilities are provided through plugins, often developed by community developers. The community around jQuery is very large, the code is of an extremely high quality, and the documentation is generally very good. There is also a great deal of print and web-based resources dedicated to this framework.

The jQuery philosophy is to be efficient and fast, allowing developers to write the least amount of code necessary. The hallmark of any jQuery script is the $ object. This is the main interface to jQuery and is used all over the place. Its primary function is to act as a DOM selector. This means it selects and returns elements from the HTML document within which our jQuery script executes. To select all anchor tags, for example, we can use the following syntax:

$("a")

Developers new to jQuery's way of doing things may be surprised at first by how easy it can be. The best place to begin learning the framework is to work through the tutorials at http://docs.jquery.com/Tutorials.

Graceful degradation and progressive enhancement

Graceful degradation and progressive enhancement are two terms used to describe an effective approach to developing web-based applications using JavaScript. The goal is to obtain compatibility with the most browser configurations as possible while providing as much enhanced functionality as we can.

There are a lot of potential risks when developing in JavaScript and the biggest is that different browsers implement their own version of the JavaScript and DOM APIs. Recent browsers do a great job of standardizing their implementation to be as compatible with other browsers as possible. But older browsers differ wildly.

By employing graceful degradation and progressive enhancement techniques, you can ensure that even when your JavaScript code breaks, the user is still able to accomplish their task.

The other goal is to work with browsers that do not support JavaScript at all. This may seem odd at first; after all don't all modern browsers support JavaScript? Unless the user has disabled support on purpose, they should be able to parse our scripts.

While true, this point of view is short-sighted because it excludes the increasing population of users who are interacting with web applications using devices other than a computer. This includes mobile devices, everything from iPhones to basic cell phones, which have very different implementations of JavaScript.

Many other new devices are web enabled and more become so every day. Video game consoles have web browsers built-in, as do some television sets. With new kinds of internet appliances, refrigerators with LCD screens, clock-radios, and mysterious Apple tablets, the list continues to increase.

Designing for such myriad products is only going to get more difficult and JavaScript really complicates the matter. The best bet to support the widest range of devices is to employ progressive enhancement. Remember that the applications we build today could exist for years beyond what we expect; we want to ensure they'll be compatible as much as possible with whatever comes next.

To build a progressively enhanced version of your application requires a fair amount of design and planning. But the benefits, especially over the long term, can be decreased maintenance, better user experience, and higher-quality code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset