Most mobile phones on the market these days have full-featured web browsers that are almost indistinguishable from desktop browsers. These mobile web browsers can handle most of the recent web technologies such as HTML5, CSS3, JavaScript, DOM manipulation, and Ajax.
The Dojo Toolkit has been evolving for desktop web application development, and Dojo can run on mobile web browsers as well. Since Dojo already provides numerous useful widgets, do we really need something special for mobile applications? Yes, for several reasons:
- Input device differences: Most mobile devices have no mouse or
physical keyboard. Instead, they provide a touch screen that supports
finger operations. User interactions on desktop
applications—drag and drop operations, mouse hover actions,
keyboard shortcuts and navigation (traversal using the TAB key or
arrow keys), and so on—present a challenge on a mobile device.
Any UI widgets for
mobile should be touch-enabled.
- Smaller screen size: A mobile screen is small, and the user
uses a finger on a touch screen. It is very important to properly
design the UI for mobile.
Also, the screen size of a tablet device is much bigger than a
smartphone screen. Mobile web applications need a user
interface that transforms according to the screen size or screen
orientation.
- Performance issues: While processor power of mobile devices is increasing rapidly, they still have less computing power than desktop computers. Also, the mobile network bandwidth is much lower than that of a desktop; sometimes it's extremely lower. Mobile web applications should be extremely small-footprint and high-performing.
Dojo Mobile is a Dojo-based widget set for creating mobile web applications. It was introduced in Dojo 1.5 as dojox.mobile to address the above issues. The input device and screen size issues, however, could be solved with a traditional approach, that is, simply enhancing existing Dojo widgets by adding mobile support without reinventing the ones just for mobile. But obviously performance issues cannot be resolved that way. Therefore, one of the most important (and challenging) tasks for Dojo Mobile is tackling the performance issues, especially minimizing code size.
One of the interesting features of Dojo Mobile is that it does not use any images to build UI widgets. WebKit-based browsers, which are the most popular browsers on mobile devices, support CSS3. CSS3 features, such as gradient backgrounds, rounded corner boxes, and transformation of DOM elements, can handle graphical representation without using images. Figure 1 shows some of the UI widgets that Dojo Mobile provides. These widgets do not use images; instead, they use DOM elements like <div> with CSS styles to construct their UI. Using many images could increase the total download size and the number of HTTP requests to the server, causing performance degradation. Dojo Mobile avoids that by using CSS3 capability as much as possible.
Figure 1. Image-free Dojo Mobile widgets
On the other hand, user applications may use images. Figure 2 shows examples that are provided as Dojo Mobile test files. As you can see, tab bar buttons, list item icons, and icon container icons are images. Overuse of images could degrade performance, but that is a choice for the application. Dojo Mobile itself does not use images, nor does it force the user application to use images. Furthermore, as you will see later, Dojo Mobile provides some useful mechanisms, such as DOM buttons and CSS sprite, which can reduce the need for images and reduce the number of HTTP requests to the server.
Figure 2. User application's images
When image use is inevitable, there are two possible ways to minimize the performance degradation. One way is to reduce the file size of your images by reducing the number of colors or increasing the compression rate. The other way is to reduce the number of HTTP requests for images by aggregating multiple small images into a single big image. The combined big image can be clipped and adjusted with CSS properties so that it can be used as one of small images. This technique is known as CSS Sprite, and Dojo Mobile supports it.
Listing 1 shows an example of list items, each using a separate icon. Figure 3 shows the result. This example produces three HTTP requests for images.
Listing 1. List items with separate images
<ul dojoType="dojox.mobile.RoundRectList"> <li dojoType="dojox.mobile.ListItem" icon="i-icon-1.png" moveTo="bar">General</li> <li dojoType="dojox.mobile.ListItem" icon="i-icon-2.png" moveTo="bar">Photos</li> <li dojoType="dojox.mobile.ListItem" icon="i-icon-3.png" moveTo="bar">Store</li> </ul> |
Figure 3. Result of Listing 1
On the other hand, Listing 2 shows an example that uses an aggregated image
(i-icon-all.png), which is shared by list items. By specifying
comma-separated values (top,left,width,height) for the
iconPos property of the ListItem widget, you
can reuse any rectangle area of the aggregated image. As shown in Figure
4, the result is the same, but it produces only one HTTP request for the
aggregated image.
Listing 2. List items with an aggregated image
<ul dojoType="dojox.mobile.RoundRectList" iconBase="i-icon-all.png"> <li dojoType="dojox.mobile.ListItem" iconPos="0,0,29,29" moveTo="bar">General</li> <li dojoType="dojox.mobile.ListItem" iconPos="0,29,29,29" moveTo="bar">Photos</li> <li dojoType="dojox.mobile.ListItem" iconPos="0,58,29,29" moveTo="bar">Store</li> </ul> |
Figure 4. Result of Listing 2
CSS Sprite can also be used for icon container's icons (Figure 5) or tab bar's buttons (Figure 6).
Figure 5. IconContainer with CSS Sprite
Figure 6. TabBar with CSS Sprite
Dojo Mobile provides simple buttons, icons, check marks/arrows for a list item, and so on, as shown in Figure 7. They are made from <div> elements with CSS styles applied without images, and are called DOM Buttons.
Figure 7. DOM Buttons
Ideally DOM Buttons are smaller in byte size, since they are made from CSS without images. Table 1 compares byte sizes of DOM Buttons and images using DomButtonGreenCircleArrow (fourth down, first column in Figure 7) as an example. You can see a DOM Button is much smaller than an image.
Table 1. Byte size comparison between a DOM Button and an image
| File | Byte size |
|---|---|
| DomButtonGreenCircleArrow.css (minified & gzipped) | 392 bytes |
| mblDomButtonGreenCircleArrow.png | 1,599 bytes |
DOM Buttons have the additional advantage of not needing to make additional HTTP requests, because they can be integrated into a theme CSS file with the build tool. In this situation, the footprint of a DOM Button is much smaller. Table 2 shows a DOM Button's byte size in an aggregated CSS file. You can see the addition of DomButtonGreenCircleArrow.css increases by only 155 bytes.
Table 2. DOM Button's byte size in an aggregated CSS file
| File | Byte size |
|---|---|
| base.css (minified & gzipped) | 2,844 bytes |
| base.css + DomButtonGreenCircleArrow.css (minified & gzipped) | 2,999 bytes |
| Difference | 155 bytes |
DOM Button consists of nested <div> elements with CSS styles applied. As mentioned, you can achieve a variety of graphical representations by using CSS3's rich capabilities, such as gradient backgrounds, rounded corner boxes, and transformation of DOM elements. You could even draw a circle by adjusting the border radius of a square <div> element. Figure 8 shows an example of DOM Button structure.
Figure 8. Structure of DOM Button
DOM Button is simply a collection of CSS styles. It does not require JavaScript code. It can be displayed by just placing nested <div> elements and applying CSS styles to them. Listing 3 shows the minimum sample code, and Figure 9 shows the result.
Listing 3. Use of DOM Button without JavaScript
<html>
<head>
<link href="themes/common/domButtons/DomButtonBlueCircleMinus.css" rel="stylesheet">
</head>
<body>
<div class="mblDomButtonBlueCircleMinus">
<div><div><div></div></div></div>
</div>
</body>
</html>
|
Figure 9. Result of Listing 3
In Listing 3, I prepared 4 levels of nested DIVs
including the DOM Button's root node, which has a class name. However, the
number of DIVs you need to prepare varies with the kind of DOM Button. To
automatically create the necessary number of DIVs, use Dojo Mobile's
dojox.mobile.createDomButton() function, as
illustrated in Listing 4.
Listing 4. Use of DOM Button with JavaScript
<div id="btn1" class="mblDomButtonBlueCircleMinus"></div>
----
var node = dojo.byId("btn1");
dojox.mobile.createDomButton(node);
|
Listing 3 and Listing 4, however, are usually not used. I include them for illustrative purposes to show the mechanism of DOM Button. Instead, some of the Dojo Mobile widgets support DOM Buttons as below. You can specify DOM Buttons in place of image icons or buttons.
- ListItem: icon, rightIcon, rightIcon2, arrowClass, and checkClass property (Figure 10)
- TabBarButton: icon1 and icon2 property (Figure 11)
- ToolBarButton: icon property (Figure 12)
- TabBarButton: icon property (Figure 13)
Figure 10. ListItem (list)
Figure 11. TabBarButton (tab bar)
Figure 12. ToolBarButton (heading)
Figure 13. TabBarButton (segmented control)
How to create a custom DOM Button
You can create your own custom DOM Buttons. Here are some tips.
- The class name of a DOM Button MUST start with
"
mblDomButton". Dojo Mobile checks it to determine if it is a DOM Button or not. (On the other hand, a CSS file name and where to place it can be your choice.) - Specify the width and height of the DOM Button to its root node. They will be the size of the entire DOM Button.
- <div> elements are nested, not siblings. Therefore, you may need to apply CSS styles to a node relative to its parent node.
- To apply CSS styles to a specific <div> element in the <div> hierarchy, you can use a child selector (>).
- If you want to support non-CSS3 desktop browsers, you should create an
equivalent image and a
compat cssfile (*-compat.css).
Listing 5 and Listing 6 show a custom DOM Button example. Figure 14 shows the result.
Listing 5. Custom DOM Button (DomButtonMyCheck.css)
/* === Red Check Button ==*/
.mblDomButtonMyCheck {
position: relative;
width: 29px;
height: 29px;
}
.mblDomButtonMyCheck > div {
position: absolute;
left: 0px;
top: 8px;
width: 16px;
height: 6px;
font-size: 1px;
-webkit-transform: scaleX(0.7) rotate(135deg);
border-width: 3px 4px 0px 0px;
border-style: solid;
border-color: red;
}
|
Listing 6. Custom DOM Button (DomButtonMyCheck-compat.css)
/* === Red Check Button ==*/
.mblDomButtonMyCheck {
background-image: url(compat/mblDomButtonMyCheck.png);
background-repeat: no-repeat;
}
.mblDomButtonMyCheck > div {
display: none;
}
|
Figure 14. Custom DOM Button
Dojo Mobile is optimized for WebKit-based mobile browsers, but it supports non-WebKit desktop browsers as well. However, no one wants to sacrifice performance on mobile devices to support desktop browsers. Cross-browser support code should not be loaded when an application runs on mobile devices.
One approach is conditional compilation, which allows you to strip out some
code blocks that are unnecessary for mobile. Dojo provides two ways of
conditional compilation, pragmas and has().
Pragmas are special directives that can be used to exclude/include some parts of the code as shown in Listing 7.
Listing 7. Example of pragma usage
process: function(){
//>>excludeStart("marker1", kwArgs.noIE);
if(dojo.isIE){
....
}
//>>excludeEnd("marker1");
....
}
|
In the above example, if you build the code with
the noIE=true condition option specified as
below, the code block surrounded by
excludeStart and
excludeEnd is removed from the build.
> build profile=myapp action=release noIE=true |
Also, if you use includeStart/includeEnd
pragmas, the surrounded code block is included only when the condition
matches.
has() (or dojo/has,
or has.js) is a feature detection/testing
mechanism, introduced in Dojo 1.7. As shown in Listing 8, you can use it
to test whether or not a specific feature exists in the current runtime
environment.
Listing 8. Example of "has" test
process: function(){
if(has("ie")){
....
}
....
}
|
If you configure the staticHasFeatures array in
your build profile as below, has("ie") is
replaced with 0, and then the compiler's optimizer detects its code block
as dead code, and the block is removed from the build.
staticHasFeatures: {
'ie': 0
}
|
Conditional compilation allows you to make a build that is optimized for a specific platform. The build, however, has a problem in that it does not work on other platforms. To support other platforms, you need to make other builds. To solve this issue, Dojo Mobile took a different approach: the compatibility module (or compat).
Compat includes some code that supports non-WebKit browsers. If compat is
loaded, it "overwrites" some of the widget methods that need to be fixed.
Overwriting the code keeps the original widget class names the same and
therefore does not affect the user's application code. On the other hand,
overriding the code by subclassing the original widgets would require the
use of newly defined widget class names. Compat also loads *-compat.css
files, which are patches to the original css files. In the compat mode,
traditional techniques are used to render the widget UIs without CSS3,
such as JavaScript-based animations with dojo.fx, background images, and
so on. To use compat for your application, load "dojox.mobile.compat"
using dojo.require() or the
require API.
Note that compat is divided into two pieces, compat.js and _compat.js. _compat.js includes all the implementation code, and compat.js is a loader of _compat.js. compat.js loads _compat.js only when the current browser is not WebKit-based. compat.js is such a tiny piece of code that it does not affect mobile performance even if it is in a build. This way, on WebKit-based browsers, performance does not degrade since _compat.js will never be loaded. On non-WebKit browsers, _compat.js is loaded automatically, and Dojo Mobile works in the compat mode. Table 3 shows byte size comparison between a mobile build without compat and a mobile build with compat. As you can see, the difference is negligibly small: 45 bytes.
Table 3. Mobile build size comparison (profile: mobile-all.profile.js, minified & gzipped)
| Description | Byte size |
|---|---|
| Mobile build without compat | 36,594 bytes |
| Mobile build with compat | 36,639 bytes |
| Difference | 45 bytes |
As described above, on non-WebKit browsers, Dojo Mobile runs in the compat mode, and additional resources, such as images and/or *-compat.css, are loaded. So, if you want to evaluate which and how many files are loaded in a mobile device, you should not use non-WebKit browsers such as Firefox or Internet Explorer. Debuggers on Google Chrome or the desktop version of Safari are better tools to monitor the network traffic for that purpose, since they are WebKit-based.
Dojo provides a lot of useful APIs, and they are packaged as modules, which are relatively small JavaScript files. There are countless useful modules available. However, overusing them could result in a very big footprint. Dojo Mobile is carefully designed to have as little module dependencies as possible. For example, it intentionally does not use some of the commonly used, useful modules like dojo.query or dijit._Templated. Also, all the Dojo Mobile widgets inherit from dijit._WidgetBase rather than dijit._Widget. dijit._WidgetBase is a base class of dijit._Widget, and does not include some of the code that is unnecessary for mobile, such as keyboard support code, and therefore it is lighter than dijit._Widget. Also, it does not use dijit._base.manager, which was a required module until Dojo 1.6; instead, it uses dijit.registry, which is a subset of dijit._base.manager.
Use of dojo modules like dojo.query or dijit._Templated from Dojo Mobile based user applications is of course your choice. However, you should carefully choose which dojo/dijit modules to use based on performance. For example, if you use dojo.query only once in your application, you could replace it with far smaller code than the entire dojo.query implementation.
Listing 9 shows the modules on which the Dojo Mobile base depends directly or indirectly. You may notice it has fewer dependencies on dojo/dijit modules than typical desktop use cases. It depends on only 11 dojo/_base modules out of 25, and has no dependency on the dijit/_base modules. If you use additional modules that are not shown in Listing 9, that increases your application's footprint. When you use such modules, you should choose them carefully.
Listing 9. Dependent modules
dijit/_Contained dijit/_Container dijit/_WidgetBase dijit/main dijit/registry dojo/Evented dojo/Stateful dojo/_base/Deferred dojo/_base/array dojo/_base/config dojo/_base/connect dojo/_base/declare dojo/_base/event dojo/_base/kernel dojo/_base/lang dojo/_base/sniff dojo/_base/unload dojo/_base/window dojo/aspect dojo/dom dojo/dom-attr dojo/dom-class dojo/dom-construct dojo/dom-geometry dojo/dom-prop dojo/dom-style dojo/domReady dojo/has dojo/keys dojo/mouse dojo/on dojo/ready dojo/topic |
To optimize the load time performance, build is an important process. Dojo has a powerful build system, which compresses all your JavaScript and CSS into fewer files and creates an efficient version of your application for release. Figure 15 and Figure 16 show transferred files comparison between a non-built (source code) application and a built application. You can see there is a huge difference in the number of requests and the total transferred size. The next section discusses building Dojo Mobile.
Figure 15. The number of requests and download size (non-built)
Figure 16. The number of requests and download size (built)
Dojo build has an option called customBase. The standard Dojo build includes most of the Dojo base modules in a build, since the Dojo base modules are always available without explicitly requiring them. However, if you make a build with the customBase option enabled, only the modules that are in the actual dependency chain are included in the build. Dojo Mobile is designed to have as few Dojo base module dependencies as possible. Therefore, to benefit from the design, the use of the customBase option is important. Listing 10 shows how to specify the customBase option in your build profile.
Listing 10. customBase option in a profile file
dependencies = {
stripConsole: "normal",
layers: [
{
name: "dojo.js",
customBase: true,
dependencies: [
"dojox.mobile.parser",
"dojox.mobile",
"dojox.mobile.compat"
]
},
....
|
There are two compilers (or compressors) that can be used form the Dojo build tool, Shrinksafe and Google Closure Compiler. Shrinksafe is Dojo's default compiler. Closure has been bundled with Dojo since version 1.7. Table 4 shows mobile build size comparison between Shrinksafe and Closure. As you can see, Closure's compression rate is better than Shrinksafe's, and the size of the Closure build is 20% smaller than that of the Shrinksafe build, at least in this example.
Table 4. Mobile build size comparison between Shrinksafe and Closure
| Description | Byte size |
|---|---|
| Mobile build (Shrinksafe, gzipped) | 44,826 bytes |
| Mobile build (Closure, gzipped) | 36,639 bytes |
Dojo Mobile has been tested against what was built with Closure. Closure is recommended to use for mobile build, since its output is smaller.
Dojo Mobile provides two sample profile files: mobile-all.profile.js and mobile.profile.js, which are in the dojo/util/buildscripts/profiles folder. To easily build with these profiles, use the simple batch files available in the dojox/mobile/build folder.
From the command line, you can run the batch file. Use
build.bat for Windows, or
build.sh for Linux.
Listing 11. Usage of build batch file
> build
Usage: build separate|single [webkit]
separate Create mobile.js that includes only dojox.mobile
single Create a single dojo.js layer that includes dojox.mobile
webkit Enable webkitMobile=true option (Loses PC browser support)
|
separate uses mobile.profile.js and
creates mobile.js that includes ONLY the dojox.mobile base modules. It
does not include the dojo base or the dijit base modules. _compat.js is
also created for desktop browser support. Also, dojo.js is created, but it
is an ordinary dojo base build, not a customBase build.
Note that "the dojox.mobile base" does not include all the Dojo Mobile widgets. For example, ScrollableView, Carousel, SpinWheel, form controls, etc. are not included in the base. If you want them in your build, you can simply add them in the dependencies array in a profile file. Listing 12 shows all the modules that are rolled into the dojox.mobile base build, mobile.js.
Listing 12. Modules in mobile.js
dojox/main dojox/mobile dojox/mobile/EdgeToEdgeCategory dojox/mobile/EdgeToEdgeList dojox/mobile/Heading dojox/mobile/ListItem dojox/mobile/ProgressIndicator dojox/mobile/RoundRect dojox/mobile/RoundRectCategory dojox/mobile/RoundRectList dojox/mobile/Switch dojox/mobile/ToolBarButton dojox/mobile/TransitionEvent dojox/mobile/View dojox/mobile/ViewController dojox/mobile/_ItemBase dojox/mobile/_base dojox/mobile/common dojox/mobile/compat dojox/mobile/sniff dojox/mobile/transition dojox/mobile/uacss |
single uses mobile-all.profile.js and
creates a single dojo.js layer that includes dojox.mobile base and all the
dependent dojo/dijit modules. _compat.js is also created for desktop
browser support. This build enables the customBase option. So, only the
minimum dojo/dijit base modules are included in the resulted dojo.js.
Listing 13 shows all the modules that are rolled into the single
build.
Listing 13. Modules in dojo.js
dijit/_Contained dijit/_Container dijit/_WidgetBase dijit/main dijit/registry dojo/Evented dojo/Stateful dojo/_base/Deferred dojo/_base/array dojo/_base/config dojo/_base/connect dojo/_base/declare dojo/_base/event dojo/_base/kernel dojo/_base/lang dojo/_base/sniff dojo/_base/unload dojo/_base/window dojo/aspect dojo/dom dojo/dom-attr dojo/dom-class dojo/dom-construct dojo/dom-geometry dojo/dom-prop dojo/dom-style dojo/domReady dojo/has dojo/keys dojo/mouse dojo/on dojo/ready dojo/topic dojox/main dojox/mobile dojox/mobile/EdgeToEdgeCategory dojox/mobile/EdgeToEdgeList dojox/mobile/Heading dojox/mobile/ListItem dojox/mobile/ProgressIndicator dojox/mobile/RoundRect dojox/mobile/RoundRectCategory dojox/mobile/RoundRectList dojox/mobile/Switch dojox/mobile/ToolBarButton dojox/mobile/TransitionEvent dojox/mobile/View dojox/mobile/ViewController dojox/mobile/_ItemBase dojox/mobile/_base dojox/mobile/common dojox/mobile/compat dojox/mobile/parser dojox/mobile/sniff dojox/mobile/transition dojox/mobile/uacss |
webkit enables the webkitMobile=true
build option, which strips out code chunks that are not necessary for
Webkit-based mobile browsers. For example, Internet Explorer- or
Firefox-specific code is excluded from the build. This reduces the total
code size, but the built module will not work on desktop browsers even
with the compatibility module (compat.js).
Also note that this option reduced a significant amount of code in Dojo 1.6, but in Dojo 1.7, feature detection/testing is moving to dojo.has, and thus the webkitMobile option no longer has much effect on code reduction.
Dojo Mobile has bunch of CSS files under the themes folder. There is a CSS file for each widget, and they are available for each theme, Android, Blackberry, Custom, and iPhone. Also, there are CSS files for DOM Buttons or transition animations. To help you easily include necessary CSS files in your application, some entry point CSS files aggregate a number of related CSS files:
- All-in-one theme file (example: themes/iphone/iphone.css)
Includes all the common CSS files and the theme CSS files - Base theme file (example: themes/iphone/base.css)
Includes theme CSS files for dojox.mobile base modules - DOM Buttons (themes/common/domButtons.css)
Includes all the DOM Buttons - Transitions (themes/common/transitions.css)
Includes all the transition animations
Use of the all-in-one theme file is the easiest, since it includes everything. However, that means unused CSS files may be included, and that could increase footprint unnecessarily. In that case, one approach is to use the base theme file and individual CSS files that are not included in the base theme file.
The above entry point CSS files are a collection of @import directive. If you perform Dojo build, @import statements are inlined and thus the referenced CSS files are combined together in the entry point CSS file. So, use of one entry point CSS file produces only one HTTP request, if it is built. However, if you listed CSS files in your application using <link> or @import as shown in Listing 14, HTTP requests would be made for each of them.
Listing 14. Link tags in html (userApp.html)
<head> <link href="../themes/iphone/base.css" rel="stylesheet"> <link href="../themes/iphone/TabBar.css" rel="stylesheet"> <link href="../themes/common/SpinWheel.css" rel="stylesheet"> <link href="../themes/common/domButtons/DomButtonBlueCircleArrow.css" rel="stylesheet"> .... |
To reduce the number of requests, create your own entry point CSS that has references to the minimum necessary CSS files using the @import directive as shown in Listing 15. If you perform a Dojo build, it will be an inlined CSS file without external references. You can use it from your application as shown in Listing 16.
Listing 15. A CSS file for aggregation (myStyles.css)
@import url("../themes/iphone/base.css");
@import url("../themes/iphone/TabBar.css");
@import url("../themes/common/SpinWheel.css");
@import url("../themes/common/domButtons/DomButtonBlueCircleArrow.css");
|
Listing 16. A single link tag in html (userApp.html)
<link href="myStyles.css" rel="stylesheet"> |
As described above, you can reduce the number of HTTP requests for CSS files by creating your own entry point CSS file and perform Dojo build.
Dynamic creation and lazy loading
Lazy loading—a technique to load modules only when they are referenced for the first time—improves the application's startup performance. Dojo Mobile itself uses the lazy loading technique internally.
With the url property of
_ItemBase, you can dynamically create a new
view immediately before making a view transition. Listing 17 shows an
example usage of the url property. The view
content can either be an HTML fragment (Listing 18) or JSON data (Listing
19).
Listing 17. Example of the url property
<ul dojoType="dojox.mobile.RoundRectList">
<li dojoType="dojox.mobile.ListItem" url="view1.html">
External View #1 (sync)
</li>
<li dojoType="dojox.mobile.ListItem" url="view2.json" sync="false">
External View #2 (async)
</li>
</ul>
|
Listing 18. An HTML fragment for a dynamic view (view1.html)
<div dojoType="dojox.mobile.View">
<h1 dojoType="dojox.mobile.Heading" back="Home" moveTo="foo">view1.html</h1>
<ul dojoType="dojox.mobile.EdgeToEdgeList">
<li dojoType="dojox.mobile.ListItem">
Jack Coleman
</li>
<li dojoType="dojox.mobile.ListItem">
James Evans
</li>
<li dojoType="dojox.mobile.ListItem">
Jason Griffin
</li>
</ul>
</div>
|
Listing 19. JSON data for a dynamic view (view2.json)
{
"dojox.mobile.View": {
"dojox.mobile.Heading": {
"@back": "Home",
"@moveTo": "foo",
"@label": "view1.json"
},
"dojox.mobile.EdgeToEdgeList": {
"dojox.mobile.ListItem": [{
"@label": "Jack Coleman"
}, {
"@label": "James Evans"
}, {
"@label": "Jason Griffin"
}]
}
}
}
|
Another option is to programmatically fetch view content and insert it in the target view. Listing 20 shows an example.
Listing 20. Example of loading content into an existing view and making a transition
<li dojoType="dojox.mobile.ListItem" moveTo="#" onclick="myAction2(this)">
Load and Move (async)
</li>
----
function myAction2(li){
var view2 = dijit.byId("view2"); // destination view
var listItem = dijit.byNode(li);
var prog = dojox.mobile.ProgressIndicator.getInstance();
dojo.body().appendChild(prog.domNode);
prog.start();
view2.destroyDescendants();
var url = "http://..."; // or var url = listItem.url;
dojo.xhrGet({
url: url,
handleAs: "text",
load: function(response, ioArgs){
var container = view2.containerNode;
container.innerHTML = response;
dojo.parser.parse(container);
prog.stop();
listItem.transitionTo("view2");
}
});
}
|
See dojox/mobile/tests/test_list-actions.html for details and more examples.
IconContainer can have multiple icons, each of
which represents a sub application. The sub applications may consist of
one or more Dojo widgets. Loading of all the sub application code at
startup could slow down the startup time of the main application. To
improve the startup time performance, you can specify the
lazy="true" parameter on
IconItems. Then the Dojo parser skips
instantiation of widgets inside IconItem, and
IconContainer loads those icon content modules
dynamically and instantiates them only when an icon is opened for the
first time.
Listing 21 is an example of lazy loading of icon contents. Note that you do
not have to explicitly require icon content modules
(dijit.CalendarLite in the following example).
Note also that, in Dojo 1.7, lazy loading is supported only in the sync
loader mode, since lazy loading is performed synchronously using
dojo.require.
Listing 21. Example of IconContainer's lazy load
<ul dojoType="dojox.mobile.IconContainer">
<li dojoType="dojox.mobile.IconItem" label="Calendar" lazy="true">
<div id="cal" dojoType="dijit.CalendarLite"></div>
</li>
....
|
Figure 17. IconContainer
If you need lazy-loadable tab panels, you can use the
TabBar widget and the same technique as
described in "Creating a view dynamically." For tab
panels, you also need a little trick for the first tab panel, because
there is no view transition at startup. You need to programmatically make
a view transition from a dummy blank view to the first tab panel at
startup to load external contents into the first tab panel. Listing 22 and
Listing 23 show the same examples; the former is a sync example, the
latter is an async example.
Listing 22. Example of lazy tab panels (sync mode)
<script src="../../../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
<script language="JavaScript" type="text/javascript">
dojo.require("dojox.mobile");
dojo.require("dojox.mobile.parser");
dojo.require("dojox.mobile.compat");
dojo.require("dojox.mobile.TabBar");
dojo.ready(function(){
setTimeout(function(){
dijit.byId("tab1").onClick();
}, 0);
});
</script>
</head>
<body style="visibility:hidden;">
<ul dojoType="dojox.mobile.TabBar" barType="segmentedControl">
<li id="tab1" dojoType="dojox.mobile.TabBarButton" url="view1.html">New</li>
<li id="tab2" dojoType="dojox.mobile.TabBarButton" url="view2.html">What's Hot</li>
<li id="tab3" dojoType="dojox.mobile.TabBarButton" url="view3.html">Genius</li>
</ul>
<div id="blank" dojoType="dojox.mobile.View" selected="true"></div>
<div id="view1" dojoType="dojox.mobile.View"></div>
<div id="view2" dojoType="dojox.mobile.View"></div>
<div id="view3" dojoType="dojox.mobile.View"></div>
</body>
|
Listing 23. Example of lazy tab panels (async mode)
<script src="../../../dojo/dojo.js" djConfig="async: true, parseOnLoad: true"></script>
<script language="JavaScript" type="text/javascript">
require([
"dojo/_base/kernel",
"dijit/registry",
"dojox/mobile",
"dojox/mobile/compat",
"dojox/mobile/parser",
"dojox/mobile/TabBar"
], function(dojo, registry){
dojo.ready(function(){
setTimeout(function(){
registry.byId("tab1").onClick();
}, 0);
});
});
</script>
</head>
<body style="visibility:hidden;">
<ul dojoType="dojox.mobile.TabBar" barType="segmentedControl">
<li id="tab1" dojoType="dojox.mobile.TabBarButton"
url="view1.html" sync="false">New</li>
<li id="tab2" dojoType="dojox.mobile.TabBarButton"
url="view2.html" sync="false">What's Hot</li>
<li id="tab3" dojoType="dojox.mobile.TabBarButton"
url="view3.html" sync="false">Genius</li>
</ul>
<div id="blank" dojoType="dojox.mobile.View" selected="true"></div>
<div id="view1" dojoType="dojox.mobile.View"></div>
<div id="view2" dojoType="dojox.mobile.View"></div>
<div id="view3" dojoType="dojox.mobile.View"></div>
</body>
|
Requiring modules dynamically at runtime is a good idea, since it could
improve the startup time performance.
But there is one potential problem you need to be aware of. Take a look at
Listing 24; it shows loading a Dojo module programmatically. It does work,
but if you build Listing 24, the build tool automatically picks up the
required module, and rolls it into a build, and thus
dojo.require does nothing at runtime since the
module has already been loaded at startup time.
Listing 24. Load a Dojo module programmatically (WRONG example)
myHandler: function(e){
dojo.require("dijit.CalendarLite");
var cal = new dijit.CalendarLite();
....
}
|
To avoid that issue, you could write
dojo["require"] instead of
dojo.require as shown in Listing 25.
Listing 25. Load a Dojo module programmatically (CORRECT example)
myHandler: function(e){
dojo["require"]("dijit.CalendarLite");
var cal = new dijit.CalendarLite();
....
}
|
If your application is using the async loader, the syntax differs as shown in Listing 26. But this is not a good example either, since the build tool picks up the specified module unexpectedly if you write the code this way.
Listing 26. Load a Dojo module programmatically (WRONG example)
myHandler: function(e){
require(["dijit/CalendarLite"], lang.hitch(this, function(module){
var cal = new module();
....
}));
}
|
You can avoid the build problem by assigning the class name to a variable as shown in Listing 27.
Listing 27. Load a Dojo module programmatically (CORRECT example)
myHandler: function(e){
var cls = "dijit/CalendarLite"; // assign to a variable so as not to be in the build
require([cls], lang.hitch(this, function(module){
var cal = new module();
....
}));
}
|
In Dojo 1.7, a new AMD (Asynchronous Module Definition) loader is provided
in addition to the traditional Dojo loader. Dojo Mobile widgets are
written in the new AMD syntax. To load any Dojo modules, you can use
either traditional dojo.require (Listing 28) or
the new require API (Listing 29).
Listing 28. Example of dojo.require (traditional)
<script src="../dojo/dojo.js" djConfig="parseOnLoad: true"></script>
<script language="JavaScript" type="text/javascript">
dojo.require("dojox.mobile");
dojo.require("dojox.mobile.parser");
dojo.require("dojox.mobile.compat");
</script>
|
Listing 29. Example of require (AMD syntax)
<script src="../dojo/dojo.js" djConfig="async:true, parseOnLoad:true"></script>
<script language="JavaScript" type="text/javascript">
require([
"dojox/mobile",
"dojox/mobile/parser",
"dojox/mobile/compat"
]);
</script>
|
Listing 28 loads modules synchronously, while Listing 29 does it asynchronously. In circumstances where a lot of JavaScript files are loaded, it is expected that asynchronous loading will perform better than synchronous loading. If the JavaScript files are combined together into a single built file, however, there may not be much difference between synchronous and asynchronous.
However, there is a bigger difference you should be aware
of. Figure 18
shows the transferred files when test_iPhone-Animation.html, which loads
modules in the Listing 28 way, is opened, and Figure 19 shows the ones
when test_iPhone-Animation-async.html, which loads modules in the Listing
29 way, is opened. As shown in the Table 5, in the sync mode, 17 more
files, 26KB in total, are additionally loaded. This is because the sync
mode works in the backward compatibility mode, and thus loads some
required modules to keep backward compatibility. Given that
test_iPhone-Animation-async.html works without those additional modules,
it is obvious that they are not used, and do not have to be loaded.
Therefore, even if you carefully choose what modules to use, and optimize
your build using the customBase option, use of
dojo.require() could derail your effort. You
should use the require API rather than
dojo.require() to
optimize your application's
performant.
Figure 18. Synchronous loading (test_iPhone-Animation.html)
Figure 19. Asynchronous loading (test_iPhone-Animation-async.html)
Table 5. Resource download comparison between sync mode and async mode
| File | Number of requests | Total size |
|---|---|---|
| test_iPhone-Animation.html | 23 | 69.15 KB |
| test_iPhone-Animation-async.html | 6 | 43.54 KB |
Incidentally, even if you use the AMD syntax like Listing 29, if you do not
specify async:true (the default value is
false), your application runs in the compatibility mode, and additional
modules are loaded.
dojox.mobile.parser is a small subset of dojo.parser. It was developed purely to reduce the total code size. It has no mobile-specific extra features over dojo.parser, so there is no reason you must use dojox.mobile.parser instead of dojo.parser; you can choose the one you like. Some of the advanced features of dojo.parser, such as <script type="dojo/method"> and <script type="dojo/connect">, are missing from dojox.mobile.parser. But dojox.mobile.parser is smaller.
As shown in Table 6, the size of dojox.mobile.parser is about 0.7KB (minified & gzipped), while dojo.parser (plus its dependent modules that are not required by the dojox.mobile base) is 6.5KB. If dojox.mobile.parser's capability is enough for your application, using it could reduce the total code size of your application.
Table 6. Size comparison between dojox.mobile.parser and dojo.parser
| Description | Byte size |
|---|---|
| dojox.mobile.parser | 734 bytes |
| dojo.parser + dependent modules | 6,507 bytes |
This article has shown how to build lightweight mobile web applications using Dojo Mobile, and how to apply its performance-optimizing techniques to your applications.
Learn
- Learn about Dojo's mobile
features.
- Read the latest dojox.mobile
documentation.
- Try the latest Dojo Mobile 1.7 nightly build tests.
- In the developerWorks
Web development zone, find hundreds of how-to articles and tutorials, as well as downloads, discussion
forums, and a wealth of other resources for web developers.
- Check for mobile updates on the
developerWorks Mobile development blog.
- You'll find many more articles on mobile topics, including articles on Dojo Mobile on developerWorks.
- Stay current with developerWorks technical events and webcasts focused on a variety
of IBM products and IT industry topics.
- Attend a free developerWorks Live! briefing to get up-to-speed quickly on
IBM products and tools, as well as IT industry trends.
- Watch developerWorks on-demand demos ranging from product installation
and setup demos for beginners, to advanced functionality for experienced
developers.
- Follow developerWorks on
Twitter.
Get products and technologies
- Download the
latest Dojo 1.7 from the Dojo
Toolkit download page.
- Download and try
the IBM Mobile Technology Preview, a set of code samples and services
to help you get started building mobile applications that extend and
integrate into the enterprise. The preview includes a RESTful notification
service; PhoneGap, an open source framework for building hybrid mobile
apps; a lightweight WebSphere Application Server runtime; and sample code
to let you see how it all works.
-
IBM WebSphere Application Server Feature Pack for Web 2.0 and
Mobile includes the IBM Dojo 1.7 Toolkit, new mobile and rich
Internet application (RIA) building blocks, and a Dojo-based diagram
component. With accompanying Rational tools, the Feature Pack helps you
take WebSphere applications developed originally for desktop browsers and
adapt and deploy them to mobile devices.
-
Evaluate
IBM products in the way that suits you best: Download a product
trial, try a product online, use a product in a cloud environment, or
spend a few hours in the SOA Sandbox learning how to implement Service Oriented
Architecture efficiently.
Discuss
- Get involved in the developerWorks
community. Connect with other developerWorks users while exploring
the developer-driven blogs, forums, groups, and wikis.

Yoshiroh Kamiyama is an Advisory Software Engineer at Yamato Software Lab (YSL), IBM Japan. He works on WebSphere Feature Pack for Web 2.0 and Mobile, and previously worked on several development projects including Mobile Mashup, Lotus iNotes, and Rational Portfolio Manager, many of which used the Dojo Toolkit. He is an original contributor of dojox.mobile and a committer to the Dojo Toolkit.




