Implementing jQuery UI in a Web Application

A lot of people thought I was crazy for wanting to develop my own PHP framework, and 1400 hours of discovery and development later, they may have a point. At the end of the day, though, I have an extremely powerful and flexible framework for making database-driven web applications. Where even I drew the line, however, was with javascript. I made the decision to use jQuery because its design philosophy seems similar to my own.

My plan is to integrate jQuery into my PHP framework, but I need to learn a lot more about how jQuery works and refactor some of my core structural components to accommodate it. In the meantime, I can start to implement jQuery in individual applications.

Downloading jQuery

To enable jQuery requires only one javascript file, available from jquery.com. I chose to copy down the latest minimized version (jquery.min.js) to my web server to have as a local file. Almost everything is driven through events.

To have all the interface elements available, both javascript and stylesheets are required, available as themes from http://jqueryui.com/themeroller. I again downloaded the relevant files to my web server: When you select a theme from the gallery, there is an option to download the package (and you can fine tune which parts of a theme you want or need). Themes are also customizable.

When you download a theme, there a number of directories and files, but there are only two important ones: the theme folder (which contains the base stylesheet and all the supporting images) and jquery-ui javascript file.

Making jQuery Available

Now, you need only reference the downloaded javascript and stylesheets. In the applications I build, I tend to use abstract application modules that handle the common tasks (like loading libraries and content necessary for most of the modules in the application).

Partial Listing: rsrc/master/ApplicationModule

abstract class ApplicationModule extends IWModule
{
   ...
   
   function pageDidLoad($page)
   {
      $page->addJavascript('js/jquery.min.js');
      $page->addJavascript('js/jquery-ui-1.8.14.custom.min.js');
      $page->addStylesheet('css/smoothness/jquery-ui-1.8.14.custom.css');
   }
   
   ...
}

The rendered page for any ApplicationModule subclass has a header block with the appropriate references.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<link rel="stylesheet" type="text/css" href="/pod/lib/css/public.css" />
<link rel="stylesheet" type="text/css" href="/pod/lib/css/editor.css" />
<link rel="stylesheet" type="text/css" 
   href="/pod/lib/css/smoothness/jquery-ui-1.8.14.custom.css" />
<script src="/pod/lib/js/jquery.min.js"
    type="text/javascript" charset="utf-8"></script>
<script src="/pod/lib/js/jquery-ui-1.8.14.custom.min.js"
    type="text/javascript" charset="utf-8"></script>
</head>
<body>

...

</body>
</html>

Now, my application is ready for some jQuery UI goodness (to be presented in later articles).

Escaping Frames

Every once in a while, a third party will try to trap your web site in a frame on their site. Sometimes, it's merely a lack of awareness about DNS that causes them to do so. Sometimes, it's mailcious. Regardless, there's an easy way to escape!

<html>
<body>

<script type="text/javascript">
    if (top != self) top.location.replace(location);
</script>

<!-- your web site here -->

</body>
</html>

Adding Javascript to an Application Module

There are numerous ways for an application module to reference javascript (or stylesheets).

Application Module delegate method

One delegate method (callback) in an application module is pageDidLoad(), which allows the module to update the page's characteristics after its instantiation. Typically, this mechanism is used to add javascript for scripts unique to that application module.

Partial Listing: BlogViewer.php


class BlogViewer
{
    function pageDidLoad($page)
    {
        $page->addJavascript('js/search.js');
        $page->addStylesheet('css/blog.css');
    }
    
}

?>

The IWPage instance passed as an argument ($page) prefixes the addJavascript() argument with the APPL_LIB_DIR constant and adds it to the <head> tag of the rendered HTML page. Suppose you needed an external javascript file. In that case, there are two possible approaches, both illustrated below.

Partial Listing: MapViewer.php


class MapViewer
{
    function pageDidLoad($page)
    {
        $javascript = 'http://maps.google.com/maps/api/js?sensor=false';
        
        // Pass an IWURL object as the addJavascript() argument
        $page->addJavascript(new IWURL($javascript));
        
        // Directly update the head() element of the IWPage instance
        $page->head()->addExternalJavascript($javascript);
    }
}

Note that the same concept works for stylesheets, except the methods are addStylesheet() and addExternalStylesheet() instead.

Page initialization method

For javascript or stylesheets that are common to many application modules, I typically add them in the initialize method of the IWPage subclass used by the application module. For example, if I intended to use GoogleMaps in a number of application modules, I might apply the API javascript to a page shared by those modules.

Partial Listing: MapPage.php


class MapPage extends XHTML11Page
{
    function initialize()
    {
        // Add internal javascript
        $this->addJavascript('css/map.js');
        
        // Add the external javascript directly to the <head> element of the page
        $google = 'http://maps.google.com/maps/api/js?sensor=false';
        $this->head()->addExternalJavascript($google);
    }
}