Chapter 7. Enhancing the User Interface with jQuery

The application as it stands now is fully functional. Events can be viewed, and users with administrative clearance can log in to create, edit, or delete events.

The next step is to add a layer of polish to the app that creates that finished look-and-feel, which you'll accomplish using a technique called progressive enhancement to add AJAX functionality to the app.

Adding Progressive Enhancements with jQuery

Progressive enhancement is a term originally coined by Steven Champeon[7] in 2003 to describe a web-development technique in which applications are designed to be accessible to any Internet connection and browser using semantic HTML and other technologies that are applied in layers (such as CSS files and JavaScript markup).

For an application to follow the principles of progressive enhancement, it must adhere to the following guidelines:

  • Basic content is accessible to all browsers using the simplest, most semantic HTML markup possible.

  • All of the basic functionality of the app works in all browsers.

  • The user's preferences are respected; this means that the web app doesn't override browser settings (such as window size).

  • Externally linked CSS handles the styling and presentation of the document.

  • Externally linked JavaScript enhances the user experience, but it remains unobtrusive, or non-essential to the application's operation.

Your application already meets the first four guidelines (it's not pretty, but the application will work with styles disabled). So as long as your JavaScript doesn't create any new functionality that can't be accessed with JavaScript disabled, you will have successfully created a progressively enhanced web application.

Setting Progressive Enhancement Goals

Using the principles of progressive enhancement, you'll add the ability to view event information without a page refresh in a modal window, a content area that sits on top of existing markup to display additional information. Such windows are usually triggered by JavaScript, and they are used on many of today's most popular web sites.

In your calendar application, you'll use a modal window to display event details after a user clicks the event title. This will be done without a page refresh using AJAX.

Include jQuery in the Calendar App

As you learned in the introduction to jQuery earlier in this book, using jQuery syntax requires that you first include the jQuery library. Because JavaScript files should be the last thing in your HTML markup before you the close body tag (</body>), you'll include the jQuery library and all subsequent files in footer.inc.php (/public/assets/common/footer.inc.php). Begin by including the latest version of jQuery in your app; you accomplish this by adding the following bold lines to footer.inc.php:

<script type="text/javascript"
          src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">
        google.load("jquery", "1");
    </script>
</body>

</html>

Save this code, then load http://localhost/ in your browser. Open the Firebug console and execute the following command to ensure that jQuery is loaded in your app:

$("h2").text();

After running this command, the console will display the following output:

>>> $("h2").text();

"January 2010"

Note

Because you're using the Google JSAPI, you need to have an Internet connection available, in addition to your Apache server. If you do not have access to an Internet connection or prefer not to use one, download the latest version of jQuery from http://jquery.com/ and include it instead.

Create a JavaScript Initialization File

Your app is following progressive enhancement guidelines, so all scripts will be housed in an external file called init.js. It will reside in the public js folder (/public/assets/js/init.js), and it will contain all of the custom jQuery code for your app.

Include the Initialization File in the Application

Before any of your scripts will be available to your app, you will need to include the initialization file in the application. Your app will use jQuery syntax, so the initialization file needs to be included after the script that loads the jQuery library in footer.inc.php.

You include the file in your app by inserting the following bold code into footer.inc.php:

<script type="text/javascript"
        src="http://www.google.com/jsapi"></script>
  <script type="text/javascript">
      google.load("jquery", "1");
  </script>
  <script type="text/javascript"
        src="assets/js/init.js">/script>
</body>

</html>

Ensuring the Document Is Ready Before Script Execution

After creating init.js, use the document.ready shortcut from jQuery to ensure that no scripts execute before the document is actually ready to be manipulated. Insert the following code into init.js:

// Makes sure the document is ready before executing scripts
jQuery(function($){

// A quick check to make sure the script loaded properly
console.log("init.js was loaded successfully.");

});

Save this file and load http://localhost/ in your browser with the Firebug console open. After the file is loaded, you should see the following result appear in the console:

init.js was loaded successfully.

Creating a New Stylesheet for Elements Created by jQuery

To ensure the elements created with jQuery look right when you start building them, you're going to jump a bit ahead here and create a new CSS file to store styling information for the elements you'll create with the jQuery scripts you're about to write.

This file will be called ajax.css, and it will reside in the css folder (/public/assets/css/ajax.css). After creating it, place the following style rules inside it:

.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,.5);
    z-index: 4;
}

