Are the smartphone wars wearing your out? When asked to choose between Objective-C and Java do you answer “None of the Above”? Do you think app stores are so 1995? Then there is good news for you and it’s called the mobile web. This isn’t about trying to port iFart to the browser, and it’s definitely not about tweaking an existing website so it doesn’t look awful on your mom’s iPhone. It is about writing full featured, engaging applications on the web. This talk is all about how to create killer web apps using HTML5, CSS3, as well as some other not-so-standard technologies available on a wide variety of popular smartphones. We’re talking about multi-threaded, high performance apps that can track your movement or even take pictures of whatever you think is interesting.
17. MO BILE
W E B GEOLOCATION
geocoder = new google.maps.Geocoder();
if (navigator.geolocation){
var gps = navigator.geolocation;
gps.getCurrentPosition(function(pos){
var latLng = new google.maps.LatLng(pos.coords.latitude,pos.coords.longitude);
var opts = {zoom:12, center:latLng, mapTypeId: google.maps.MapTypeId.ROADMAP};
map = new google.maps.Map($("map_canvas"), opts);
theUser = new google.maps.Marker({
position: latLng,
map: map,
title: "You!"
});
});
trackerId = gps.watchPosition(function(pos){
var latLng = new google.maps.LatLng(pos.coords.latitude,pos.coords.longitude);
map.setCenter(latLng);
theUser.setPosition(latLng);
});
}
18. MO BILE
W E B GEOLOCATION
OS/Browser Status/Version
3.0
2.0
6.0
X
X
19. MO BILE
W E B DOM STORAGE
if (window.localStorage){
localStorage.setItem("tweet" + tweet.id, JSON.stringify(tweet));
var index = localStorage.getItem("index::" + keyword);
if (index){
index = JSON.parse(index);
} else {
index = [];
}
index.push(tweet.id);
localStorage.setItem("index::"+keyword, JSON.stringify(index));
}
20. MO BILE
W E B DOM STORAGE
if (window.localStorage){
localStorage.setItem("tweet" + tweet.id, JSON.stringify(tweet));
var index = localStorage.getItem("index::" + keyword);
if (index){
index = JSON.parse(index);
} else {
index = [];
}
index.push(tweet.id);
localStorage.setItem("index::"+keyword, JSON.stringify(index));
}
21. MO BILE
W E B DOM STORAGE
OS/Browser Status/Version
3.0
2.0
6.0
7.0
X
22. MO BILE
W E B WEB WORKERS
var worker = new Worker("details.js");
worker.onmessage = function(message){
var responseXmlStr = message.data.responseXml;
var itemDetails = parseFromXml(responseXmlStr);
if (window.localStorage){
localStorage.setItem(itemDetails.id, responseXmlStr);
}
dealDetails[itemDetails.id] = itemDetails;
};
worker.postMessage(item.itemId);
onmessage = function(message){
var itemId = message.data;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200){
postMessage({responseXml: this.responseText});
}
};
var urlStr = generateUrl(itemId);
xhr.open("GET", "proxy?url=" + escape(urlStr));
xhr.send(null);
}
23. MO BILE
W E B WEB WORKERS
OS/Browser Status/Version
X
2.0
6.0
X
X
24. MO BILE
W E B WEBSOCKET
if (window.WebSocket){
var conn = new WebSocket("ws://my.server.com/socket");
conn.onopen = function(){
setStatusMessage('connecting...');
conn.send('connect');
};
conn.onmessage = function(msg){
setStatusMessage('connected');
updateItemStatus(JSON.parse(msg.data));
};
a
at
conn.onerror = function(err){
D
showError(err);
conn.close();
};
conn.onclose = function(evt){
setStatusMessage('connection closed');
};
}
25. MO BILE
W E B WEBSOCKET
OS/Browser Status/Version
4.2b
X
X
X
X
26. MOBILE
W E B CANVAS
var ctx = $("graph").getContext("2d");
ctx.font = "bold 12px sans-serif";
ctx.textAlign = "start";
for (i=0;i<data.length;i++){
ctx.fillStyle = "rgba(0, 0, 200, 0.9)";
ctx.fillRect(x, maxHeight - (data[i][report.y] / 2), width,
(data[i][report.y] / 2));
ctx.fillStyle = "rgba(0, 0, 0, 0.9)";
ctx.fillText(data[i][report.x], x + (width / 4),
maxHeight + 15);
x += width + buffer;
}
ctx.moveTo(axisBuffer, maxHeight);
ctx.lineTo(axisBuffer+maxWidth, maxHeight);
ctx.strokeStyle = "black";
ctx.stroke();
ctx.moveTo(axisBuffer,0);
ctx.lineTo(axisBuffer,maxHeight);
ctx.stroke();
27. MO BILE
W E B CANVAS
OS/Browser Status/Version
1.0
1.0
6.0
X
v2
28. MOBILE
W E B CSS 3.0
$("formSection").style["-webkit-transform"] = "rotateZ(-5deg)";
$("formSection").style["-webkit-transition"] =
"-webkit-transform 2s ease-in-out";
$("rtBtn").innerHTML = "Undo";
$("rtBtn").onclick = function() {
$("formSection").style["-webkit-transform"] = "";
$("rtBtn").innerHTML = "Rotate";
$("rtBtn").setAttribute("onclick", "rotate()");
}
30. MO BILE
W E B CSS 3.0
OS/Browser Status/Version
3.0
2.0
X
X
X
31. MO BILE
APPLICATION
W E B
CACHE <!DOCTYPE html>
<html manifest="manifest.mf">
<head>
<!-- ... -->
</head>
<body>
<!-- ... -->
</body>
</html>
CACHE MANIFEST
# Version 0.2
CACHE:
offline.html
json2.js
/images/gym.jpg
/images/soccer.jpg
/images/online.jpg
NETWORK:
http://search.twitter.com/
32. MO BILE
W E B APPLICATION
OS/Browser Status/Version
2.0
2.0
6.0
X
X
33. DEVICE
MOBILE
W E B
if (navigator.device.captureImage){
device.captureImage(function(data){
var file = data[0];
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", function(e) {
if (e.lengthComputable) {
var percentage = Math.round((e.loaded * 100) / e.total);
updateStatusBar(percentage);
}
}, false);
xhr.open("POST", "http://my.server.com/upload");
xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
xhr.sendAsBinary(file.getAsBinary());
});
}
34. MO BILE
W E B DEVICE
OS/Browser Status/Version
X
3.0
X
X
X
35. MO BILE
W E B TOUCH EVENTS
logo.ontouchmove = function(event){
if (event.touches.length == 1){
event.preventDefault();
var touch = event.touches[0];
var node = touch.target;
node.style.position = "absolute";
node.style.left = touch.pageX + "px";
node.style.top = touch.pageY + "px";
}
}
var angle = 0;
logo.ongesturechange = function(event){
var node = event.target;
node.style.webkitTransform = "rotate("+
((angle + event.rotation) % 360)+"deg)";
}
logo.ongestureend = function(event){
angle = (angle + event.rotation) % 360;
}
36. MO BILE
W E B TOUCH EVENTS
OS/Browser Status/Version
2.0
1.0
6.0?
X
X
37. MO BILE
W E B AUDIO/VIDEO
<video controls="controls" preload="true"
width="720" height="640">
<source src="feature.ogg" type="video/ogg" />
<source src="feature.mp4" type="video/mp4" />
Your browser sucks
</video>
38. MO BILE
W E B AUDIO/VIDEO
OS/Browser Status/Version
1.0
2.0
X
X
X
39. MO BILE
W E B META
<meta name="viewport" content="width=device-width; user-
scalable=no;"/>
<meta name="apple-touch-fullscreen" content="YES" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style"
content="black" />
<link rel="apple-touch-icon" href="rice-and-bones.png"/>
41. MOBILE
BEST
W E B
PRACTICES
• Servers are for data
• Orientation matters
• Cache, cache, cache
• Frameworks (not really mobile): SproutCore, Cappuccino
• Frameworks (mobile): Sencha, jQTouch