Mobile Web 5.0

Preview:

DESCRIPTION

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.

Citation preview

MOBILE WEB 5.0Michael Galpin, eBay

WHO AM I?

Michael Galpin

Mobile Architect, eBay

Android & Mobile Web

Author, Android in Practice

@michaelg

WHY?

Mobile is the new HOTness

MOBILEW E B THE IPHONE MYTH

MOBILEW E B

2 BIRDS, 1 STONE?

MOBILEW E B

ONE WEBKIT TO RULE THEM ALL?

MOBILEW E B

ONE WEBKIT TO RULE THEM ALL?

Android 2.2.1 iOS 4.1

MOBILEW E B

PARTY LIKE IT’S 2022

WHAT?

WHAT ABOUT?

OMG! VIDEO TAG!!!

HTML

HTML

JavaScript

CSS 3.0

MOBILEW E B

JUST ADD VIEWPORT?

HOW?

MOBILEW 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); });}

MOBILEW E B GEOLOCATION

OS/Browser Status/Version

3.0

2.0

6.0

X

X

MOBILEW 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)); }

MOBILEW 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)); }

MOBILEW E B DOM STORAGE

OS/Browser Status/Version

3.0

2.0

6.0

7.0

X

MOBILEW 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);}

MOBILEW E B WEB WORKERS

OS/Browser Status/Version

X

2.0

6.0

X

X

MOBILEW E B WEBSOCKET

Data

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)); }; conn.onerror = function(err){ showError(err); conn.close(); }; conn.onclose = function(evt){ setStatusMessage('connection closed'); };}

MOBILEW E B WEBSOCKET

OS/Browser Status/Version

4.2b

X

X

X

X

MOBILEW 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();

MOBILEW E B CANVAS

OS/Browser Status/Version

1.0

1.0

6.0

X

v2

MOBILEW 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()");}

MORE CSS 3.0tr:nth-child(4n+1) { color: navy; }tr:nth-child(4n+2) { color: green; }tr:nth-child(4n+3) { color: maroon; }tr:nth-child(4n+4) { color: purple; }header > h1{ color: yellow; background: -webkit-gradient(linear, left top, left bottom, from(blue), to(white))}.xyz{ text-shadow: #6374AB 4px -4px 2px; overflow: hidden; text-overflow: ellipsis; border: 1px solid #bbb; border-radius: 9px; background-color: #fff;}

.abc { border: 1px solid #000; border-radius: 9px; -webkit-column-count:4; -webkit-column-rule: 1px solid #a00; -webkit-column-gap: 0.75em;}h2 { -webkit-text-fill-color: blue; -webkit-text-stroke-color: yellow; -webkit-text-stroke-width: 1.5px; background: -webkit-gradient(radial, 430 50, 0, 430 50, 200, from(red), to(#000)); -webkit-box-reflect:below 5px -webkit-gradient( linear, left top, left bottom, from(transparent), color-stop(0.5, transparent), to(white));}

MOBILEW E B CSS 3.0

OS/Browser Status/Version

3.0

2.0

X

X

X

MOBILEW E B

APPLICATION CACHE

<!DOCTYPE html><html manifest="manifest.mf"><head> <!-- ... --></head><body> <!-- ... --></body></html>

CACHE MANIFEST# Version 0.2CACHE:offline.htmljson2.js/images/gym.jpg/images/soccer.jpg/images/online.jpg

NETWORK:http://search.twitter.com/

MOBILEW E B APPLICATION

OS/Browser Status/Version

2.0

2.0

6.0

X

X

MOBILEW E B DEVICE

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()); });}

MOBILEW E B DEVICE

OS/Browser Status/Version

X

3.0

X

X

X

MOBILEW 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;}

MOBILEW E B TOUCH EVENTS

OS/Browser Status/Version

2.0

1.0

6.0?

X

X

MOBILEW 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>

MOBILEW E B AUDIO/VIDEO

OS/Browser Status/Version

1.0

2.0

X

X

X

MOBILEW 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"/>

NO REALLY, HOW?

MOBILEW E B

BEST PRACTICES

• Servers are for data

• Orientation matters

• Cache, cache, cache

• Frameworks (not really mobile): SproutCore, Cappuccino

• Frameworks (mobile): Sencha, jQTouch