.modal-window {
    position: absolute;
    top: 140px;
    left: 50%;
    width: 300px;
    height: auto;
    margin-left: −150px;
    padding: 20px;
    border: 2px solid #000;
    background-color: #FFF;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    -moz-box-shadow: 0 0 14px #123;
    -webkit-box-shadow: 0 0 14px #123;
    box-shadow: 0 0 14px #123;
    z-index: 5;
}

.modal-close-btn {
    position: absolute;
    top: 0;
    right: 4px;
    margin: 0;
    padding: 0;
    text-decoration: none;
    color: black;
    font-size: 16px;
}

.modal-close-btn:before {
    position: relative;
    top: −1px;
    content: "Close";
    text-transform: uppercase;
    font-size: 10px;
}

Including the Stylesheet in the Index File

Next, open index.php and include the new stylesheet in the $css_files array by adding the line in bold:

<?php

/*
 * Include necessary files
 */
include_once '../sys/core/init.inc.php';

/*
 * Load the calendar
 */
$cal = new Calendar($dbo, "2010-01-01 12:00:00");

/*
 * Set up the page title and CSS files
 */
$page_title = "Events Calendar";
$css_files = array('style.css', 'admin.css', 'ajax.css'),

/*
 * Include the header
 */
include_once 'assets/common/header.inc.php';

?>

<div id="content">
<?php

/*
 * Display the calendar HTML
 */
echo $cal->buildCalendar();

?>

</div><!-- end #content -->

<?php

/*
 * Include the footer
 */
include_once 'assets/common/footer.inc.php';

?>

Creating a Modal Window for Event Data

The modal window you'll create for this app will be fairly simple; the script to create it will follow these steps:

  1. Prevent the default action (opening the detailed event view in view.php).

  2. Add an active class to the event link in the calendar.

  3. Extract the query string from the event link's href attribute.

  4. Create a button that will close the modal window when clicked.

  5. Create the modal window itself and put the Close button inside it.

  6. Use AJAX to retrieve the information from the database and display it in the modal window.

All of the preceding steps will be carried out when the click event is fired for an event title link.

Binding a Function to the Click Event of Title Links

Begin by adding a new selector to init.js that selects all anchor elements that are direct descendants of list items (li>a) and use the .live() method to bind a handler to the click event. Insert the following bold code into init.js:

// Makes sure the document is ready before executing scripts
jQuery(function($){

// Pulls up events in a modal window
$("li>a").live("click", function(event){

        // Event handler scripts go here

    });

});

Preventing the Default Action and Adding an Active Class

Next, you need to prevent the default action by using .preventDefault(), then add an active class to the clicked element using .addClass().

This is accomplished by adding the following bold code:

// Makes sure the document is ready before executing scripts
jQuery(function($){

// Pulls up events in a modal window
$("li>a").live("click", function(event){

        // Stops the link from loading view.php
event.preventDefault();
        // Adds an "active" class to the link
        $(this).addClass("active");

        // Proves the event handler worked by logging the link text
        console.log( $(this).text() );

    });

});

After saving this code, reload http://localhost/ in your browser and click any of the event titles. Instead of going to the event details on view.php, the title of the event is output in the console. For instance, if you click the New Year's Day event, you will see the following output in the console:

New Year's Day

Extracting the Query String with Regular Expressions

The modal window is being created to display event information, so you'll need some way of knowing which event should be displayed. Without adding any extra markup, you can actually pull the event ID right out of the href attribute using regular expressions.

