If you have been following any of my bogs in the past, we presented techniques for optimizing JavaScript libraries when used with mobile devices. Some of this centered on using more traditional java/Ajax frameworks such as java server pages to execute most of the complicated logic on the server side vs. the device side.
Here we take two different approaches for creating an iphone type image slider, one approach uses an iphone web application and the other a native application.
Both utilize commonly available JavaScript libraries, the purely web approach exposes the yahoo user interface library carousel as a jsf component using a widely available ajax/jsf component platform icefaces in this case.
http://web.me.com/cannonwc/Site_4/contents/Entries/2009/1/28_Building_A_carousel_in_5_steps.html
The approach works rather well for mobile web applications as long as you keep the size of the exposed jsf component to a minimum, remember execution takes place on the server side; this is in some ways similar to GWT. Playing with this slider over a fast 3g or wi-fi network shows some impressive results. Performance is good but not great over an EDGE connection.
The best way to utilize JavaScript libraries in mobile applications and not have network degradation is to remove the server from the equation and execute the JavaScript on the device itself. Although the above-described technique will work with any webkit browser what follows is very Iphone specific.
The question begs, why use a JavaScript framework over native objective-c code. The short answer is that the iphone has been around for only a relatively short period but JavaScript libraries such as yui, jquery and others have been in use for some time, have matured and a vast number of useful components have been produced.
Take visualization for instance, as our world becomes more complex the amount of material that must be catorgized, digested and disseminated in usable form becomes almost unmanageable. Volumes of research have been produced in just how to slice the mountains of data into discrete chunks that can be analyzed. Especially when non traditional display technologies are utilized, volumetric displays, screens on mobile devices to name a few.
Some of the more useful techniques that have been proposed use hyperbolic browsers, directed force graphs and treemaps.
To reproduce these on an iphone or android device in open/el or open/gl would not be impossible but would not be easy either.
Fortunately there are a few very nice JavaScript libraries available.
- java script infoVis toolkit http://thejit.org/
- Processing.js , which is a branch of the MIT processing Project http://processingjs.org/
- A few of us have gotten Mit simele to work quite well with iphone/andorid http://simile.mit.edu/wiki/SIMILE:About
Although these frameworks are powerful over a slow connection they can be maddening to load.
But there is another way to optimize network bandwidth and still get the advantages some of these toolkits provide, Execute the JavaScript on the device.
Two things to remember. The iphone screen ui is essentially flat and 2d, if you carefully choose you color and shading the user will not be able to deduce the difference between the screens created in JavaScript and those created using the native sdk.
The example I am about to discuss creates a simple slider using jquery. If you have not already done so please download the sample code. (available internally only, others may get the code by emailing mooncatventures.com).
simpleExample.xcode actually illustrates a few different techniques, but our focus is on jquery.
Notice the 2 JavaScript libraries jquery-1.32 which is the jquery core library and the open source looped-slider jquery component. These should be copied into your resource bundle along with the images you which to utilize in your slideshow, alternatively your server could produce a simple json or xml page that could be parsed from an xmlhttprequest in your index or main js file, also in the resource bundle.
Once you have your JavaScript code in place it is a simple matter of executing it using the following.
//determine the path the to the index.html file in the Resources directory
// NSString *domain = @"domain:'http://172.16.1.33:49258'";
NSString *filePathString = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSMutableString *html = [[NSMutableString alloc] initWithContentsOfFile: filePathString];
//
// [html replaceOccurrencesOfString: @"domain:''" withString: domain
// options: NSLiteralSearch range: NSMakeRange(0, [html length])];
//NSURLRequest *aRequest = [NSURLRequest requestWithURL:
// [NSURL initWithString:html]];
//build the URL and the request for the index.html file
NSURL *aURL = [NSURL fileURLWithPath:filePathString];
[aWebView loadHTMLString:html baseURL:aURL];
//NSURLRequest *aRequest = [NSURLRequest requestWithURL:aURL];
//load the index.html file into the web view.
// [aWebView loadRequest:aRequest];
//add the web view to the content view
[contentView addSubview:webView];
For convience here we use the quickconnectViewController from the QC project, but this is not really necessary. just do something like the above code.
The index file in the resource bundle looks like this.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>browse</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="minimum-scale=1.0, width=device-width, maximum-scale=1">
<meta name="apple-mobile-web-app-capable" content="YES">
<link rel="apple-touch-icon" href="WebClipIcon.png">
<link rel="stylesheet" href="main.css">
<script type="text/javascript" src="setup.js" charset="utf-8"></script>
<script type="text/javascript" src="Text.js" charset="utf-8"></script>
<script type="text/javascript" src="main.js" charset="utf-8"></script>
<script src="jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
<script src="loopedslider.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
$(function(){
var id=0;
var slides = document.getElementById("slide");
var div = document.createElement("div");
div.setAttribute('id', id);
var elem = document.createElement("img");
elem.setAttribute("src", "image-04.jpg");
elem.setAttribute("height", "100%");
elem.setAttribute("width", "100%");
elem.setAttribute("alt", "a"+id);
div.appendChild(elem);
slides.appendChild(div);
var elem1 = document.createElement("img");
var div1 = document.createElement("div");
elem1.setAttribute("src", "image-03.jpg");
elem1.setAttribute("height", "100%");
elem1.setAttribute("width", "100%");
elem1.setAttribute("alt", "a"+id++);
div1.appendChild(elem1);
slides.appendChild(div1);
var div2 = document.createElement("div");
var elem2 = document.createElement("img");
elem2.setAttribute("src", "image-02.jpg");
elem2.setAttribute("height", "100%");
elem2.setAttribute("width", "100%");
elem2.setAttribute("alt", "a"+id++);
div2.appendChild(elem2);
slides.appendChild(div2);
$('#loopedSlider').loopedSlider();
});
</script>
<style type="text/css" media="screen">
/*
* Required
*/
.container { width:500px; height:375px; overflow:hidden; position:absolute; cursor:pointer; }
.slides { position:absolute; top:0; left:0; }
.slides div { position:absolute; top:0; width:500px; display:none; }
/*
* Optional
*/
#loopedSlider,#newsSlider { margin:0 auto; width:500px; position:relative; clear:both; }
ul.pagination { list-style:none; padding:0; margin:0; }
ul.pagination li { float:left; }
ul.pagination li a { padding:2px 4px; }
ul.pagination li.active a { background:blue; color:white; }
</style>
</head>
<body onload="load();">
<div id="content">
<div id="loopedSlider">
<div class="container">
<div id="slide" class="slides">
</div>
<a href="#" class="previous"><img src="previous1.png" width="50" height="50" id="img1"></a>
<a href="#" class="next"><img src="next1.png" width="50" height="50" id="img"></a>
</div>
</div>
<div id="footer"></div>
</div>
</body>
</html>
Comments