View
227
Download
2
Category
Tags:
Preview:
Citation preview
Bringing sexy back to the mobile web
Mohammad (Mo) Jangda
batmoo@gmail.commohammad.jangda@vortexmobile.ca
http://digitalize.ca@mjangda
’
Move over Jesse James Garret!
We've found the new AJAX!
• HTML4 all grown up?
• xHTML's way cooler cousin?
• 5 Highly Trained Militant Lemurs?
Steve JobsInventor of HTML5
HTML
CSS
JavaScript
Semantics
Forms
Geolocation
Offline
Presentation
StylingTransformsAnimations
Rich MediaAudioVideo
Canvas
Minus some legitimate & illegitimate cousins...
Web Workers
Web Sockets
Storage
Good markup is healthy markup.
Add all the whiz, bang, and fireworks without having
to rely on 3rd party libraries and plugins.
Stuff that took images and extra markup and hours to perfect, now available through a CSS property or two.
APIs that help us build more powerful, feature-rich mobile webapps.
Helping bridge the gap between native and web.
’
•It's finally growing up
•WebApps are better, smarter, sexier
•WebApps can do more with less
•WebApps can do the same, if not more than Native Apps
CO
DE
<video src=“movie.mp4” />
<audio src=“sound.wav” />
Simple
CO
DE
<video width=”320” height=”240” poster=”poster.png”> <source src="video.m4v" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' /> <source src="video.webm" type='video/webm; codecs="vp8, vorbis"' /> <source src="video.ogv" type='video/ogg; codecs="theora, vorbis"' /> <object> <!-- Add Flash fallback here --> <!-- Be nice to really dumb devices --> <p>Download the <a href="video.mp4">video</a></p> </object></video>
Advanced
Player is customizable and programmatically
accessible through javascript (i.e. play, pause, etc.)
Not the case on mobile devices(iPad excluded)
Most devices offload audio and video playback to
their native media players...which is
a good thing
Oh, and support kinda sucks...
YAUFW!(Yet Another Unnecessary Format War)
CO
DE
<div class="qzForm roundedcornr_box_812460"><div class="roundedcornr_top_812460">
<div></div></div><div class="roundedcornr_content_812460">
Your content goes here!</div>
<div class="roundedcornr_bottom_812460"><div></div>
</div></div>
<style>/* Rounded corner for registration tab */
.roundedcornr_box_812460 { background: url(../images/rounded/roundedcornr_812460_tl.png) no-repeat top left;
} .roundedcornr_top_812460 {
background: url(../images/rounded/roundedcornr_812460_tr.png) no-repeat top right; } .roundedcornr_bottom_812460 {
background: url(../images/rounded/roundedcornr_812460_bl.png) no-repeat bottom left; } .roundedcornr_bottom_812460 div {
background: url(../images/rounded/roundedcornr_812460_br.png) no-repeat bottom right; } .roundedcornr_content_812460 {
background: url(../images/rounded/roundedcornr_812460_r.png) top right repeat-y; }
.roundedcornr_top_812460 div,.roundedcornr_top_812460, .roundedcornr_bottom_812460 div, .roundedcornr_bottom_812460 {
width: 100%; height: 15px; font-size: 1px;
} .roundedcornr_content_812460, .roundedcornr_bottom_812460 {
/*margin-top: -19px;*/ } .roundedcornr_content_812460 { padding: 0 15px; }</style>
Pre-CSS3: Rounded Corners
CO
DE
CSS3: Rounded Corners
<div class=“rounded”>This is content
</div>
<style type=“text/css”>.rounded {
border-radius: 5px;border: 1px solid #111;
}</style>
Yes, we just went from 3 billion lines of code...
...to just under 10.
Rounded corners:border-radius
Drop shadows: box-shadow & text-shadow
Multiple columns:column-count & column-gap
Transparent backgrounds:rgba
Multiple backgrounds
Background gradients
’
border-radius
-moz-border-radius (for Fennec / FF)-o-border-radius (for Opera Mobile)-webkit-border-radius (in Mobile Safari, Android, webOS, BB6)-ms-border-radius (in IE Mobile)
Well, close enough.
Attribute pattern-matching
starts with[rel^=”awesome”]
ends with[title$=”amazing”]
contains[name*=”super”]
Element matching
nth-childnth-child(odd) nth-child(2) nth-child(2n)
nth-last-childsame as above, except working backwards
not:not(input)
and a whole bunch of others...
#Box1#Box1
Meet Mr. Box.
#Box1
#Box1
Feelin’ Tipsy, Mr. Box?
#Box1 { transform: rotate(45deg);}
#Box1#Box1
Feelin’ Out of Place, Mr. Box?
#Box1 { transform: translate(10px, 10px);}
#Box1#Box1
#Box1#Box1
Feelin’ (Vertically) Out of Place, Mr. Box?
#Box1 { transform: translateY(10px);}
#Box1#Box1
#Box1#Box1
Feelin’ (Horizontally) Out of Place, Mr. Box?
#Box1 { transform: translateX(10px);}
#Box1#Box1
Feelin’ a little bloated, Mr. Box?
#Box1 { transform: scale(2);}
#Box1#Box1
Feelin’ weak, Mr. Box?
#Box1 { transform: scale(0.5);}
#Box#Box11
#Box1#Box1
How’s the weather up there, Mr. Box?
#Box1 { transform: scaleY(2);}
Ate too much, Mr. Box?
#Box1 { transform: scaleX(2);}
#Box1#Box1
View (a)skew , Mr. Box?
#Box1 { transform: skew(-30deg, 30deg);}
iPhone-only at this point.(though, possibly BlackBerry 6 as well)
Transform in Z-space using Z properties.
scaleZrotateZ
rotate3DtranslateZ
CSS animations are smoother, faster, and require far less code.
And just for kicks, we’ll throw in some hardware acceleration
too.
transition: 1s;
Whenever a property for the transition-ready element changes, the browser
auto-tweens the element for you!
#container { transition: 1s;}
#container:hover { opacity: 0.4}
Transition Properties
Which properties should be animated?transition-property: color;
default: all
How long should the transition take?transition-duration: 1s;
default: 0, which means no animation. Required!
Should we wait a bit before starting?transition-delay: 0.5s;
default: 0Can be negative. Will start as if pre-animated.
Transition Properties (cont’d)
Which timing curve should we use?transition-timing-function: ease-out;
default: ease
Other values:
linearease-in
ease-outease-in-out
cubic-bezier (custom-defined)
CO
DE
Feeling lazy? Shorthand it.
p { transition: color 1s ease-in 2s;}
Might change to:
p { transition: color 1s/2s ease-in;}
Want to make everything transition-ready?
(though, probably a bad idea)
* { transition: 1s;}
Whenever possible, use classes instead of direct CSS
manipulation.Generally yields better performance.
What about complex animations?
Combine multiple transitions!
Define tween checkpoints and the properties to be changed at each.
#box1.animated { animation-name: goCrazy }
@keyframes goCrazy { 0% { } 33% { left: 200px; } 66% { -webkit-transform: rotate(-90deg); } 100% { -webkit-transform: scale(2); opacity: 0; }}
Animation Properties
Same as beforeanimation-duration: 1s;animation-delay: 0.5s;
animation-timing-function: ease-out;
Which direction should animations run?animation-direction: alternate;
default: normal;
Which direction should animations run?animation-iteration-count: 4;
default: 1;Use infinite for a never-ending loop.
’
#Box2#Box2#Box1#Box1
Remember Mr. Box?Say Hello to Mrs. Box.
#Box2#Box2#Box1#Box1
Let’s get animating!
#Box2#Box2#Box1#Box1
Flip horizontally
transform: rotateY(180deg);
#Box2#Box2#Box1#Box1
Re-position and wrap
position: absolute;
#Container#Container
position: relative;
#Container#Container
Box 2Box 2#Box1#Box1
Enable 3D animation
#container { transform-style: preserve-3d; transition: transform 1s;}
#Container#Container
Box 2Box 2#Box1#Box1
#Container#Container
#Box1#Box1
Get flippy
#container:hover { transform: rotateY(180deg);}
#Box2#Box2
#Container#Container
Box 2Box 2#Box1#Box1
#container.flipped { transform: rotateY(180deg);}
<div id=”container” onclick=”this.className = ‘flipped’”>...</div>
Because :hover and mobile don’t always get along...
http://www.paulrhayes.com/experiments/cube-3d/index.html
A blank slate with which you can do (almost) anything:
- create elements, shapes, lines, images, 3D things, text.- modify them- animate them- etc.
CO
DE
if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(success, error);
} else {alert('Your device doesn\'t support HTML5 geolocation');
}
CO
DE
function success( position ) {alert( 'Latitude: ' + position.coords.latitude );alert( 'Longitude: ' + position.coords.longitude );// position exposes other properties as well:// timestamp, accuracy, heading, altitude, etc.
}
CO
DE
function error( error ) {alert( 'Sorry, we could\’nt figure out your location!' );console.error( 'Error', error.code, error.message );// error codes:// 1: location permission denied// 2: location fetch failed// 3: timeout// 0: unknown
}
Not quite stalker-ish enough for you?
CO
DE
if(navigator.geolocation) {watch = navigator.geolocation.watchPosition( success );// Callback triggered whenever position changes// Success callback could add a point to a map// Or refresh a list of nearby locations// Etc.
}
// Stop stalkingclearWatch(watch);
Always provide a fallback!
IP location can suck.
GPSes are awesome, but satellites can have bad days.
Have an [edit location] button AND manual entry
Let’s Map It
CO
DE
<div id="map"> </div> <script src="http://maps.google.com/maps/api/js?sensor=false"></script> <script> function initMap(id) { var mapOptions = {
center: new google.maps.LatLng(0, 0), zoom: 15, mapTypeId: google.maps.MapTypeId.ROADMAP };
return new google.maps.Map(document.getElementById(id), mapOptions); }
var map = initMap('map');
</script>
Initialize the map
CO
DE
Add User’s Location to the map
<script> function mapPosition(map, lat, lng) { var position = new google.maps.LatLng(lat, lng);
markerOptions = { position: position, map: map }; var marker = new google.maps.Marker(markerOptions); map.setCenter(position); return marker;
}
if(navigator.geolocation) {navigator.geolocation.getCurrentPosition(
function( position ) { mapPosition(map, position.coords.latitude,position.coords.longitude); }, function( error ) { alert(error.message); } );
}
</script>
Let’s Geocode It.
CO
DE
http://maps.google.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=false
Server-side (need proxy)
CO
DE
Client-side
new google.maps.Geocoder();geocoder.geocode( {
'latLng': new google.maps.LatLng(lat, lng)},function(results, status) {
for( var i = 0; i < data.results.length; i++ ) {var result = results[i];if(result.types[0] == 'locality' && result.types[1] == 'political') {
alert('Your city: ' + result.formatted_address);}
}}
);
Connect with any of the 3 trillion Location-based APIs out there.
Cache for storing HTML,
CSS, JS required for offline usage.
Cache for storing data.
3 flavours:
sessionStoragelocalStorage
Web SQL
(and a few other types being cooked up for the
future...)
Pre-loading of content improves speed and prevents repeated roundtrips to server.
Cache heavy or unique data loads that are unlikely to change, e.g. location information,
favourites, etc.
CO
DE
<!DOCTYPE HTML><html manifest="offline-manifest">
CACHE MANIFESTindex.htmlhelp.htmlstyle/main.cssimages/logo.pngimages/cupcakes.png
Specify the manifest file
offline-manifest file
sessionStorage.haveMessage = true;
localStorage.messages = [ ‘Hello World’ , ‘Goodbye World’]
Window 1
Window 2
sessionStorage.haveMessage=> truelocalStorage.messages=> [ ‘Hello World’, ‘Goodbye World’ ]
Window 1
Window 2
sessionStorage.haveMessage=> nulllocalStorage.messages=> [ ‘Hello World’, ‘Goodbye World’ ]
Full-fledged SQLLite database in the browser!
CO
DE
// Basic API methods
db = openDatabase( name, version );
db.transaction( callback );
transaction.executeSql( sql, values, success, error );
CO
DE
// Create database connection// @params: name, version, display name, size in bytes var db = openDatabase('bakery', '1.0', 'My Bakery', 1048576);
CO
DE
// Create tabledb.transaction(function(trans) { trans.executeSql('CREATE TABLE IF NOT EXISTS Cupcakes (name TEXT, description TEXT)', []);});
CO
DE
// Add entriesdb.transaction(function(trans) {
trans.executeSql('INSERT INTO Cupcakes VALUES (?, ?)', ['Vanilla', 'Good ol vanilla!']); trans.executeSql('INSERT INTO Cupcakes VALUES (?, ?)', ['Chocolate', 'Good ol chocolate!']);});
CO
DE
// Select entriesdb.transaction(function(trans) {
trans.executeSql(‘SELECT * FROM Cupcakes’, [], function(trans, results) {for(var i = 0; i < results.rows.length; i++) {
var cupcake = results.rows.item(i);document.getElement('cupcakes').innerHTML += '<li>' + cupcake.name + ':</strong> ' + cucpake.description + '</li>';
} alert('We\'ve got ' + results.rows.length + ' cupcake(s)');
});});
sessionStorage: CupcakelocalStorage: Slice of cake
Web SQL: Multi-tiered wedding cake
(Though, the last two can vary depending on your views on SQL / noSQL)
Gmail Web SQL databaseRecent messages are pre-fetched. Certain data (labels)
is pre-fetched. Requires force refresh for update.
YouTube localStorageCaches AJAX requests, search history, user actions, etc.
window.onhashchange / pushState
Build true event-driven, dyanmic sites with solid back button support and fragement
urls.
data-attributes
Store data as attributes within DOM Elements.
CO
DE
<a data-flavour=”chocolate”>Cupcake!</a>
(Accessed via element.dataset.flavour => chocolate)
Get User Location(geolocation)
Store Favourite Cities(localStorage)
Pre-fetch long-term forecast(Web SQL)
Weather Trends Graphs(Canvas)
Eye Candy(CSS3 transitions /
animations)
Video Weather Report(<video>)
Because only nerds build everything from
scratch.
iUI
jQTouch
SenchaTouch
SproutCore
jQuery Mobile
processing.js
raphael.jsgeolocation (with fallbacks)
jQuery.animate + CSS3 Animationspersistence.js (with fallback to Gears)
’Hardware access?
Notifications?Mind control?
Mohammad JangdaVortex Mobile
batmoo@gmail.commohammad.jangda@vortexmobile.ca
http://digitalize.ca@mjangda
Recommended