Chapter 3: Implementing the Interface
68
Scripting UI Behavior with iui.js
When you use the iUI framework, iui.js powers all of the UI behavior for you once you include it in your
document head. However, because the iUI framework does take control over many aspects of the
environment, it is important that you have a solid understanding of the library ’ s internals.
The iui.js consists of a JSON object
window.iui
, three listeners for
load
and
click
events, and several
supporting routines. All of the JavaScript code is enclosed in an anonymous function with several
constants and variables defined:
(function() {
var slideSpeed = 20;
var slideInterval = 0;
var currentPage = null;
var currentDialog = null;
var currentWidth = 0;
var currentHash = location.hash;
var hashPrefix = “#_”;
var pageHistory = [];
var newPageCount = 0;
var checkTimer;
// **** REST OF IUI CODE HERE ****
})();
The anonymous function creates a local scope to allow private semi - global variables and avoid name
conflicts with applications that use iui.js.
Chapter 3: Implementing the Interface
69
images and then a routine called
checkOrientAndLocation()
, which is an event handler used for
detecting and handling viewport orientation changes. (Orientation change events are fully covered in
Chapter 5 .) The
setInterval
function then calls
checkOrientAndLocation()
every 300ms when the
application runs. Note that the
checkOrientAndLocation()
also contains the code to hide the URL bar.
The iPhone update 1.1.1 added an
orientationchange
event. However, for maximum compatibility
with iPhone 1.0, I recommend continuing to use the
checkOrientAndLocation()
event.
Getting back to
iui.showPage()
, its code is as follows:
showPage: function(page, backwards)
{
if (page)
{
if (currentDialog)
{
The node is then evaluated to determine whether it is a dialog (containing
class=”dialog”
as an
attribute) or a normal page. While the opening page of an iPhone/iPod touch is often a normal page,
you may wish to have a login or initial search dialog.
Loading a Standard iUI Page
For normal pages, iUI will assign the value of
currentPage
to the variable
fromPage
and then reassign
currentPage
to the
page
parameter. If
fromPage
is not null (i.e., every page after the initial page), then
iUI performs a slide - in animation with a function called
slidePages()
. The
fromPage
,
page
, and
backwards
variables are passed to
slidePages()
.
backButton.innerHTML = prevPage.title ? prevPage.title : “Back”;
}
else
backButton.style.display = “none”;
}
}
The
updatePage()
function is responsible for updating the
pageHistory
array, which is required for
enabling the Mobile Safari Back button to work even in single - page applications. The value of the node ’ s
title
attribute is then assigned to be the
innerHTML
of the top toolbar ’ s
h1 pageTitle
.
If the page name contains the string
form
in it, then the
showForm()
function is called. Otherwise, the
routine continues on, looking to see if a
backButton
element is defined in the toolbar. If so, then
the page history is updated and button title is updated.
Subsequent pages will always bypass the direct call to
updatePage()
checkTimer = setInterval(checkOrientAndLocation, 300);
setTimeout(updatePage, 0, toPage, fromPage);
}
if (axis == “y”)
{
backwards
? fromPage.style.top = (100-percent) + “%”
: toPage.style.top = percent + “%”;
}
else
{
fromPage.style.left = (backwards ? (100-percent) : (percent-100)) + “%”;
toPage.style.left = (backwards ? -percent : percent) + “%”;
}
}
}
The primary purpose of
slidePages()
is to emulate the standard iPhone/iPod touch slide animation
effect when you move between pages. It achieves this by using JavaScript timer routines to incrementally
update the
style.left
property of the
fromPage
and the
toPage
. The
updatePage()
function
(discussed previously) is called inside of a
{
link.setAttribute(“selected”, “progress”);
iui.showPageByHref(link.href, null, null, link, unselect);
}
else if (!link.target)
{
link.setAttribute(“selected”, “progress”);
iui.showPageByHref(link.href, null, null, null, unselect);
}
else
return;
event.preventDefault();
}
}, true);
This routine evaluates the type of link that it is:
If it is an internal URL, then the page is passed to
iui.showPage()
.
If the
backButton
is tapped, then
history.back()
is triggered.
Dialog forms typically contain a Submit and Cancel button. If a Submit button is tapped,
then
submitForm()
is called. If a Cancel button is tapped, then
cancelDialog()
is called.
(The
❑
❑
❑
❑
❑
(continued)
c03.indd 72c03.indd 72 12/7/07 2:43:45 PM12/7/07 2:43:45 PM
Chapter 3: Implementing the Interface
73
{
if (replace)
replaceElementWithSource(replace, req.responseText);
else
{
var frag = document.createElement(“div”);
frag.innerHTML = req.responseText;
iui.insertPages(frag.childNodes);
}
if (cb)
setTimeout(cb, 1000, true);
}
};
if (args)
{
req.open(method || “GET”, href, true);
req.setRequestHeader(“Content-Type”, “application/x-www-form-
urlencoded”);
req.setRequestHeader(“Content-Length”, args.length);
req.send(args.join(“ & ”));
}
replaceElementWithSource()
function is called. As the following code shows, the calling link
node (the
replace
parameter) is replaced with the
source
(the AJAX document fragment):
function replaceElementWithSource(replace, source)
{
var page = replace.parentNode;
var parent = replace;
while (page.parentNode != document.body)
{
page = page.parentNode;
parent = parent.parentNode;
}
var frag = document.createElement(parent.localName);
frag.innerHTML = source;
page.removeChild(parent);
while (frag.firstChild)
page.appendChild(frag.firstChild);
}
c03.indd 73c03.indd 73 12/7/07 2:43:45 PM12/7/07 2:43:45 PM