A Taste of IWP
This document is an attempt to give you a feeling for the process of prototyping and building Ajax user interface with IWP. If you have questions or find errors either in the text or the working examples please contact. Thank you!
It is easy to get started with IWP, and a worked example, step by step, is a way to see the concepts and get a feeling for the process. This document goes through a realistic but simple example that shows use of some of the key techniques with IWP.
This tutorial takes you through several versions of the page. They all launch in the same window on the side, leaving this one available for you to refer back to. You can put the side window at a convenient location and size, then go back and forth between this window and it.
A Login Form
This example shows use of IWP to prototype a streamlined login form for a site that allows access to the public, but also supports logins that give extra privileges, as for Wiki members who can edit pages, or from a news site that offers extra services and information to paid subscribers. This form will log you in without jumping to a different page. The user's process is more streamlined, more efficient, and less distracting.
We start our prototype with a static page. The target of our attention will be the login form in the upper right corner. At this point the source code is pretty standard for any form, except that the submit action is just an alert. The void(0) at the end of the onsubmit stops the form from submitting itself to the server.
<form class=small name=login method=GET onsubmit="javascript:alert('login');void(0);">
<table border=0 cellspacing=0 cellspacing=2>
<tr>
<td class=label>Login:</td><td><input type=text size=12></td>
</tr>
<tr>
<td class=label>Password:</td><td><input type=password size=12></td>
</tr>
<tr>
<td><input type=submit name=submit value="Log In"></td><td id=loginProgress><br></td>
</tr>
</table>
</form>
View version 1.
The login form looks something like this:
A First Active Page
Setting Up the Page for IWP
We're going to go directly to submitting the form the Ajax and IWP way, but pages using IWP need a little bit of standard setup. In the future you will probably do this right at the beginning, but since it is a new thing to learn, let's see how it goes.
To set up for IWP, you add one line to the head section of the page to bring in IWP so it is available to make everything work, and wrap some HTML around your usual body. In the head section:
<script type="text/javascript" src="../js/iwp.js"></script>
Note: in your real files you will have to change src="../js/iwp.js" to reflect the actual path from each page to iwp.js, which comes from the IWP distribution.
Also, in the body section of your document, you will need to "wrap" your body HTML inside some stock code like this:
<div id="iw_mainBody"> <!-- YOUR PAGE CONTENT HERE!! --> </div> <!-- iw_mainBody --> <ul id="iw_actions" style="display: none"> <li>Action1 </ul> <script type="text/javascript"> iw_supportHere(); </script>
In other words, you put the contents of your page in a div with an id of iw_mainBody, add the beginning of a bullet list, and after all that, place one line of JavaScript IWP magic.
Connecting Form Submission to IWP
Now you are ready to start actually using IWP. First thing, we'll upgrade the form to submit itself through IWP:
<form class=small name=login method=GET onsubmit="iw_submit(this, event); return false;">
The onsubmit action calls the IWP function iw_submit. IWP functions and variables begin with the prefix iw_ to indicate that they belong to IWP.
That bullet list now becomes a real IWP action definition. Change the word Action1 to the name of the form you are submitting -- login, and add a bullet list of individual actions under it. We are going to put a progress message in the table cell with ID LoginProgress, next to the form's submit button, to make it look like this:
<ul id="iw_actions" style="display: none">
<li>login
<ul>
<li>LoginProgress
<div>
<i style="color: red; font-weight: bold;">Logging in ...</i>
</div>
</li>
</ul>
</li>
</ul>
Each IWP action is described by its own bullet item in HTML. If the bullet item contains a single word followed by a div, the document element with matching ID will get its content replaced by the contents of the div when the action is requested. As soon as you press the button you will see the message "Logging in ... " beside the button.
View version 2 and
press the button.
The form becomes:
Building a Prototype Update Page
And for our next trick ... , we will go and get an update page from the server. The first part of the change is minor: to the "login" actions we add a request for a server page named login.html, so now the action looks like this:
<li>login
<ul>
<li>LoginProgress
<div>
<i style="color: red; font-weight: bold;">Logging in ...</i>
</div>
<li>=> login.html</li>
</li>
</ul>
</li>
A bullet item beginning with => and followed by a URL tells IWP you want to request that page as an update from the server.
The second part of the change is to create the update page, login.html. IWP update pages have a standard structure, like this:
<html>
<head>
<script src="/path/to/inner-utils.js" type="text/javascript"></script>
</head>
<body>
<ul>
<li>Update
<ul>
<!-- PUT UPDATE ACTIONS HERE -->
</ul>
</li>
</ul>
</body>
</html>
In login.html, we change "/path/to/inner-utils.js" to "../js/inner-utils.js". Any time you make an update page, you will need to make a similar change to it to match the path from your update page to your copy of inner-utils.js. In this update page the one and only action is named Update. IWP expects every update page to have an action with the name Update, capitalized just like this one.
Now on to the interesting part: putting our own actions in. This works just like actions in the original page. We put items into the bullet list of steps for the Update action, in this case a single step to tell the user that she is now logged in. The HTML for it should look kind of familiar to you, thus:
<li>Update
<ul>
<li>LoginProgress
<div><b style="color: green;">Logged in.</b></div>
</li>
</ul>
</li>
Launch version 3.
Submit the login form. When the update page loads, the red progress
message changes to a green "Logged in" message.
And it looks like:
Before we go further, let's stop and smell the roses for just a moment. You might want to take a look at this first version of the update page. By design, these update pages are previewable in a Web browser. Where an update page contains chunks of HTML that will go into another page, you can look at the HTML as you are developing it. Go ahead, use your favorite HTML authoring tool, whether it is vi or BBEdit or DreamWeaver. There is no harm in referring to style sheets just as in your other pages. IWP only pays attention to the action definitions, but your browser can use the style sheets to render your HTML nicely even when you are just previewing it. If your update page refers to images, the browser can render them too, especially if you make a practice of putting update pages in the same directory as the page they will update. This way the paths to images "just work" when you preview.
Hiding the Form
It's very nice that we can submit a form through IWP and get different messages, but we want our pages to look professional — for example when the user has logged in we might prefer to present a welcome message instead of the form that no one needs now. Let's build a prototype of that!
First we'll identify the HTML that will be replaced by the welcome message, in this case the contents of the form. The update page can now replace the whole form with its message. To make it easy for IWP to find the FORM tag, give it an ID with the same value as the name attribute it already has, like this:
<form class=small name=login id=login method=GET . . .
Even when prototyping, IWP sends form data to the server. And in development mode, update pages are aware of the form data that was sent. You can access it by enclosing the name of the input element in dollar signs in the text of your update, and IWP will merge it in as it does the update for you.
The latest source code for the update page is:
<li>Update
<ul>
<li>LoginArea
<div>
<div style="font-size: medium; text-align: left; width: 150px;">
<b>Welcome $username$.</b>
</div>
</div>
</li>
</ul>
</li>
Launch version 4.
This time enter a username and then submit the form.
A message replaces the form:
Time Out for Good Behavior. This is a good opportunity to explain an important benefit of IWP that is easy to overlook until you start building without it. Page updates made with IWP are well-behaved: they stay around in spite of using the forward and back buttons or jumping around in the browser history stack. Try this out on our example. After you get the "welcome" message, go to some other Web site or at least some other page, then return. The message stays!
This may seem simple and obvious, but many Ajax user interfaces lack this good quality. If you build with IWP you get it automatically whether you use IWP's update language or its JavaScript programmer APIs.
Prototyping Server Logic
Logins don't always succeed, as most of us know from experience. Our user interface prototype would not be complete without the ability to walk through scenarios where the login fails as well as ones where the login is successful. IWP is built to handle alternative scenarios during prototyping, by simulating server logic with some assistance from you.
IWP can handle this in a couple of different ways. If needed, during prototyping it can ask the user which application logic choice you want it to simulate, and continue after you tell it. The simplest case though is its automatic simulation of forms validation. By default, input fields are valid unless their value contains a "sharp" ("#") character. By adding a custom attribute to the input field, you can declare it to IWP as a "required field" that must not be empty. When IWP simulates your application's server-side processing, it does these simplified validations and can choose different actions depending on whether an input, or an entire form, is valid.
For this taste of IWP we will just check the validity of the password field. The changes are concentrated in the update page, which now looks like this:
- Update
- login.password.valid?
- yes
- LoginArea
Welcome $username$.
- LoginArea
- no
- LoginProgress
Bad Password.
- LoginProgress
- yes
- login.password.valid?
Launch version 5.
After entering a bad password, you see:
Summary and Notes
This small example shows a typical simple application of IWP to prototyping of live Ajax user interfaces. Working almost entirely with HTML and CSS, you get a live prototype that extends easily to an actual application.
You can use dynamic pages during prototyping if your team prefers to build a certain amount of server logic even during this phase. Update pages receive form data as standard query strings or POST data. If your update page is dynamic, it simply generates suitable HTML for the update using your usual templating system.
Page updates made through IWP behave well, too. After you make them, the changes don't get lost if the user uses the forward and back buttons or jumps around in the browser's history stack. In this example you don't risk that your logged-in user may be shown the login form again.