progressive enhancement with javascript
DESCRIPTION
We’ve all heard the rallying cry for writing “unobtrusive” JavaScript, but that only gets you so far. To truly meet users’ needs, no matter what their device or platform, you’ll have to apply the principles of “progressive enhancement” to your client-side scripting. This session will help you get into the PE mindset and walk you through concrete examples that demonstrate PE in action.TRANSCRIPT
Aaron Gustafson
AN EVENT APART - 25 APRIL 2008
Progressive Enhancement with JavaScript
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
What isProgressive
Enhancement?
2
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
ProgressiveEnhancement
vs.Graceful
Degradation
3
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Graceful Degradation! A holdover from engineering
! Build for the latest browsers
! Test on older devices
! Happens at the end
! Accounts for few versions
! Expects a poor experience for older browsers
! Fixes major issues but little else
4
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 5
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 5
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Progressive Enhancementfocuses on contentcontent
6
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Content is why we build websites
and should beour central focus
7
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
How does it work?
8
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 9
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 10
Flavorful nugget of content(semantic goodness)
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 11
Rich, indulgent design
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 12
Sweet interactivity(keeps it from melting in your hands)
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 13
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Technologies applied as layers
14
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 15
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 16
(Mr. Clarke’s web standards trifle)
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 17
Why a peanut m&m?
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
The peanut is good for
18
! diabetics
! search engine spiders
! mobile devices
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 19
It’s a basic levelof support
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 20
! some browsers only handle a certain level of CSS
! some companies turn o" JavaScript
Rich, chocolaty goodness
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 21
It can be beautiful(and progressive)
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
The candy coating
22
! JavaScript can turn a website into an experience
! we can deliver our scripts a la carte
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 23
How do we do it?
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Restraint& Planning
24
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Wieldyour power
wisely
25
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Dear George Lucas, please don’t sue me. Kthxbye.
A long time ago, in acubicle far, far away...
26
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
DHTML
27
(was awful)
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Spaghetti code
28
(our HTML was spaghetti too)
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Things are better now,but we have new challenges
29
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
What canJavaScript do?
30
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
How shouldJavaScriptbe used?
31
JavaScript
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Progressive Enhancementhelps us by reminding usto focus on the content
32
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Back to basics
33
XHTML + HTTP
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Back to basics
33
solid foundation
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
All code neededto understandand use a site
should exist beforeany scripts run
PE Maxim:
34
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Period.
PE Maxim:
34
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Consider lala.com
35
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Without JavaScript
36
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Without JavaScript
36
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Without JavaScript
36
Doh!
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
And looking at the markup...
37
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
And looking at the markup...
37
Ugh!
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
What about search?
38
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
What aboutalternative devices?
39
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
EnterUnobtrusiveJavaScript
40
the cornerstone of ProgressiveEnhancement with JavaScript( )
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Don’t do this
41
<a href="javascript:someFunction();">some text</a>
or
<a href="javascript:void(null);" onclick="someFunction();">some text</a>
or
<a href="#" onclick="someFunction();">some text</a>
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
An improvement, but still...
42
<a href="http://offsite.com" onclick="newWin( this.href ); return false;"> some text</a>
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
window.onload = handleExternalLinks;
function handleExternalLinks(){
var server = document.location.hostname; var anchors = document.getElementsByTagName("a"); var i, href; for( i=0; i < anchors.length; i++ ){ href = anchors[i].href;
if( href.indexOf("http://" + server) == -1 && href.indexOf("https://" + server) == -1 ){ // HREF is not a file on my server anchors[i].onclick = function(){ newWin( this.href );
}; } }}
Getting warmer...
43
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
document.getElementsByTagName( 'body' )[0].onclick = clickDelegator;
function clickDelegator( e ){ e = ( e ) ? e : event; var el = e.target || e.srcElement;
// external links
if( el.nodeName.toLowerCase() == 'a' && el.getAttribute( 'rel' ) == 'external' ){ newWin( el.href ); }}
You’re hot
44
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Keep the hot side hotand the cold side cold
45
or getting some separationbetween your CSS and JS( )
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Remember stu" like this?
46
<a href="foo.html" style="color:blue;" onmouseover="this.style.color='red'"
onmouseout="this.style.color='blue'">Foo</a>
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Remember stu" like this?
46
<a href="foo.html" style="color:blue;" onmouseover="this.style.color='red'"
onmouseout="this.style.color='blue'">Foo</a>
Obvisouly, we should be doing this instead:
a, a:link, a:visited { color: blue;}
a:hover { color: red;}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
CSS waspoorly understood
back then
47
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 47
but we knowbetter now
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 47
don’t we?
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Hmm...
48
for( i=0; i<objects.length; i++){ objects[i].style.display = 'none';}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Better
49
for( i=0; i<objects.length; i++){ objects[i].style.position = 'absolute'; objects[i].style.left = '-999em';
}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Separation
50
CSS:
.hidden { position: absolute; left: -999em;}
JavaScript:
for( i=0; i<objects.length; i++){ objects[i].addClassName( 'hidden' );
}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Maintenance options
51
! external style rules added to master CSS file by hand
! external CSS file added to the document by hand
! external CSS file added to the document via script
! embedding CSS in the document via script
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
But keep in mind
52
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 52
you need toavoid applying
script-related styles
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 52
until you knowyour script can run
and it hasinitialized properly
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
How do we do that?
53
! make your style rules specific:
.TabInterface-folder {
...
}
or
#TabInterface .tab {
...
}
#TabInterface .tab.active {
...
}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
How do we do that?
54
! turn “on” script-related rules at run-time:
<div id="main" class="tabbed">
becomes
<div id="main" class="tabbed-on">
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
How do we do that?
54
! turn “on” script-related rules at run-time:
Default Activated
add “-on” to the class .tabbed .tabbed-on
add an activation class .auto-submit .auto-submit.active
change the form of the class .replace-me .replaced
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Become a detective
55
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Look for methods
56
function someFunction(){ if( !document.getElementsByTagName ) return; // code that uses document.getElementsByTagName()
...}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Look for methods
57
function someFunction(){ if( !document.getElementsByTagName || !document.getElementById ) return;
/* code that uses document.getElementsByTagName() and document.getElementById() */}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Look for elements
58
function someFunction(){ if( !document.getElementsByTagName || !document.getElementsByTagName( 'p' ) ) return;
/* code that uses document.getElementsByTagName() and requires the presence of a P element */ ...}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Look for identified elements
59
function someFunction(){ if( !document.getElementById || !document.getElementById( 'content' ) ) return;
// code that requires the presence of #content ...}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Look for objects
60
function someFunction(){ if( typeof( Prototype ) == 'undefined' ) return; // code that uses Prototype
...}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Look for object versions
61
function someFunction(){ if( typeof( Prototype ) == 'undefined' || parseFloat( Prototype.Version ) < 1.5 ) return;
// code that uses Prototype 1.5 or higher ...}
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Look before you leap
62
window.onload = function(){ if( document.getElementsByTagName && document.getElementById ){
someFunction(); }};
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008
Be progressive
63
! Start with the content, then work your way out
! Get unobtrusive
! Keep some distance between your styles & your scripts
! Put on your detective hat
PROGRESSIVE ENHANCEMENT WITH JAVASCRIPT
AN EVENT APART - 25 APRIL 2008 64
Questions?