Chapter 10: Packaging Apps as Bookmarks: Bookmarklets and Data URLs
226
Storing an Application in a Data URL
In addition to JavaScript functionality, you can also store a Web page or even a complete application
inside of a bookmark. The
data:
protocol allows you to encode an entire page’s content — HTML, CSS,
JavaScript, and images — inside a single URL. To be clear, data URLs store, not a simple link to a remote
page, but the actual contents of the page. This data URL can then be saved as a bookmark. When users
access this bookmark, they can interact with the page whether or not they have Internet access. The
implications are significant — you can use data URLs to package certain types of Web applications and
get around the live Internet connection requirement.
c10.indd 226c10.indd 226 12/7/07 2:56:57 PM12/7/07 2:56:57 PM
Chapter 10: Packaging Apps as Bookmarks: Bookmarklets and Data URLs
227
Constraints and Issues with Using Data URL s
While the potential of data URLs is exciting for the developer, make sure you keep the following
constraints and issues in mind before working with them:
You can store client-side technologies — such as HTML, CSS, JavaScript, and XML — inside a
data URL. However, you cannot package PHP, MYSQL, or any server-side applications in a
bookmark.
Any Web application that requires server access for data or application functionality will need to
have a way to pack and go: (1) use client-side JavaScript for application functionality, and (2)
package up a snapshot of the data and put it in a form accessible from a client script.
The application must be entirely self-contained. Therefore, every external resource the
application needs, such as images, style sheets, and .js libraries, must be encoded inside of the
main HTML file.
External resources that are referenced multiple times cannot be cached. Therefore, each separate
reference must be encoded and embedded in the file.
Images must be encoded as base64, though the conversion will increase their size by
approximately 33 percent.
The maximum size of a data URL in Mobile Safari is technically 128KB, though in actual
practice, you can work with URLs much larger, at least up to several megabytes. However,
performance of the Mobile Safari Bookmark manager suffers significantly when large amounts
of data are stored inside of a bookmark. Therefore, think thin for data URL–based applications.
Mobile Safari has issues working with complex JavaScript routines embedded in a data URL
application. For example, at the time of this writing, certain parts of the iUI framework are not
functional inside of a data URL, thus greatly limiting the potential for Web developers to take
advantage of offline storage.
Creating an Offline iPhone/iPod touch Application
After examining these constraints, it is clear that the best candidates for offline iPhone/iPod touch
applications are those that are relatively small in both scope and overall code base. A tip calculator, for
example, is a good example applet because its UI would be simple and its programming logic would be
straightforward and not require accessing complex JavaScript libraries. I’ll walk you through the steps
needed to create an offline application.
After reviewing the constraints and making sure that your application will likely work in an offline
mode, you will want to begin by designing and programming as if it were a normal iPhone/iPod touch
application. For this sample applet, the interface of the tip calculator is based on a subset of the iUI
framework. (Because the functionality inside iui.js is not compatible with data URLs, I am not including
any references to this external file.) Figure 10-4 shows the Tipster application interface that you will be
constructing.
❑
❑
❑
❑
❑
❑
❑
c10.indd 227c10.indd 227 12/7/07 2:56:58 PM12/7/07 2:56:58 PM
Chapter 10: Packaging Apps as Bookmarks: Bookmarklets and Data URLs
228
The following source file shows the core HTML and JavaScript code:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
“ /><html xmlns=” /><head>
<title>Tipster</title>
<meta name=”viewport” content=”width=320; initial-scale=1.0; maximum-scale=1.0;
user-scalable=0;”/>
<style type=”text/css” media=”screen”>@import “../iui/iui.css”;</style>
<script type=”application/x-javascript”>
addEventListener(‘load’, function() {
setTimeout(function() {
window.scrollTo(0, 1);
}, 100);
}, false);
function checkTotal(fld) {
Figure 10-4: Tipster application design
c10.indd 228c10.indd 228 12/7/07 2:56:58 PM12/7/07 2:56:58 PM
Chapter 10: Packaging Apps as Bookmarks: Bookmarklets and Data URLs
229
var x=fld.value;
var n=/(^\d+$)|(^\d+\.\d+$)/;
if (n.test(x)) {
if (fldTipPercent.selectedIndex != 0) getRec();
}
else {
alert(‘Please enter a valid total’)
clearTotal(fld);
}
}
function clearTotal(fld) {
fld.value = ‘’;
}
function getRec() {
if (fldTipPercent.selectedIndex == 0) { alert(‘Please rate the service first.’);
return; }
var selPercent = Number( eval( fldTipPercent.
var billAmount = Number( eval( fldBillTotal.value));
var tipAmount = (selPercent*billAmount);
var finalP = tipAmount + billAmount;
fldTipRec.value = ‘$’ + tipAmount.toFixed(2);
fldFinalTotal.value = ‘$’ + finalP.toFixed(2);
}
</script>
</head>
<body>
<div class=”toolbar”>
<h1 id=”pageTitle”>The Tipster</h1>
<a id=”backButton” class=”button” href=”#”></a>
</div>
<div id=”main” title=”Tipster” class=”panel” selected=”true”>
<h2 class=”tip”>Let the Tipster ease your pain and calculate the tip for
you.</h2>
<fieldset>
<div class=”row”>
<label>Bill amount:</label>
<input type=”text” id=”fldBillTotal” value=”20.00” tabindex=”1”
onfocus=”clearTotal(this)” onchange=”checkTotal(this)”/>
</div>
<div class=”row”>
<label>Rating:</label>
<select id=”fldTipPercent” onchange=”getRec()”
tabindex=”2”>
<option value=”0”>(Rate service)</option>
<option value=”10”>Very poor</option>
<option value=”12.5”>Poor</option>
<option value=”15”>Just as
expected</option>
<option value=”17.5”>Above
average</option>
<option value=”20”>Exceptional</option>
<option value=”25”>Wow!</option>
</select>
</div>
</fieldset>
(continued)
c10.indd 229c10.indd 229 12/7/07 2:56:59 PM12/7/07 2:56:59 PM
Chapter 10: Packaging Apps as Bookmarks: Bookmarklets and Data URLs
230
<fieldset>
<div class=”row”>
<label>Tip: </label>
<input type=”text” id=”fldTipRec” value=”0.00” readonly=”true”
disabled=”true”/>
</div>
<div class=”row”>
<label>Final total:</label>
<input type=”text” id=”fldFinalTotal” value=”0.00” readonly=”true”
disabled=”true”/>
</div>
</fieldset>
</div>
</body>
</html>
The
fldBillTotal
input field captures the total before the tip. The
fldTipPercent
select list displays
a set of ratings for the service, each corresponding with a percentage value (see Figure 10-5 ). These two
factors are then calculated together to generate the output values in the
fldTipRec
and
fldFinalTotal
input fields.
(continued)
Figure 10-5: Scrolling through the select list
c10.indd 230c10.indd 230 12/7/07 2:56:59 PM12/7/07 2:56:59 PM