To do this, you need to extract the query string from the link. (If the href attribute value is http://localhost/view.php?event_id=1, the query string is event_id=1.)

You will extract the query string using two items: .replace(), a native JavaScript function that accepts a string or regular expression pattern to match; and a string or pattern that matches should be replaced with.

Using the Lazy Approach: String-Based Replacement

At a glance, the obvious solution might seem to be the following:

var data = string.replace("http://localhost/view.php?", "");

And, yes, this does work, producing the output "event_id=1" (if you assume the original value of $string was http://localhost/view.php?event_id=1). Unfortunately, this approach is not flexible enough; for example, what if the application is moved to another domain name? Or, what if the file name is changed to event.php? Either change breaks the preceding logic and requires an update to the script.

Adopting a Better Solution: Regular Expressions

However, there is a better solution: regular expressions. Regular expressions are a powerful pattern-matching tool available in most modern programming languages.

To extract the query string, you'll use a pattern that looks for the first question mark (?) in a string, and then returns everything after it. This pattern will look like this:

/.*??(.*)$/

Regular expressions in JavaScript are delimited by forward slashes (/) at each end of the expression. Inside this expression, the pattern looks for zero or more of any character (from left to right) until the first time it reaches a question mark; it then stores all characters after the question mark until the end of the string as a named group for use in the replacement.

Note

You'll learn much more about regular expressions and how they work in Chapter 9.

Incorporating a Regular Expression into a Script

You want to extract the href value of the link that was clicked, so you'll use the this keyword. In order to use jQuery methods, you have to pass this as the selector to the jQuery function first. Now access the href value with the .attr() method, then call .replace() and extract the query string.

When using regular expressions in .replace(), no quotes are used to enclose the pattern. Using the regular expression just described, modify init.js to store the query string from the clicked link in a variable called data; do this by adding the code shown in bold:

// Makes sure the document is ready before executing scripts
jQuery(function($){

// Pulls up events in a modal window
$("li>a").live("click", function(event){

        // Stops the link from loading view.php
        event.preventDefault();

        // Adds an "active" class to the link
        $(this).addClass("active");

        // Gets the query string from the link href
        var data = $(this)
                        .attr("href")
                        .replace(/.+??(.*)$/, "$1");

        // Logs the query string
        console.log( data );
});

});

Save this code, then reload http://localhost/ and click a link. You should see something similar to the following appear in the console:

event_id=1

Creating a Modal Window

The next step is to generate the HTML markup that will actually create the modal window and overlay. This markup is extremely simple, and it will basically consist of a div element wrapped around other content. For example, the New Year's Day event modal window markup will look like this:

<div class="modal-window">
    <h2>New Year's Day</h2>
    <p class="dates">January 01, 2010, 12:00am—11:59pm</p>
    <p>Happy New Year!</p>
</div>

You are going to use this same modal window for other features as well (such as for displaying the editing form for events), so the actual creation of the modal window is going to be abstracted in a separate function for easy re-use. Because you will re-use more than one function, you'll organize your script by placing all utility functions in an object literal, which is a comma-separated list of name-value pairs (for more information, see the sidebar, "Using an Object Literal for Utility Functions").

Creating the Utility Function to Check for a Modal Window

At the top of init.js, declare a new object literal called fx to store your utility functions:

// Makes sure the document is ready before executing scripts
jQuery(function($){

// Functions to manipulate the modal window
var fx = {};

// Pulls up events in a modal window
$("li>a").live("click", function(event){

        // Stops the link from loading view.php
        event.preventDefault();

        // Adds an "active" class to the link
        $(this).addClass("active");

        // Gets the query string from the link href
var data = $(this)
                        .attr("href")
                        .replace(/.+??(.*)$/, "$1");

        // Logs the query string
        console.log( data );

    });

});

The first function to be stored in fx will be called initModal, and it will check whether a modal window already exists. If it does, the function will select it; otherwise, it will create a new one and append it to the body tag.

To see if an element already exists, use the length property after executing the jQuery function with a selector for that element. If the length property returns 0, the element does not currently exist in the document object model (DOM).

Perform the check and return a modal window by inserting the following bold code into fx inside init.js:

// Functions to manipulate the modal window
var fx = {

        // Checks for a modal window and returns it, or
        // else creates a new one and returns that
        "initModal" : function() {
                // If no elements are matched, the length
                // property will return 0
                if ( $(".modal-window").length==0 )
                {
                    // Creates a div, adds a class, and
                    // appends it to the body tag
                    return $("<div>")
                            .addClass("modal-window")
                            .appendTo("body");
                }
                else
                {

                    // Returns the modal window if one
                    // already exists in the DOM
                    return $(".modal-window");
                }
            }

    };

Calling the Utility Function from the Event Handler

Next, modify the click event handler to load the result of fx.initModal into a variable for use in the script by adding the following bold code in init.js:

// Pulls up events in a modal window
$("li>a").live("click", function(event){

        // Stops the link from loading view.php
        event.preventDefault();

        // Adds an "active" class to the link
        $(this).addClass("active");

        // Gets the query string from the link href
        var data = $(this)
                        .attr("href")
                        .replace(/.+??(.*)$/, "$1"),

        // Checks if the modal window exists and
        // selects it, or creates a new one
            modal = fx.initModal();

    });

Note

The semicolon after the data variable has been replaced with a comma in this example.

Save, then reload http://localhost/ and click one of the event titles to cause a modal window to appear on the screen (see Figure 7-1).

Clicking an event title causes a modal window to appear

Figure 7-1. Clicking an event title causes a modal window to appear

Retrieve and Display Event Information with AJAX

Now that the modal window loads, it's time to load the event information and display it. To do this, you'll be using the $.ajax() method.

Using the $.ajax() method, you will send data to a processing file (which you'll build in the next section) using the POST method, then insert the response into the modal window.

Creating a File to Handle AJAX Requests

Before you put together the call to $.ajax(), it helps to know where and how the data should be sent. In the inc folder, create a new file called ajax.inc.php (/public/assets/inc/ajax.inc.php). This file will work very similarly to process.inc.php, except it will deal exclusively with AJAX calls. Because a value returned from a PHP function can't be read by JavaScript unless the value is actually output (using echo or its ilk), process.inc.php will not function properly for this aspect of the application.

Essentially, ajax.inc.php will use a lookup array to determine which objects and methods need to be used, then output the returned values using echo for use with AJAX.

Start by enabling sessions, loading the necessary configuration information, defining a constant, and putting together an auto-load function. Now add the following to ajax.inc.php:

<?php

/*
 * Enable sessions
 */
session_start();

/*
 * Include necessary files
 */
include_once '../../../sys/config/db-cred.inc.php';

/*
 * Define constants for config info
 */
foreach ( $C as $name => $val )
{
    define($name, $val);
}

function __autoload($class_name)
{
    $filename = '../../../sys/class/class.'
        . strtolower($class_name) . '.inc.php';
    if ( file_exists($filename) )
    {
        include_once $filename;
    }
}

?>

Next, define the lookup array with information for loading event data, then put together the code that will instantiate an object, call the method, and output the returned value using the bold code that follows:

<?php
/*
 * Enable sessions
 */
session_start();

/*
 * Include necessary files
 */
include_once '../../../sys/config/db-cred.inc.php';

/*
 * Define constants for config info
 */
foreach ( $C as $name => $val )
{
    define($name, $val);
}

/*
 * Create a lookup array for form actions
 */
$actions = array(
        'event_view' => array(
                'object' => 'Calendar',
                'method' => 'displayEvent'
            )
    );

/*
 * Make sure the anti-CSRF token was passed and that the
 * requested action exists in the lookup array
 */
if ( isset($actions[$_POST['action']]) )
{
    $use_array = $actions[$_POST['action']];
    $obj = new $use_array['object']($dbo);

    /*
     * Check for an ID and sanitize it if found
     */
    if ( isset($_POST['event_id']) )
    {
        $id = (int) $_POST['event_id'];
    }
    else { $id = NULL; }

    echo $obj->$use_array['method']($id);
}

function __autoload($class_name)
{
$filename = '../../../sys/class/class.'
        . strtolower($class_name) . '.inc.php';
    if ( file_exists($filename) )
    {
        include_once $filename;
    }
}

?>

The only real differences from process.inc.php in the preceding code are the lack of a header key in the lookup array and the use of echo to output the return value of called methods.

Loading Event Data Using AJAX

Moving back to init.js, you can now add the call to $.ajax(). There will eventually be several calls to $.ajax() in your application, so store the location of the processing file in a variable for easy maintenance if the file location or name could ever change. Add this variable to the top of init.js by inserting the code shown in bold:

// Makes sure the document is ready before executing scripts
jQuery(function($){

// File to which AJAX requests should be sent
var processFile = "assets/inc/ajax.inc.php",

// Functions to manipulate the modal window
    fx = {

        // Checks for a modal window and returns it, or
        // else creates a new one and returns that
        "initModal" : function() {
                // If no elements are matched, the length
                // property will be 0
                if ( $(".modal-window").length==0 )
                {
                    // Creates a div, adds a class, and
                    // appends it to the body tag
                    return $("<div>")
                            .addClass("modal-window")
                            .appendTo("body");
                }
                else
                {
                    // Returns the modal window if one
                    // already exists in the DOM
                    return $(".modal-window");
                }
            }

    };
// Pulls up events in a modal window
$("li>a").live("click", function(event){

        // Stops the link from loading view.php
        event.preventDefault();

        // Adds an "active" class to the link
        $(this).addClass("active");

        // Gets the query string from the link href
        var data = $(this)
                        .attr("href")
                        .replace(/.+??(.*)$/, "$1"),

        // Checks if the modal window exists and
        // selects it, or creates a new one
            modal = fx.initModal();

    });

});

Next, set up the call to $.ajax() in the event handler. It will use the POST method, point to the processFile, and send the appropriate data. Because the query string extracted from the link does not include an action field, insert one manually here. Finally, use .append() to insert the returned markup into the modal window if the call succeeds or to display an error message if it fails.

Do this by inserting the following bold lines into init.js:

// Pulls up events in a modal window
$("li>a").live("click", function(event){

        // Stops the link from loading view.php
        event.preventDefault();

        // Adds an "active" class to the link
        $(this).addClass("active");

        // Gets the query string from the link href
        var data = $(this)
                        .attr("href")
                        .replace(/.+??(.*)$/, "$1"),

        // Checks if the modal window exists and
        // selects it, or creates a new one
            modal = fx.initModal();

        // Loads the event data from the DB
        $.ajax({
                type: "POST",
                url: processFile,
data: "action=event_view&" + data,
                success: function(data){
                        // Alert event data for now
                        modal.append(data);
                    },
                error: function(msg) {
                        modal.append(msg);
                    }
            });

    });

Save your changes, then reload http://localhost/ and click an event title to see the event information loaded into the modal window (see Figure 7-2).

The event information loaded into the modal window

Figure 7-2. The event information loaded into the modal window

Add a Close Button

As it stands right now, the only way to get rid of the modal window after clicking an event title is to reload the page. Of course, this isn't good enough, so you need to add a Close button.

To accomplish this, you need to create a new link and bind a click event handler to it that removes the modal window from the DOM. To give it a traditional Close button feel, use the multiplication symbol as its content (and the CSS in ajax.css adds the word "close" in front of it). Also, add an href attribute to make sure hovering over the link causes the mouse to behave as though the button is clickable.

Next, add a Close button by inserting the following bold code into init.js:

// Pulls up events in a modal window
$("li>a").live("click", function(event){

        // Stops the link from loading view.php
        event.preventDefault();

        // Adds an "active" class to the link
        $(this).addClass("active");

        // Gets the query string from the link href
        var data = $(this)
                        .attr("href")
                        .replace(/.+??(.*)$/, "$1"),

        // Checks if the modal window exists and
        // selects it, or creates a new one
            modal = fx.initModal();

        // Creates a button to close the window
        $("<a>")
            .attr("href", "#")
            .addClass("modal-close-btn")
            .html("&times;")
            .click(function(event){
                        // Prevent the default action
                        event.preventDefault();

                        // Removes modal window
                        $(".modal-window")
                            .remove();
                    })
            .appendTo(modal);

        // Loads the event data from the DB
        $.ajax({
                type: "POST",
                url: processFile,
                data: "action=event_view&" + data,
                success: function(data){
                        // Alert event data for now
modal.append(data);
                    },
                error: function(msg) {
                        modal.append(msg);
                    }
            });

    });

After saving the preceding code, load http://localhost/ and click an event title to see the new Close button (see Figure 7-3). Click the Close button to remove the modal window.

The Close button is now visible in the modal window

Figure 7-3. The Close button is now visible in the modal window

Add Effects to the Creation and Destruction of the Modal Window

To give the modal window a little more style and polish, you'll add effects to make the box fade in when it's created and fade out when it's removed. Also, to help draw focus to the modal window when it's active, you'll add an overlay to the site that will darken everything but the modal window.

Fade Out the Modal Window

First, you need to add effects to fade out the modal window. This function will be triggered in several ways, some of which also trigger events; to handle this, you create a conditional statement that checks whether an event was triggered, then prevent the default action if that's the case.

Next, remove the class active from all links, since none of them are in use when the modal window isn't visible.

Finally, you select and fade out the modal window using .fadeOut(). In the callback function of .fadeOut(), the modal window will be removed from the DOM entirely.

You add this function by inserting the following bold code in the fx object literal:

// Functions to manipulate the modal window
    fx = {

        // Checks for a modal window and returns it, or
        // else creates a new one and returns that
        "initModal" : function() {
                // If no elements are matched, the length
                // property will be 0
                if ( $(".modal-window").length==0 )
                {
                    // Creates a div, adds a class, and
                    // appends it to the body tag
                    return $("<div>")
                            .addClass("modal-window")
                            .appendTo("body");
                }
                else
                {
                    // Returns the modal window if one
                    // already exists in the DOM
                    return $(".modal-window");
                }
            },

        // Fades out the window and removes it from the DOM
        "boxout" : function(event) {
                // If an event was triggered by the element
                // that called this function, prevents the
                // default action from firing
                if ( event!=undefined )
                {
                    event.preventDefault();
                }

                // Removes the active class from all links
                $("a").removeClass("active");

                // Fades out the modal window, then removes
                // it from the DOM entirely
                $(".modal-window")
.fadeOut("slow", function() {
                            $(this).remove();
                        }
                    );
            }

    };

To incorporate this new function into the script, modify the click event handler for the Close button using the following bold code:

// Creates a button to close the window
        $("<a>")
            .attr("href", "#")
            .addClass("modal-close-btn")
            .html("&times;")
            .click(function(event){
                        // Removes modal window
                        fx.boxout(event);
                    })
            .appendTo(modal);

Save init.js and reload http://localhost/ in your browser. Click an event title to create a new modal window, then click the Close button to watch the modal window fade out (see Figure 7-4).

The modal window mid-fade after the user clicks the Close button

Figure 7-4. The modal window mid-fade after the user clicks the Close button

Adding an Overlay and Fade in the Modal Window

To add the overlay and fade in the modal window, you need to add another function to the fx object literal. It will be called boxin, and it will be called in the success callback of $.ajax() in the event title click handler. This function will accept two parameters: the data returned by ajax.inc.php (data) and the modal window object (modal).

First, the function will create a new div with a class of modal-overlay; next, it will hide the div and append it to the body element. To help usability, the overlay will also have a click handler attached to it that will remove the modal window when clicked by invoking fx.boxout().

Next, the function will hide the modal window and append the information stored in data to it. Finally, it will fade in both elements using .fadeIn().

You add this function to the fx object literal by inserting the code shown in bold:

// Functions to manipulate the modal window
    fx = {

        // Checks for a modal window and returns it, or
        // else creates a new one and returns that
"initModal" : function() {
                // If no elements are matched, the length
                // property will be 0
                if ( $(".modal-window").length==0 )
                {
                    // Creates a div, adds a class, and
                    // appends it to the body tag
                    return $("<div>")
                            .addClass("modal-window")
                            .appendTo("body");
                }
                else
                {
                    // Returns the modal window if one
                    // already exists in the DOM
                    return $(".modal-window");
                }
            },

        // Adds the window to the markup and fades it in
        "boxin" : function(data, modal) {
                // Creates an overlay for the site, adds
                // a class and a click event handler, then
                // appends it to the body element
                $("<div>")
                    .hide()
                    .addClass("modal-overlay")
                    .click(function(event){
                            // Removes event
                            fx.boxout(event);
                        })
                    .appendTo("body");
                // Loads data into the modal window and
                // appends it to the body element
                modal
                    .hide()
                    .append(data)
                    .appendTo("body");

                // Fades in the modal window and overlay
                $(".modal-window,.modal-overlay")
                    .fadeIn("slow");
            },

        // Fades out the window and removes it from the DOM
        "boxout" : function(event) {
                // If an event was triggered by the element
                // that called this function, prevents the
                // default action from firing
                if ( event!=undefined )
{
                     event.preventDefault();
                }

                // Removes the active class from all links
                $("a").removeClass("active");

                // Fades out the modal window, then removes
                // it from the DOM entirely
                $(".modal-window")
                    .fadeOut("slow", function() {
                            $(this).remove();
                        }
                    );
            }

    };

Next, you need to modify the callback function that fires on a successful execution of $.ajax() when clicking an event title to call fx.boxin; you do so by adding the line of bold code in the listing that follows:

// Pulls up events in a modal window
$("li>a").live("click", function(event){

        // Stops the link from loading view.php
        event.preventDefault();

        // Adds an "active" class to the link
        $(this).addClass("active");

        // Gets the query string from the link href
        var data = $(this)
                        .attr("href")
                        .replace(/.+??(.*)$/, "$1"),

        // Checks if the modal window exists and
        // selects it, or creates a new one
            modal = fx.initModal();

        // Creates a button to close the window
        $("<a>")
            .attr("href", "#")
            .addClass("modal-close-btn")
            .html("&times;")
            .click(function(event){
                        // Removes modal window
                        fx.boxout(event);
                    })
            .appendTo(modal);
// Loads the event data from the DB
        $.ajax({
                type: "POST",
                url: processFile,
                data: "action=event_view&" + data,
                success: function(data){
                        fx.boxin(data, modal);
                    },
                error: function(msg) {
                        modal.append(msg);
                    }
            });

    });

Save this code, reload http://localhost/, and click an event title to see the modal overlay and modal window fade in (see Figure 7-5).

The modal window with an overlay to help draw the focus

Figure 7-5. The modal window with an overlay to help draw the focus

You may have noticed that the modal window appears to flicker right as it's opened. This happens because fx.initModal() appends the modal window to the body element without hiding it. To correct this, add a call to .hide() in fx.initModal() using the following bold code:

// Functions to manipulate the modal window
    fx = {

        // Checks for a modal window and returns it, or
        // else creates a new one and returns that
        "initModal" : function() {
                // If no elements are matched, the length
                // property will be 0
                if ( $(".modal-window").length==0 )
                {
                    // Creates a div, adds a class, and
                    // appends it to the body tag
                    return $("<div>")
                            .hide()
                            .addClass("modal-window")
                            .appendTo("body");
                }
                else
                {
                    // Returns the modal window if one
                    // already exists in the DOM
                    return $(".modal-window");
                }
            },

        // Adds the window to the markup and fades it in
        "boxin" : function(data, modal) {
                // Code omitted for brevity
            },

        // Fades out the window and removes it from the DOM
        "boxout" : function(event) {
                // Code omitted for brevity
            }

    };

Finally, clicking the Close button does not remove the overlay. To fade out and remove the overlay, simply modify the selector in fx.boxout() to include the class modal-overlay:

// Functions to manipulate the modal window
    fx = {

        // Checks for a modal window and returns it, or
        // else creates a new one and returns that
        "initModal" : function() {
                // Code omitted for brevity
},

        // Adds the window to the markup and fades it in
        "boxin" : function(data, modal) {
                // Code omitted for brevity
            },

        // Fades out the window and removes it from the DOM
        "boxout" : function(event) {
                // If an event was triggered by the element
                // that called this function, prevents the
                // default action from firing
                if ( event!=undefined )
                {
                    event.preventDefault();
                }

                // Removes the active class from all links
                $("a").removeClass("active");

                // Fades out the modal window and overlay,
                // then removes both from the DOM entirely
                $(".modal-window,.modal-overlay")
                    .fadeOut("slow", function() {
                            $(this).remove();
                        }
                    );
            }

    };

After making this change, reload http://localhost/ and click an event title. The modal window and overlay will fade in, and clicking either the Close button or the overlay will cause the modal window and overlay to fade out.

Summary

In this chapter, you learned how to load event data dynamically with jQuery using the progressive enhancement technique. You also learned about event handling, basic effects, and even a little bit about regular expressions.

In the next chapter, you'll continue to add AJAX functionality by making the editing controls work via AJAX, as well.



[7] http://www.hesketh.com/about-us/leadership-team/

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

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