SlideShare a Scribd company logo
1 of 263
FUNDAMENTAL
 JAVASCRIPT
   Aaron Gustafson
DOM SCRIPTING
(a.k.a. Document Manipulation via JavaScript)
FUNDAMENTAL JAVASCRIPT




    DHTML
๏   …was all about animation and interactivity
๏   ...was invented by marketing wonks
๏   ...is really three technologies: JavaScript, CSS & HTML
๏   ...carried a lot of baggage: browser-specific, forked code,
    screen only & non-standard markup
๏   ...was a maintenance nightmare




    IN CONTROL 2009                                              3
FUNDAMENTAL JAVASCRIPT




    DOM Scripting
๏   …is the web standards approach to manipulating documents
๏   ...only requires a scripting language and valid markup
๏   ...is browser independent
๏   ...makes use of progressive enhancement
๏   ...just makes sense




    IN CONTROL 2009                                            4
FUNDAMENTAL JAVASCRIPT




The document
<!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Strict//ENquot;
 quot;http://www.w3.org/TR/XHTML1/DTD/XHTML1-strict.dtdquot;>
<html xmlns=quot;http://www.w3.org/1999/XHTMLquot; xml:lang=quot;enquot; lang=quot;enquot;>
<head>
  <title>Page Title</title>
  <meta http-equiv=quot;content-typequot; content=quot;text/html; charset=utf-8quot; />
  <meta http-equiv=quot;Content-Languagequot; content=quot;en-usquot; />
</head>
<body>
  <h1>This is a heading</h1>
  <p>This is a paragraph with a <a href=quot;http://easy-reader.netquot;>link</a></p>
  <ul>
    <li>a list item</li>
    <li>another list item</li>
    <li>a third list item</li>
  </ul>
</body>
</html>




IN CONTROL 2009                                                                 5
FUNDAMENTAL JAVASCRIPT




The DOM
                         html




IN CONTROL 2009                 6
FUNDAMENTAL JAVASCRIPT




The DOM
                                        html




                         head                  body




              title      meta   meta   h1       p     ul




                                                a     li   li   li




IN CONTROL 2009                                                      6
FUNDAMENTAL JAVASCRIPT




The DOM
                                                p




                          this is a paragraph   a   .
                          of text with a




                   href=quot;http://easy-reader.netquot;    link




IN CONTROL 2009                                            6
FUNDAMENTAL JAVASCRIPT




CSS



                    getter { setter }




IN CONTROL 2009                         7
FUNDAMENTAL JAVASCRIPT




CSS



                    p { color: red; }




IN CONTROL 2009                         7
FUNDAMENTAL JAVASCRIPT




CSS


           #footer {
             font-size: small;
           }



IN CONTROL 2009                  7
FUNDAMENTAL JAVASCRIPT




DOM Scripting




IN CONTROL 2009          8
FUNDAMENTAL JAVASCRIPT




DOM Scripting


         var myNode =
           document.getter();



IN CONTROL 2009                 8
FUNDAMENTAL JAVASCRIPT




DOM Scripting



                         myNode.setter();




IN CONTROL 2009                             8
FUNDAMENTAL JAVASCRIPT




    Getters
๏   document.getElementById( ID );

๏   document.getElementsByTagName( tagName );

๏   element.getAttribute( attributeName );




    IN CONTROL 2009                             9
FUNDAMENTAL JAVASCRIPT




    Using getters
๏   var content = document.getElementById( 'content' );

๏   var abbrs = document.getElementsByTagName( 'abbr' );

๏   var title = abbrs[0].getAttribute( 'title' );




    IN CONTROL 2009                                        10
FUNDAMENTAL JAVASCRIPT




    Language comparison
๏   English
    Get the element with the ID “content”.
๏   CSS
    #content { }

๏   DOM
    document.getElementById( 'content' )




    IN CONTROL 2009                          11
FUNDAMENTAL JAVASCRIPT




    Language comparison
๏   English
    Get all the paragraphs in a document.
๏   CSS
    p { }

๏   DOM
    document.getElementsByTagName( 'p' );




    IN CONTROL 2009                         12
FUNDAMENTAL JAVASCRIPT




    Language comparison
๏   English
    Get all the paragraphs within the element with the ID
    “content”.
๏   CSS
    #content p { }

๏   DOM
    document.getElementById( 'content' )
            .getElementsByTagName( 'p' );




    IN CONTROL 2009                                         13
FUNDAMENTAL JAVASCRIPT




    Content generation
๏   Bad:
    ‣ document.write();

    ‣ innerHTML




    IN CONTROL 2009          14
FUNDAMENTAL JAVASCRIPT




    Content generation
๏   Good:
    ‣ document.createElement( tagName );

    ‣ document.createTextNode( text );

    ‣ element.setAttribute( name, value );




    IN CONTROL 2009                          15
FUNDAMENTAL JAVASCRIPT




    Generation in action
๏   var abbr = document.createElement( 'abbr' );

๏   var text = document.createTextNode( 'TN' );

๏   abbr.setAttribute( 'title', 'Tennessee' );




    IN CONTROL 2009                                16
FUNDAMENTAL JAVASCRIPT




    Adding to the DOM
๏   element.appendChild( newNode );
๏   element.insertBefore( newNode, targetNode );




    IN CONTROL 2009                                17
FUNDAMENTAL JAVASCRIPT




Adding to the DOM
var abbr = document.createElement( 'abbr' );

var text = document.createTextNode( 'TN' );

abbr.setAttribute( 'title', 'Tennessee' );

abbr.appendChild( text );

var p = document.getElementsByTagName( 'p' )[0];

p.appendChild( abbr );




IN CONTROL 2009                                    18
TIME FOR AN
  EXAMPLE
FUNDAMENTAL JAVASCRIPT




The idea
Make use of the cite attribute in blockquotes.




IN CONTROL 2009                                  20
FUNDAMENTAL JAVASCRIPT




The document
<!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Strict//ENquot;
 quot;http://www.w3.org/TR/XHTML1/DTD/XHTML1-strict.dtdquot;>
<html xmlns=quot;http://www.w3.org/1999/XHTMLquot; xml:lang=quot;enquot; lang=quot;enquot;>
<head>
  <title>Example 1</title>
  <meta http-equiv=quot;content-typequot; content=quot;text/html; charset=utf-8quot; />
  <meta http-equiv=quot;Content-Languagequot; content=quot;en-usquot; />
</head>
<body>
  <blockquote cite=quot;http://en.wikipedia.org/wiki/Progressive_Enhancementquot;>
    <p>Progressive Enhancement, as a label for a strategy for Web design,
    was coined by Steven Champeon in a series of articles and presentations
    for Webmonkey and the SxSW Interactive conference.</p>
  </blockquote>
</body>
</html>




IN CONTROL 2009                                                               21
FUNDAMENTAL JAVASCRIPT




The page

                  Progressive Enhancement, as a label for a
                  strategy for Web design, was coined by
                  Steven Champeon in a series of articles
                  and presentations for Webmonkey and
                  the SxSW Interactive conference.




IN CONTROL 2009                                               22
FUNDAMENTAL JAVASCRIPT




The document
<!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Strict//ENquot;
 quot;http://www.w3.org/TR/XHTML1/DTD/XHTML1-strict.dtdquot;>
<html xmlns=quot;http://www.w3.org/1999/XHTMLquot; xml:lang=quot;enquot; lang=quot;enquot;>
<head>
  <title>Example 1</title>
  <meta http-equiv=quot;content-typequot; content=quot;text/html; charset=utf-8quot; />
  <meta http-equiv=quot;Content-Languagequot; content=quot;en-usquot; />
</head>
<body>
  <blockquote cite=quot;http://en.wikipedia.org/wiki/Progressive_Enhancementquot;>
    <p>Progressive Enhancement, as a label for a strategy for Web design,
    was coined by Steven Champeon in a series of articles and presentations
    for Webmonkey and the SxSW Interactive conference.</p>
  </blockquote>
</body>
</html>




IN CONTROL 2009                                                               23
FUNDAMENTAL JAVASCRIPT




The idea
1. Find all the blockquotes in a document

2. Get the value of the cite attribute

3. Create a new anchor element node

4. Set the href attribute of the anchor

5. Create a new text node with the word “source”

6. Insert the text into the anchor

7. Insert the anchor into the blockquote.




IN CONTROL 2009                                    24
FUNDAMENTAL JAVASCRIPT




The idea
1. Find all the blockquotes in a document

2. Get the value of the cite attribute

3. Create a new anchor element node

4. Set the href attribute of the anchor

5. Create a new text node with the word “source”

6. Insert the text into the anchor

7. Insert the anchor into the blockquote.




IN CONTROL 2009                                    25
FUNDAMENTAL JAVASCRIPT




The idea
1. Find all the blockquotes in a document getElementsByTagName

2. Get the value of the cite attribute

3. Create a new anchor element node

4. Set the href attribute of the anchor

5. Create a new text node with the word “source”

6. Insert the text into the anchor

7. Insert the anchor into the blockquote.




IN CONTROL 2009                                             25
FUNDAMENTAL JAVASCRIPT




The idea
1. Find all the blockquotes in a document getElementsByTagName

2. Get the value of the cite attribute             getAttribute

3. Create a new anchor element node

4. Set the href attribute of the anchor

5. Create a new text node with the word “source”

6. Insert the text into the anchor

7. Insert the anchor into the blockquote.




IN CONTROL 2009                                               25
FUNDAMENTAL JAVASCRIPT




The idea
1. Find all the blockquotes in a document getElementsByTagName

2. Get the value of the cite attribute              getAttribute

3. Create a new anchor element node                createElement

4. Set the href attribute of the anchor

5. Create a new text node with the word “source”

6. Insert the text into the anchor

7. Insert the anchor into the blockquote.




IN CONTROL 2009                                                25
FUNDAMENTAL JAVASCRIPT




The idea
1. Find all the blockquotes in a document getElementsByTagName

2. Get the value of the cite attribute              getAttribute

3. Create a new anchor element node                createElement

4. Set the href attribute of the anchor             setAttribute

5. Create a new text node with the word “source”

6. Insert the text into the anchor

7. Insert the anchor into the blockquote.




IN CONTROL 2009                                                25
FUNDAMENTAL JAVASCRIPT




The idea
1. Find all the blockquotes in a document getElementsByTagName

2. Get the value of the cite attribute               getAttribute

3. Create a new anchor element node                 createElement

4. Set the href attribute of the anchor              setAttribute

5. Create a new text node with the word “source”   createTextNode

6. Insert the text into the anchor

7. Insert the anchor into the blockquote.




IN CONTROL 2009                                                 25
FUNDAMENTAL JAVASCRIPT




The idea
1. Find all the blockquotes in a document getElementsByTagName

2. Get the value of the cite attribute               getAttribute

3. Create a new anchor element node                 createElement

4. Set the href attribute of the anchor              setAttribute

5. Create a new text node with the word “source”   createTextNode

6. Insert the text into the anchor                    appendChild

7. Insert the anchor into the blockquote.




IN CONTROL 2009                                                 25
FUNDAMENTAL JAVASCRIPT




The idea
1. Find all the blockquotes in a document getElementsByTagName

2. Get the value of the cite attribute               getAttribute

3. Create a new anchor element node                 createElement

4. Set the href attribute of the anchor              setAttribute

5. Create a new text node with the word “source”   createTextNode

6. Insert the text into the anchor                    appendChild

7. Insert the anchor into the blockquote.             appendChild




IN CONTROL 2009                                                 25
FUNDAMENTAL JAVASCRIPT




The code
var quotes = document.getElementsByTagName( 'blockquote' );
for( var i=0; i < quotes.length; i++ ){
  var source = quotes[i].getAttribute( 'cite' );
  if( source ){
    var link = document.createElement( 'a' );
    link.setAttribute( 'href', source );
    var text = document.createTextNode( 'source' );
    link.appendChild( text );
    quotes[i].appendChild( link );
  }
}




IN CONTROL 2009                                               26
FUNDAMENTAL JAVASCRIPT




The code
var quotes = document.getElementsByTagName( 'blockquote' );
for( var i=0; i < quotes.length; i++ ){
  var source = quotes[i].getAttribute( 'cite' );
  if( source ){
    var link = document.createElement( 'a' );
    link.setAttribute( 'href', source );
    var text = document.createTextNode( 'source' );
    link.appendChild( text );
    var para = document.createElement( 'p' );
    para.className = 'attribution';
    para.appendChild( link );
    quotes[i].appendChild( para );
  }
}




IN CONTROL 2009                                               27
FUNDAMENTAL JAVASCRIPT




The code
function sourceQuotes(){
  var quotes = document.getElementsByTagName( 'blockquote' );
  for( var i=0; i < quotes.length; i++ ){
    var source = quotes[i].getAttribute( 'cite' );
    if( source ){
      var link = document.createElement( 'a' );
      link.setAttribute( 'href', source );
      var text = document.createTextNode( 'source' );
      link.appendChild( text );
      var para = document.createElement( 'p' );
      para.className = 'attribution';
      para.appendChild( link );
      quotes[i].appendChild( para );
    }
  }
}
window.onload = sourceQuotes;

IN CONTROL 2009                                                 28
FUNDAMENTAL JAVASCRIPT




The result

                  Progressive Enhancement, as a label for a
                  strategy for Web design, was coined by
                  Steven Champeon in a series of articles
                  and presentations for Webmonkey and
                  the SxSW Interactive conference.




IN CONTROL 2009                                               29
FUNDAMENTAL JAVASCRIPT




The result

                  Progressive Enhancement, as a label for a
                  strategy for Web design, was coined by
                  Steven Champeon in a series of articles
                  and presentations for Webmonkey and
                  the SxSW Interactive conference.
                                                      source




IN CONTROL 2009                                                30
PROGRESSIVE
ENHANCEMENT
WHAT IS
 PROGRESSIVE
ENHANCEMENT?
PROGRESSIVE
ENHANCEMENT
     VS.
  GRACEFUL
DEGRADATION
GRACEFUL
DEGRADATION
FUNDAMENTAL JAVASCRIPT




    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




    IN CONTROL 2009                                          34
WEB STANDARDS: FUELING INNOVATION




WEB BUILDER 2.0                     35
WEB STANDARDS: FUELING INNOVATION




WEB BUILDER 2.0                     35
PROGRESSIVE
ENHANCEMENT
 FOCUSES ON
  CONTENT
PROGRESSIVE
ENHANCEMENT
 FOCUSES ON
  CONTENT
CONTENT IS WHY
WE BUILD WEBSITES
  AND SHOULD
     BE OUR
 CENTRAL FOCUS
WEB STANDARDS: FUELING INNOVATION




WEB BUILDER 2.0                     38
WEB STANDARDS: FUELING INNOVATION




WEB BUILDER 2.0                     39
HOW DOES IT
  WORK?
WEB STANDARDS: FUELING INNOVATION




WEB BUILDER 2.0                     41
FUNDAMENTAL JAVASCRIPT




Flavorful nugget of content
(semantic goodness)




IN CONTROL 2009               42
FUNDAMENTAL JAVASCRIPT




Rich, indulgent design




IN CONTROL 2009          43
FUNDAMENTAL JAVASCRIPT




Sweet interactivity
(keeps it from melting in your hands)




IN CONTROL 2009                         44
WEB STANDARDS: FUELING INNOVATION




WEB BUILDER 2.0                     45
TECHNOLOGIES
APPLIED AS LAYERS
WEB STANDARDS: FUELING INNOVATION




WEB BUILDER 2.0                     47
WEB STANDARDS: FUELING INNOVATION




                                    stuffandnonsense.co.uk/archives/web_standards_trifle.html

WEB BUILDER 2.0                                                                            48
WHY A PEANUT
   M&M?
FUNDAMENTAL JAVASCRIPT




    The peanut is good for
๏   diabetics




    IN CONTROL 2009          50
FUNDAMENTAL JAVASCRIPT




    The peanut is good for
๏   diabetics
๏   search engine spiders




    IN CONTROL 2009          50
FUNDAMENTAL JAVASCRIPT




    The peanut is good for
๏   diabetics
๏   search engine spiders
๏   mobile devices




    IN CONTROL 2009          50
IT’S A BASIC LEVEL
   OF SUPPORT
FUNDAMENTAL JAVASCRIPT




The chocolate is good for




IN CONTROL 2009             52
FUNDAMENTAL JAVASCRIPT




    The chocolate is good for
๏   diabetics




    IN CONTROL 2009             52
FUNDAMENTAL JAVASCRIPT




    Rich, chocolaty goodness
๏   some browsers only handle
    a certain level of CSS
๏   some companies turn off
    JavaScript




    IN CONTROL 2009             52
IT CAN BE
BEAUTIFUL
 (and progressive)
FUNDAMENTAL JAVASCRIPT




The candy coating




IN CONTROL 2009          54
FUNDAMENTAL JAVASCRIPT




    The candy coating
๏   JavaScript can turn a website
    into an experience




    IN CONTROL 2009                 54
FUNDAMENTAL JAVASCRIPT




    The candy coating
๏   JavaScript can turn a website
    into an experience
๏   we can deliver our scripts
    a la carte




    IN CONTROL 2009                 54
PROGRESSIVE
 ENHANCEMENT
WITH JAVASCRIPT
RESTRAINT
& PLANNING
FUNDAMENTAL JAVASCRIPT




A long time ago, in a
cubicle far, far away...




                         Dear George Lucas, please don’t sue me. Kthxbye.




IN CONTROL 2009                                                             57
FUNDAMENTAL JAVASCRIPT




A long time ago, in a
cubicle far, far away...




                         Dear George Lucas, please don’t sue me. Kthxbye.




IN CONTROL 2009                                                             57
WHAT CAN
JAVASCRIPT DO?
HOW SHOULD
 JAVASCRIPT
   BE USED?
PROGRESSIVE
ENHANCEMENT
  REMINDS US
 TO FOCUS ON
THE CONTENT
FUNDAMENTAL JAVASCRIPT




Back to basics




IN CONTROL 2009          60
FUNDAMENTAL JAVASCRIPT




Back to basics



         XHTML + HTTP


IN CONTROL 2009          60
FUNDAMENTAL JAVASCRIPT




Back to basics



         solid foundation


IN CONTROL 2009             60
FUNDAMENTAL JAVASCRIPT




         ALL CODE NEEDED
         TO UNDERSTAND
          AND USE A SITE
       SHOULD EXIST BEFORE
         ANY SCRIPTS RUN

IN CONTROL 2009              61
FUNDAMENTAL JAVASCRIPT




                         PERIOD.

IN CONTROL 2009                    61
FUNDAMENTAL JAVASCRIPT




Consider lala.com




IN CONTROL 2009          62
FUNDAMENTAL JAVASCRIPT




Without JavaScript




IN CONTROL 2009          63
FUNDAMENTAL JAVASCRIPT




Without JavaScript




IN CONTROL 2009          63
FUNDAMENTAL JAVASCRIPT




Without JavaScript



                         Doh!

IN CONTROL 2009                 63
FUNDAMENTAL JAVASCRIPT




And looking at the




IN CONTROL 2009          64
FUNDAMENTAL JAVASCRIPT




And looking at the




                         Ug h !

IN CONTROL 2009                   64
WHAT ABOUT
 SEARCH?
WHAT ABOUT
ALTERNATIVE
  DEVICES?
ENTER
UNOBTRUSIVE
 JAVASCRIPT
ENTER
UNOBTRUSIVE
 JAVASCRIPT
(           )
 the cornerstone of Progressive
  Enhancement with JavaScript
FUNDAMENTAL JAVASCRIPT




Don’t do this
<a href=quot;javascript:someFunction();quot;>some text</a>


                             or

<a href=quot;javascript:void(null);quot;
   onclick=quot;someFunction();quot;>some text</a>


                             or

<a href=quot;#quot; onclick=quot;someFunction();quot;>some text</a>




IN CONTROL 2009                                       67
FUNDAMENTAL JAVASCRIPT




An improvement, but still...
<a href=quot;http://offsite.comquot;
   onclick=quot;newWin( this.href ); return false;quot;>
   some text</a>




IN CONTROL 2009                                    68
FUNDAMENTAL JAVASCRIPT




Getting warmer...
window.onload = handleExternalLinks;

function handleExternalLinks(){
  var server = document.location.hostname;
  var anchors = document.getElementsByTagName(quot;aquot;);
  var i, href;
  for( i=0; i < anchors.length; i++ ){
    href = anchors[i].href;
    if( href.indexOf(quot;http://quot; + server) == -1 &&
         href.indexOf(quot;https://quot; + server) == -1 ){
      // HREF is not a file on my server
      anchors[i].onclick = function(){
         newWin( this.href );
      };
    }
  }
}


IN CONTROL 2009                                       69
FUNDAMENTAL JAVASCRIPT




Getting warmer...
window.onload = handleExternalLinks;

function handleExternalLinks(){
  var server = document.location.hostname;
  var anchors = document.getElementsByTagName(quot;aquot;);
  var i, href;
  for( i=0; i < anchors.length; i++ ){
    href = anchors[i].href;
    if( href.indexOf(quot;http://quot; + server) == -1 &&
         href.indexOf(quot;https://quot; + server) == -1 ){
      // HREF is not a file on my server
      anchors[i].onclick = function(){
         newWin( this.href );
      };
    }
  }
}


IN CONTROL 2009                                       69
FUNDAMENTAL JAVASCRIPT




Getting warmer...
window.onload = handleExternalLinks;

function handleExternalLinks(){
  var server = document.location.hostname;
  var anchors = document.getElementsByTagName(quot;aquot;);
  var i, href;
  for( i=0; i < anchors.length; i++ ){
    href = anchors[i].href;
    if( href.indexOf(quot;http://quot; + server) == -1 &&
         href.indexOf(quot;https://quot; + server) == -1 ){
      // HREF is not a file on my server
      anchors[i].onclick = function(){
         newWin( this.href );
      };
    }
  }
}


IN CONTROL 2009                                       69
FUNDAMENTAL JAVASCRIPT




Getting warmer...
window.onload = handleExternalLinks;

function handleExternalLinks(){
  var server = document.location.hostname;
  var anchors = document.getElementsByTagName(quot;aquot;);
  var i, href;
  for( i=0; i < anchors.length; i++ ){
    href = anchors[i].href;
    if( href.indexOf(quot;http://quot; + server) == -1 &&
         href.indexOf(quot;https://quot; + server) == -1 ){
      // HREF is not a file on my server
      anchors[i].onclick = function(){
         newWin( this.href );
      };
    }
  }
}


IN CONTROL 2009                                       69
FUNDAMENTAL JAVASCRIPT




Getting warmer...
window.onload = handleExternalLinks;

function handleExternalLinks(){
  var server = document.location.hostname;
  var anchors = document.getElementsByTagName(quot;aquot;);
  var i, href;
  for( i=0; i < anchors.length; i++ ){
    href = anchors[i].href;
    if( href.indexOf(quot;http://quot; + server) == -1 &&
         href.indexOf(quot;https://quot; + server) == -1 ){
      // HREF is not a file on my server
      anchors[i].onclick = function(){
         newWin( this.href );
      };
    }
  }
}


IN CONTROL 2009                                       69
FUNDAMENTAL JAVASCRIPT




Getting warmer...
window.onload = handleExternalLinks;

function handleExternalLinks(){
  var server = document.location.hostname;
  var anchors = document.getElementsByTagName(quot;aquot;);
  var i, href;
  for( i=0; i < anchors.length; i++ ){
    href = anchors[i].href;
    if( href.indexOf(quot;http://quot; + server) == -1 &&
         href.indexOf(quot;https://quot; + server) == -1 ){
      // HREF is not a file on my server
      anchors[i].onclick = function(){
         newWin( this.href );
      };
    }
  }
}


IN CONTROL 2009                                       69
FUNDAMENTAL JAVASCRIPT




Getting warmer...
window.onload = handleExternalLinks;

function handleExternalLinks(){
  var server = document.location.hostname;
  var anchors = document.getElementsByTagName(quot;aquot;);
  var i, href;
  for( i=0; i < anchors.length; i++ ){
    href = anchors[i].href;
    if( href.indexOf(quot;http://quot; + server) == -1 &&
         href.indexOf(quot;https://quot; + server) == -1 ){
      // HREF is not a file on my server
      anchors[i].onclick = function(){
         newWin( this.href );
      };
    }
  }
}


IN CONTROL 2009                                       69
FUNDAMENTAL JAVASCRIPT




Getting warmer...
window.onload = handleExternalLinks;

function handleExternalLinks(){
  var server = document.location.hostname;
  var anchors = document.getElementsByTagName(quot;aquot;);
  var i, href;
  for( i=0; i < anchors.length; i++ ){
    href = anchors[i].href;
    if( href.indexOf(quot;http://quot; + server) == -1 &&
         href.indexOf(quot;https://quot; + server) == -1 ){
      // HREF is not a file on my server
      anchors[i].onclick = function(){
         newWin( this.href );
      };
    }
  }
}


IN CONTROL 2009                                       69
FUNDAMENTAL JAVASCRIPT




You’re hot
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 );
    }
}




IN CONTROL 2009                                     70
FUNDAMENTAL JAVASCRIPT




You’re hot
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 );
    }
}




IN CONTROL 2009                                     70
FUNDAMENTAL JAVASCRIPT




You’re hot
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 );
    }
}




IN CONTROL 2009                                     70
FUNDAMENTAL JAVASCRIPT




You’re hot
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 );
    }
}




IN CONTROL 2009                                     70
FUNDAMENTAL JAVASCRIPT




You’re hot
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 );
    }
}




IN CONTROL 2009                                     70
FUNDAMENTAL JAVASCRIPT




You’re hot
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 );
    }
}




IN CONTROL 2009                                     70
WEB STANDARDS: FUELING INNOVATION




WEB BUILDER 2.0                     71
JavaScript
             CSS
FUNDAMENTAL JAVASCRIPT




Remember stuff like this?
<a href=quot;foo.htmlquot;
   style=quot;color:blue;quot;
   onmouseover=quot;this.style.color='red'quot;
   onmouseout=quot;this.style.color='blue'quot;>Foo</a>




IN CONTROL 2009                                   73
FUNDAMENTAL JAVASCRIPT




Remember stuff like this?
<a href=quot;foo.htmlquot;
   style=quot;color:blue;quot;
   onmouseover=quot;this.style.color='red'quot;
   onmouseout=quot;this.style.color='blue'quot;>Foo</a>

Obvisouly, we should be doing this instead:
a, a:link, a:visited {
  color: blue;
}
a:hover {
  color: red;
}




IN CONTROL 2009                                   73
FUNDAMENTAL JAVASCRIPT




Isn’t this the same?
for( i=0; i<objects.length; i++){
  objects[i].style.display = 'none';
}




IN CONTROL 2009                        74
FUNDAMENTAL JAVASCRIPT




Small improvement
for( i=0; i<objects.length; i++){
  objects[i].style.position = 'absolute';
  objects[i].style.left     = '-999em';
}




IN CONTROL 2009                             75
FUNDAMENTAL JAVASCRIPT




Separation
CSS:
.hidden {
  position: absolute;
  left: -999em;
}


JavaScript:
for( i=0; i<objects.length; i++){
  objects[i].addClassName( 'hidden' );
}




IN CONTROL 2009                          76
FUNDAMENTAL JAVASCRIPT




    Maintenance options
๏   external style rules added to your 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




    IN CONTROL 2009                                        77
FUNDAMENTAL JAVASCRIPT




Option 1: Add by hand
At the end of your screen layout CSS file:
/* =START WickedCool Script CSS (do not remove) */
.wicked {
  color: red;
  font: bold 4em/2 quot;Comic Sansquot;;
}
.cool {
  color: blue;
  font: bold 4em/2 quot;Comic Sansquot;;
}
/* =END WickedCool Script CSS */




IN CONTROL 2009                                      78
FUNDAMENTAL JAVASCRIPT




Option 2: Include by hand
Added to the head of your document:

<script type=quot;text/javascriptquot; src=quot;WickedCool.jsquot;></script>
<link rel=quot;stylesheetquot; type=quot;text/cssquot;
      media=quot;screenquot; href=quot;WickedCool.cssquot; />




IN CONTROL 2009                                                79
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
function FindPath( filename ){
  var path = false;
  var scripts = document.getElementsByTagName( 'script' );
  for( var i=0; i<scripts.length; i++ ){
    if( scripts[i].getAttribute( 'src' ) &&
        scripts[i].getAttribute( 'src' )
                  .indexOf( filename ) != -1 ){
      path = scripts[i].getAttribute( 'src' )
                       .replace( new RegExp( filename ), '' );
      break;
    }
  }
  return path;
}




IN CONTROL 2009                                              80
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
function FindPath( filename ){
  var path = false;
  var scripts = document.getElementsByTagName( 'script' );
  for( var i=0; i<scripts.length; i++ ){
    if( scripts[i].getAttribute( 'src' ) &&
        scripts[i].getAttribute( 'src' )
                  .indexOf( filename ) != -1 ){
      path = scripts[i].getAttribute( 'src' )
                       .replace( new RegExp( filename ), '' );
      break;
    }
  }
  return path;
}




IN CONTROL 2009                                              80
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
function FindPath( filename ){
  var path = false;
  var scripts = document.getElementsByTagName( 'script' );
  for( var i=0; i<scripts.length; i++ ){
    if( scripts[i].getAttribute( 'src' ) &&
        scripts[i].getAttribute( 'src' )
                  .indexOf( filename ) != -1 ){
      path = scripts[i].getAttribute( 'src' )
                       .replace( new RegExp( filename ), '' );
      break;
    }
  }
  return path;
}




IN CONTROL 2009                                              80
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
function FindPath( filename ){
  var path = false;
  var scripts = document.getElementsByTagName( 'script' );
  for( var i=0; i<scripts.length; i++ ){
    if( scripts[i].getAttribute( 'src' ) &&
        scripts[i].getAttribute( 'src' )
                  .indexOf( filename ) != -1 ){
      path = scripts[i].getAttribute( 'src' )
                       .replace( new RegExp( filename ), '' );
      break;
    }
  }
  return path;
}




IN CONTROL 2009                                              80
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
function FindPath( filename ){
  var path = false;
  var scripts = document.getElementsByTagName( 'script' );
  for( var i=0; i<scripts.length; i++ ){
    if( scripts[i].getAttribute( 'src' ) &&
        scripts[i].getAttribute( 'src' )
                  .indexOf( filename ) != -1 ){
      path = scripts[i].getAttribute( 'src' )
                       .replace( new RegExp( filename ), '' );
      break;
    }
  }
  return path;
}




IN CONTROL 2009                                              80
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
function FindPath( filename ){
  var path = false;
  var scripts = document.getElementsByTagName( 'script' );
  for( var i=0; i<scripts.length; i++ ){
    if( scripts[i].getAttribute( 'src' ) &&
        scripts[i].getAttribute( 'src' )
                  .indexOf( filename ) != -1 ){
      path = scripts[i].getAttribute( 'src' )
                       .replace( new RegExp( filename ), '' );
      break;
    }
  }
  return path;
}




IN CONTROL 2009                                              80
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
function FindPath( filename ){
  var path = false;
  var scripts = document.getElementsByTagName( 'script' );
  for( var i=0; i<scripts.length; i++ ){
    if( scripts[i].getAttribute( 'src' ) &&
        scripts[i].getAttribute( 'src' )
                  .indexOf( filename ) != -1 ){
      path = scripts[i].getAttribute( 'src' )
                       .replace( new RegExp( filename ), '' );
      break;
    }
  }
  return path;
}




IN CONTROL 2009                                              80
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
function FindPath( filename ){
  var path = false;
  var scripts = document.getElementsByTagName( 'script' );
  for( var i=0; i<scripts.length; i++ ){
    if( scripts[i].getAttribute( 'src' ) &&
        scripts[i].getAttribute( 'src' )
                  .indexOf( filename ) != -1 ){
      path = scripts[i].getAttribute( 'src' )
                       .replace( new RegExp( filename ), '' );
      break;
    }
  }
  return path;
}




IN CONTROL 2009                                              80
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
var WickedCool = {
  jsFile:    'WickedCool.js',
  cssFile:   'WickedCool.css',
  basePath: false,
  initialize: function(){
    // determine the path
    this.basePath = FindPath( this.jsFile );
    // add the CSS file
    var css = document.createElement( 'link' );
    css.setAttribute( 'rel', 'stylesheet' );
    css.setAttribute( 'type', 'text/css' );
    css.setAttribute( 'media', 'screen' );
    css.setAttribute( 'href', this.basePath + this.cssFile );
    document.getElementsByTagName( 'head' )[0]
            .appendChild( css );
    // do the rest of the wicked cool stuff
  }
};

IN CONTROL 2009                                                 81
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
var WickedCool = {
  jsFile:    'WickedCool.js',
  cssFile:   'WickedCool.css',
  basePath: false,
  initialize: function(){
    // determine the path
    this.basePath = FindPath( this.jsFile );
    // add the CSS file
    var css = document.createElement( 'link' );
    css.setAttribute( 'rel', 'stylesheet' );
    css.setAttribute( 'type', 'text/css' );
    css.setAttribute( 'media', 'screen' );
    css.setAttribute( 'href', this.basePath + this.cssFile );
    document.getElementsByTagName( 'head' )[0]
            .appendChild( css );
    // do the rest of the wicked cool stuff
  }
};

IN CONTROL 2009                                                 81
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
var WickedCool = {
  jsFile:    'WickedCool.js',
  cssFile:   'WickedCool.css',
  basePath: false,
  initialize: function(){
    // determine the path
    this.basePath = FindPath( this.jsFile );
    // add the CSS file
    var css = document.createElement( 'link' );
    css.setAttribute( 'rel', 'stylesheet' );
    css.setAttribute( 'type', 'text/css' );
    css.setAttribute( 'media', 'screen' );
    css.setAttribute( 'href', this.basePath + this.cssFile );
    document.getElementsByTagName( 'head' )[0]
            .appendChild( css );
    // do the rest of the wicked cool stuff
  }
};

IN CONTROL 2009                                                 81
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
var WickedCool = {
  jsFile:    'WickedCool.js',
  cssFile:   'WickedCool.css',
  basePath: false,
  initialize: function(){
    // determine the path
    this.basePath = FindPath( this.jsFile );
    // add the CSS file
    var css = document.createElement( 'link' );
    css.setAttribute( 'rel', 'stylesheet' );
    css.setAttribute( 'type', 'text/css' );
    css.setAttribute( 'media', 'screen' );
    css.setAttribute( 'href', this.basePath + this.cssFile );
    document.getElementsByTagName( 'head' )[0]
            .appendChild( css );
    // do the rest of the wicked cool stuff
  }
};

IN CONTROL 2009                                                 81
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
var WickedCool = {
  jsFile:    'WickedCool.js',
  cssFile:   'WickedCool.css',
  basePath: false,
  initialize: function(){
    // determine the path
    this.basePath = FindPath( this.jsFile );
    // add the CSS file
    var css = document.createElement( 'link' );
    css.setAttribute( 'rel', 'stylesheet' );
    css.setAttribute( 'type', 'text/css' );
    css.setAttribute( 'media', 'screen' );
    css.setAttribute( 'href', this.basePath + this.cssFile );
    document.getElementsByTagName( 'head' )[0]
            .appendChild( css );
    // do the rest of the wicked cool stuff
  }
};

IN CONTROL 2009                                                 81
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
var WickedCool = {
  jsFile:    'WickedCool.js',
  cssFile:   'WickedCool.css',
  basePath: false,
  initialize: function(){
    // determine the path
    this.basePath = FindPath( this.jsFile );
    // add the CSS file
    var css = document.createElement( 'link' );
    css.setAttribute( 'rel', 'stylesheet' );
    css.setAttribute( 'type', 'text/css' );
    css.setAttribute( 'media', 'screen' );
    css.setAttribute( 'href', this.basePath + this.cssFile );
    document.getElementsByTagName( 'head' )[0]
            .appendChild( css );
    // do the rest of the wicked cool stuff
  }
};

IN CONTROL 2009                                                 81
FUNDAMENTAL JAVASCRIPT




Option 3: Scripted include
var WickedCool = {
  jsFile:    'WickedCool.js',
  cssFile:   'WickedCool.css',
  basePath: false,
  initialize: function(){
    // determine the path
    this.basePath = FindPath( this.jsFile );
    // add the CSS file
    var css = document.createElement( 'link' );
    css.setAttribute( 'rel', 'stylesheet' );
    css.setAttribute( 'type', 'text/css' );
    css.setAttribute( 'media', 'screen' );
    css.setAttribute( 'href', this.basePath + this.cssFile );
    document.getElementsByTagName( 'head' )[0]
            .appendChild( css );
    // do the rest of the wicked cool stuff
  }
};

IN CONTROL 2009                                                 81
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
function addCSS( styles ){
  var el = document.createElement( 'style' );
      el.setAttribute( 'type', 'text/css' );
  if( el.styleSheet ){
    el.styleSheet.cssText = styles;
  } else {
    el.appendChild( document.createTextNode( styles ) );
  }
  document.getElementsByTagName( 'head' )[0]
           .appendChild( el );
}




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 82
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
function addCSS( styles ){
  var el = document.createElement( 'style' );
      el.setAttribute( 'type', 'text/css' );
  if( el.styleSheet ){
    el.styleSheet.cssText = styles;
  } else {
    el.appendChild( document.createTextNode( styles ) );
  }
  document.getElementsByTagName( 'head' )[0]
           .appendChild( el );
}




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 82
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
function addCSS( styles ){
  var el = document.createElement( 'style' );
      el.setAttribute( 'type', 'text/css' );
  if( el.styleSheet ){
    el.styleSheet.cssText = styles;
  } else {
    el.appendChild( document.createTextNode( styles ) );
  }
  document.getElementsByTagName( 'head' )[0]
           .appendChild( el );
}




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 82
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
function addCSS( styles ){
  var el = document.createElement( 'style' );
      el.setAttribute( 'type', 'text/css' );
  if( el.styleSheet ){
    el.styleSheet.cssText = styles;
  } else {
    el.appendChild( document.createTextNode( styles ) );
  }
  document.getElementsByTagName( 'head' )[0]
           .appendChild( el );
}




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 82
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
function addCSS( styles ){
  var el = document.createElement( 'style' );
      el.setAttribute( 'type', 'text/css' );
  if( el.styleSheet ){
    el.styleSheet.cssText = styles;
  } else {
    el.appendChild( document.createTextNode( styles ) );
  }
  document.getElementsByTagName( 'head' )[0]
           .appendChild( el );
}




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 82
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
function addCSS( styles ){
  var el = document.createElement( 'style' );
      el.setAttribute( 'type', 'text/css' );
  if( el.styleSheet ){
    el.styleSheet.cssText = styles;
  } else {
    el.appendChild( document.createTextNode( styles ) );
  }
  document.getElementsByTagName( 'head' )[0]
           .appendChild( el );
}




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 82
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
var WickedCool = {
  _css: '.wicked { color: red; ' +
        '          font: bold 4em/2 quot;Comic Sansquot;; } ' +
        '.cool { color: blue; ' +
        '        font: bold 4em/2' quot;Comic Sansquot;; }',
  initialize: function(){
    // add the CSS
    addCSS( this._css );
    // do the rest of the wicked cool stuff
  }
};




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 83
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
var WickedCool = {
  _css: '.wicked { color: red; ' +
        '          font: bold 4em/2 quot;Comic Sansquot;; } ' +
        '.cool { color: blue; ' +
        '        font: bold 4em/2' quot;Comic Sansquot;; }',
  initialize: function(){
    // add the CSS
    addCSS( this._css );
    // do the rest of the wicked cool stuff
  }
};




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 83
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
var WickedCool = {
  _css: '.wicked { color: red; ' +
        '          font: bold 4em/2 quot;Comic Sansquot;; } ' +
        '.cool { color: blue; ' +
        '        font: bold 4em/2' quot;Comic Sansquot;; }',
  initialize: function(){
    // add the CSS
    addCSS( this._css );
    // do the rest of the wicked cool stuff
  }
};




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 83
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
var WickedCool = {
  _css: '.wicked { color: red; ' +
        '          font: bold 4em/2 quot;Comic Sansquot;; } ' +
        '.cool { color: blue; ' +
        '        font: bold 4em/2' quot;Comic Sansquot;; }',
  initialize: function(){
    // add the CSS
    addCSS( this._css );
    // do the rest of the wicked cool stuff
  }
};




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 83
FUNDAMENTAL JAVASCRIPT




Option 4: Scripted embed
var WickedCool = {
  _css: '.wicked { color: red; ' +
        '          font: bold 4em/2 quot;Comic Sansquot;; } ' +
        '.cool { color: blue; ' +
        '        font: bold 4em/2' quot;Comic Sansquot;; }',
  initialize: function(){
    // add the CSS
    addCSS( this._css );
    // do the rest of the wicked cool stuff
  }
};




                                          based on the work of Nicholas Zakas

IN CONTROL 2009                                                                 83
BUT KEEP IN MIND
YOU NEED TO
   AVOID APPLYING
SCRIPT-RELATED STYLES
UNTIL YOU KNOW
YOUR SCRIPT CAN RUN
     AND IT HAS
INITIALIZED PROPERLY
FUNDAMENTAL JAVASCRIPT




    How do we do that?
๏   make your style rules specific:

    .TabInterface-folder {
      ...
    }

    or

    #TabInterface .tab {
      ...
    }
    #TabInterface .tab.active {
      ...
    }




    IN CONTROL 2009                  85
FUNDAMENTAL JAVASCRIPT




How do we do that?
<div id=quot;mainquot; class=quot;tabbedquot;>

becomes

<div id=quot;mainquot; class=quot;tabbed-onquot;>




IN CONTROL 2009                     86
FUNDAMENTAL JAVASCRIPT




How do we do that?
                               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




IN CONTROL 2009                                                     86
WEB STANDARDS: FUELING INNOVATION




WEB BUILDER 2.0                     87
FUNDAMENTAL JAVASCRIPT




Look for methods
function someFunction(){
  if( !document.getElementsByTagName ) return;
  // code that uses document.getElementsByTagName()
  ...
}




IN CONTROL 2009                                       88
FUNDAMENTAL JAVASCRIPT




Look for methods
function someFunction(){
  if( !document.getElementsByTagName ||
      !document.getElementById ) return;
  /* code that uses document.getElementsByTagName()
     and document.getElementById() */
}




IN CONTROL 2009                                       89
FUNDAMENTAL JAVASCRIPT




Look for elements
function someFunction(){
  if( !document.getElementsByTagName ||
       !document.getElementsByTagName( 'p' ) ) return;
  /* code that uses document.getElementsByTagName()
      and requires the presence of a P element */
  ...
}




IN CONTROL 2009                                          90
FUNDAMENTAL JAVASCRIPT




Look for identified elements
function someFunction(){
  if( !document.getElementById ||
      !document.getElementById( 'content' ) ) return;
  // code that requires the presence of #content
  ...
}




IN CONTROL 2009                                         91
FUNDAMENTAL JAVASCRIPT




Look for objects
function someFunction(){
  if( typeof( Prototype ) == 'undefined' ) return;
  // code that uses Prototype
  ...
}




IN CONTROL 2009                                      92
FUNDAMENTAL JAVASCRIPT




Look for object versions
function someFunction(){
  if( typeof( jQuery ) == 'undefined' ||
      parseFloat( jQuery.jquery ) < 1.2 ) return;
  // code that uses jQuery 1.2 or higher
  ...
}




IN CONTROL 2009                                     93
FUNDAMENTAL JAVASCRIPT




Look before you leap
window.onload = function(){
   if( document.getElementsByTagName &&
       document.getElementById ){
     someFunction();
  }
};




IN CONTROL 2009                           94
FUNDAMENTAL JAVASCRIPT




    PE with JavaScript
๏   Start with the content, then work your way out
๏   Get unobtrusive
๏   Keep some distance between your styles & your scripts
๏   Always wear your detective hat




    IN CONTROL 2009                                         95
HOW DOES IT
  ALL COME
 TOGETHER?
FUNDAMENTAL JAVASCRIPT




Example 1: Tab Interface




IN CONTROL 2009            97
FUNDAMENTAL JAVASCRIPT




Traditional approach
<h1>Pumpkin Pie</h1>

<div class=quot;containerquot;>
  <div class=quot;sectionquot;>
    <h2>Overview</h2>
    <img src=quot;pie.jpgquot; alt=quot;quot;>
    <p>Whether you're hosting a festive party or a casual get-together with
    friends, our Pumpkin Pie will make entertaining easy!</p>
    ...
  </div>
  ...
  <ul class=quot;tabsquot;>
    <li><a href=quot;#quot;>Overview</a></li>
    <li><a href=quot;#quot;>Ingredients</a></li>
    <li><a href=quot;#quot;>Directions</a></li>
    <li><a href=quot;#quot;>Nutrition</a></li>
  </ul>
</div>




IN CONTROL 2009                                                               98
FUNDAMENTAL JAVASCRIPT




Traditional approach
<h1>Pumpkin Pie</h1>

<div class=quot;containerquot;>
  <div class=quot;sectionquot;>
    <h2>Overview</h2>
    <img src=quot;pie.jpgquot; alt=quot;quot;>
    <p>Whether you're hosting a festive party or a casual get-together with
    friends, our Pumpkin Pie will make entertaining easy!</p>
    ...
  </div>
  ...
  <ul class=quot;tabsquot;>
    <li><a href=quot;#quot;>Overview</a></li>
    <li><a href=quot;#quot;>Ingredients</a></li>
    <li><a href=quot;#quot;>Directions</a></li>
    <li><a href=quot;#quot;>Nutrition</a></li>
  </ul>
</div>




IN CONTROL 2009                                                               98
FUNDAMENTAL JAVASCRIPT




Traditional approach
<h1>Pumpkin Pie</h1>

<div class=quot;containerquot;>
  <div class=quot;sectionquot;>
    <h2>Overview</h2>
    <img src=quot;pie.jpgquot; alt=quot;quot;>
    <p>Whether you're hosting a festive party or a casual get-together with
    friends, our Pumpkin Pie will make entertaining easy!</p>
    ...
  </div>
  ...
  <ul class=quot;tabsquot;>
    <li><a href=quot;#quot;>Overview</a></li>
    <li><a href=quot;#quot;>Ingredients</a></li>
    <li><a href=quot;#quot;>Directions</a></li>
    <li><a href=quot;#quot;>Nutrition</a></li>
  </ul>
</div>




IN CONTROL 2009                                                               98
FUNDAMENTAL JAVASCRIPT




Traditional approach
<h1>Pumpkin Pie</h1>

<div class=quot;containerquot;>
  <div class=quot;sectionquot;>
    <h2>Overview</h2>
    <img src=quot;pie.jpgquot; alt=quot;quot;>
    <p>Whether you're hosting a festive party or a casual get-together with
    friends, our Pumpkin Pie will make entertaining easy!</p>
    ...
  </div>
  ...
  <ul class=quot;tabsquot;>
    <li><a href=quot;#quot;>Overview</a></li>
    <li><a href=quot;#quot;>Ingredients</a></li>
    <li><a href=quot;#quot;>Directions</a></li>
    <li><a href=quot;#quot;>Nutrition</a></li>
  </ul>
</div>




IN CONTROL 2009                                                               98
FUNDAMENTAL JAVASCRIPT




No style




IN CONTROL 2009          99
FUNDAMENTAL JAVASCRIPT




A little typography




IN CONTROL 2009          100
FUNDAMENTAL JAVASCRIPT




Typography & color




IN CONTROL 2009          101
FUNDAMENTAL JAVASCRIPT




No style




IN CONTROL 2009          102
FUNDAMENTAL JAVASCRIPT




No style




                         .tabbed
IN CONTROL 2009                    102
FUNDAMENTAL JAVASCRIPT




The actual source
<h1>Pumpkin Pie</h1>

<div class=quot;tabbedquot;>
  <h2>Overview</h2>
  <img src=quot;pie.jpgquot; alt=quot;quot; />
  <p>Whether you're hosting a festive party or a casual get-together with friends,
  our Pumpkin Pie will make entertaining easy!</p>
  ...

  <h2>Ingredients</h2>
  <ul>
    <li>1 (9<abbr title=quot;inchquot;>in</abbr>) unbaked deep dish pie crust</li>
    <li>½ cup white sugar</li>
    <li>1 <abbr title=quot;teaspoonquot;>tsp</abbr> ground cinnamon</li>
    ...
  </ul>

  <h2>Directions</h2>
  ...
</div>




IN CONTROL 2009                                                                  103
FUNDAMENTAL JAVASCRIPT




The actual source
<h1>Pumpkin Pie</h1>

<div class=quot;tabbedquot;>
  <h2>Overview</h2>
  <img src=quot;pie.jpgquot; alt=quot;quot; />
  <p>Whether you're hosting a festive party or a casual get-together with friends,
  our Pumpkin Pie will make entertaining easy!</p>
  ...

  <h2>Ingredients</h2>
  <ul>
    <li>1 (9<abbr title=quot;inchquot;>in</abbr>) unbaked deep dish pie crust</li>
    <li>½ cup white sugar</li>
    <li>1 <abbr title=quot;teaspoonquot;>tsp</abbr> ground cinnamon</li>
    ...
  </ul>

  <h2>Directions</h2>
  ...
</div>




IN CONTROL 2009                                                                  103
FUNDAMENTAL JAVASCRIPT




Understanding the flow




IN CONTROL 2009          104
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  // Public Properties
  this.Version = '0.3'; // version

  // Private Properties
  var _i       = i;      // incrementor
  var _cabinet = el;     // the quot;cabinetquot; element (container)
  var _id      = false; // ID of _cabinet
  var _active = false; // ID of the active quot;folderquot;
  var _tag     = false; // tag we'll split it on
  // the tab list
  var _index   = document.createElement( 'ul' );
  // prototype elements
  var _els     = { li: document.createElement( 'li' ),
                    div: document.createElement( 'div' ) };

  // methods to go here

};




IN CONTROL 2009                                                 105
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  // Public Properties
  this.Version = '0.3'; // version

  // Private Properties
  var _i       = i;      // incrementor
  var _cabinet = el;     // the quot;cabinetquot; element (container)
  var _id      = false; // ID of _cabinet
  var _active = false; // ID of the active quot;folderquot;
  var _tag     = false; // tag we'll split it on
  // the tab list
  var _index   = document.createElement( 'ul' );
  // prototype elements
  var _els     = { li: document.createElement( 'li' ),
                    div: document.createElement( 'div' ) };

  // methods to go here

};




IN CONTROL 2009                                                 105
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  // Public Properties
  this.Version = '0.3'; // version

  // Private Properties
  var _i       = i;      // incrementor
  var _cabinet = el;     // the quot;cabinetquot; element (container)
  var _id      = false; // ID of _cabinet
  var _active = false; // ID of the active quot;folderquot;
  var _tag     = false; // tag we'll split it on
  // the tab list
  var _index   = document.createElement( 'ul' );
  // prototype elements
  var _els     = { li: document.createElement( 'li' ),
                    div: document.createElement( 'div' ) };

  // methods to go here

};




IN CONTROL 2009                                                 105
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  // Public Properties
  this.Version = '0.3'; // version

  // Private Properties
  var _i       = i;      // incrementor
  var _cabinet = el;     // the quot;cabinetquot; element (container)
  var _id      = false; // ID of _cabinet
  var _active = false; // ID of the active quot;folderquot;
  var _tag     = false; // tag we'll split it on
  // the tab list
  var _index   = document.createElement( 'ul' );
  // prototype elements
  var _els     = { li: document.createElement( 'li' ),
                    div: document.createElement( 'div' ) };

  // methods to go here

};




IN CONTROL 2009                                                 105
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  // Public Properties
  this.Version = '0.3'; // version

  // Private Properties
  var _i       = i;      // incrementor
  var _cabinet = el;     // the quot;cabinetquot; element (container)
  var _id      = false; // ID of _cabinet
  var _active = false; // ID of the active quot;folderquot;
  var _tag     = false; // tag we'll split it on
  // the tab list
  var _index   = document.createElement( 'ul' );
  // prototype elements
  var _els     = { li: document.createElement( 'li' ),
                    div: document.createElement( 'div' ) };

  // methods to go here

};




IN CONTROL 2009                                                 105
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  ...
  function initialize(){
    // code to come
  }
  function addClassName( e, c ){
    var classes = ( !e.className ) ? [] : e.className.split( ' ' );
    classes.push( c );
    e.className = classes.join( ' ' );
  }
  function removeClassName( e, c ){
    var classes = e.className.split( ' ' );
    for( var i=classes.length-1; i>=0; i-- ){
      if( classes[i] == c ) classes.splice( i, 1 );
    }
    e.className = classes.join( ' ' );
  }

  // start it up
  initialize();
};



IN CONTROL 2009                                                       106
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  ...
  function initialize(){
    // code to come
  }
  function addClassName( e, c ){
    var classes = ( !e.className ) ? [] : e.className.split( ' ' );
    classes.push( c );
    e.className = classes.join( ' ' );
  }
  function removeClassName( e, c ){
    var classes = e.className.split( ' ' );
    for( var i=classes.length-1; i>=0; i-- ){
      if( classes[i] == c ) classes.splice( i, 1 );
    }
    e.className = classes.join( ' ' );
  }

  // start it up
  initialize();
};



IN CONTROL 2009                                                       106
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  ...
  function initialize(){
    // code to come
  }
  function addClassName( e, c ){
    var classes = ( !e.className ) ? [] : e.className.split( ' ' );
    classes.push( c );
    e.className = classes.join( ' ' );
  }
  function removeClassName( e, c ){
    var classes = e.className.split( ' ' );
    for( var i=classes.length-1; i>=0; i-- ){
      if( classes[i] == c ) classes.splice( i, 1 );
    }
    e.className = classes.join( ' ' );
  }

  // start it up
  initialize();
};



IN CONTROL 2009                                                       106
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  ...
  function initialize(){
    // code to come
  }
  function addClassName( e, c ){
    var classes = ( !e.className ) ? [] : e.className.split( ' ' );
    classes.push( c );
    e.className = classes.join( ' ' );
  }
  function removeClassName( e, c ){
    var classes = e.className.split( ' ' );
    for( var i=classes.length-1; i>=0; i-- ){
      if( classes[i] == c ) classes.splice( i, 1 );
    }
    e.className = classes.join( ' ' );
  }

  // start it up
  initialize();
};



IN CONTROL 2009                                                       106
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  ...
  function initialize(){
    // code to come
  }
  function addClassName( e, c ){
    var classes = ( !e.className ) ? [] : e.className.split( ' ' );
    classes.push( c );
    e.className = classes.join( ' ' );
  }
  function removeClassName( e, c ){
    var classes = e.className.split( ' ' );
    for( var i=classes.length-1; i>=0; i-- ){
      if( classes[i] == c ) classes.splice( i, 1 );
    }
    e.className = classes.join( ' ' );
  }

  // start it up
  initialize();
};



IN CONTROL 2009                                                       106
FUNDAMENTAL JAVASCRIPT




THE CODE
function TabInterface( el, i ){
  function initialize(){

     // set the id
     _id = el.getAttribute( 'id' ) || 'folder-' + _i;
     if( !el.getAttribute( 'id' ) ) el.setAttribute( 'id', _id );

     // trim whitespace
     var node = _cabinet.firstChild;
     while( node ){
       var nextNode = node.nextSibling;
       if( node.nodeType == 3 &&
           !/S/.test( node.nodeValue ) )
         _cabinet.removeChild( node );
       node = nextNode;
     }

  }
  ...
};




IN CONTROL 2009                                                     107
FUNDAMENTAL JAVASCRIPT




THE CODE
function TabInterface( el, i ){
  function initialize(){

     // set the id
     _id = el.getAttribute( 'id' ) || 'folder-' + _i;
     if( !el.getAttribute( 'id' ) ) el.setAttribute( 'id', _id );

     // trim whitespace
     var node = _cabinet.firstChild;
     while( node ){
       var nextNode = node.nextSibling;
       if( node.nodeType == 3 &&
           !/S/.test( node.nodeValue ) )
         _cabinet.removeChild( node );
       node = nextNode;
     }

  }
  ...
};




IN CONTROL 2009                                                     107
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  function initialize(){
    ...

     // find the first heading
     var headers = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ];
     var hLen = headers.length;
     for( var i=0; i<hLen; i++ ){
       if( _cabinet.firstChild.nodeName.toLowerCase() == headers[i] ){
         _tag = headers[i];
         break;
       }
     }

  }
  ...
};




IN CONTROL 2009                                                          108
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  function initialize(){
    ...

     // establish the folders
     var rexp = new RegExp( '<(' + _tag + ')', 'ig' );
     var arr = _cabinet.innerHTML.replace( rexp, quot;||||<$1quot; ).split( '||||' );
         arr.shift();
     _cabinet.innerHTML = '';
     removeClassName( _cabinet, 'tabbed' );
     addClassName( _cabinet, 'tabbed-on' );

  }
  ...
};




IN CONTROL 2009                                                                 109
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  function initialize(){
    ...
    for( var k=0, aLen = arr.length; k<aLen; k++ ){
      // build the div
      var folder = _els.div.cloneNode( true );
          addClassName( folder, 'folder' );
          folder.setAttribute( 'id', _id + '-' + k );
          folder.innerHTML = arr[k];
          _cabinet.appendChild( folder );
      // build the tab
      var tab = _els.li.cloneNode( true );
          tab.folder = folder.getAttribute( 'id' );
          tab.setAttribute( 'id', tab.folder + '-tab' );
          tab.onclick = swap; // set the action
      var heading = folder.getElementsByTagName( _tag )[0];
          tab.innerHTML = heading.innerHTML;
          addClassName( heading, 'hidden' );
          _index.appendChild( tab );
    }
  }
  ...

IN CONTROL 2009                                               110
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  function initialize(){
    ...
    for( var k=0, aLen = arr.length; k<aLen; k++ ){
      // build the div
      var folder = _els.div.cloneNode( true );
          addClassName( folder, 'folder' );
          folder.setAttribute( 'id', _id + '-' + k );
          folder.innerHTML = arr[k];
          _cabinet.appendChild( folder );
      // build the tab
      var tab = _els.li.cloneNode( true );
          tab.folder = folder.getAttribute( 'id' );
          tab.setAttribute( 'id', tab.folder + '-tab' );
          tab.onclick = swap; // set the action
      var heading = folder.getElementsByTagName( _tag )[0];
          tab.innerHTML = heading.innerHTML;
          addClassName( heading, 'hidden' );
          _index.appendChild( tab );
    }
  }
  ...

IN CONTROL 2009                                               110
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  function initialize(){
    ...
    for( var k=0, aLen = arr.length; k<aLen; k++ ){
      // build the div
      var folder = _els.div.cloneNode( true );
          addClassName( folder, 'folder' );
          folder.setAttribute( 'id', _id + '-' + k );
          folder.innerHTML = arr[k];
          _cabinet.appendChild( folder );
      // build the tab
      var tab = _els.li.cloneNode( true );
          tab.folder = folder.getAttribute( 'id' );
          tab.setAttribute( 'id', tab.folder + '-tab' );
          tab.onclick = swap; // set the action
      var heading = folder.getElementsByTagName( _tag )[0];
          tab.innerHTML = heading.innerHTML;
          addClassName( heading, 'hidden' );
          _index.appendChild( tab );
    }
  }
  ...

IN CONTROL 2009                                               110
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
  function initialize(){
    ...
    for( var k=0, aLen = arr.length; k<aLen; k++ ){
      // build the div
      var folder = _els.div.cloneNode( true );
          addClassName( folder, 'folder' );
          folder.setAttribute( 'id', _id + '-' + k );
          folder.innerHTML = arr[k];
          _cabinet.appendChild( folder );
      // build the tab
      var tab = _els.li.cloneNode( true );
          tab.folder = folder.getAttribute( 'id' );
          tab.setAttribute( 'id', tab.folder + '-tab' );
          tab.onclick = swap; // set the action
      var heading = folder.getElementsByTagName( _tag )[0];
          tab.innerHTML = heading.innerHTML;
          addClassName( heading, 'hidden' );
          _index.appendChild( tab );
    }
  }
  ...

IN CONTROL 2009                                               110
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
   function initialize(){
     ...
     for( var k=0, aLen = arr.length; k<aLen; k++ ){
       ...
       // active?
       if( k == 0 ){
         addClassName( folder, 'visible' );
         _active = folder.getAttribute( 'id' );
         addClassName( tab, 'active-tab' );
       }
     }
     // add the index
     _index.className = 'tab-list';
     _cabinet.appendChild( _index );
   }
   ...
};




IN CONTROL 2009                                        111
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
   function initialize(){
     ...
     for( var k=0, aLen = arr.length; k<aLen; k++ ){
       ...
       // active?
       if( k == 0 ){
         addClassName( folder, 'visible' );
         _active = folder.getAttribute( 'id' );
         addClassName( tab, 'active-tab' );
       }
     }
     // add the index
     _index.className = 'tab-list';
     _cabinet.appendChild( _index );
   }
   ...
};




IN CONTROL 2009                                        111
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
   ...
   function swap( e ){
     e = ( e ) ? e : event;
     var tab = e.target || e.srcElement;
     removeClassName( document.getElementById( _active + '-tab' ), 'active-tab' );
     removeClassName( document.getElementById( _active ), 'visible' );
     addClassName( tab, 'active-tab' );
     addClassName( document.getElementById( tab.folder ), 'visible' );
     _active = tab.folder;
   }
   ...
};




IN CONTROL 2009                                                                      112
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
   ...
   function swap( e ){
     e = ( e ) ? e : event;
     var tab = e.target || e.srcElement;
     removeClassName( document.getElementById( _active + '-tab' ), 'active-tab' );
     removeClassName( document.getElementById( _active ), 'visible' );
     addClassName( tab, 'active-tab' );
     addClassName( document.getElementById( tab.folder ), 'visible' );
     _active = tab.folder;
   }
   ...
};




IN CONTROL 2009                                                                      112
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
   ...
   function swap( e ){
     e = ( e ) ? e : event;
     var tab = e.target || e.srcElement;
     removeClassName( document.getElementById( _active   + '-tab' ), 'active-tab' );
     removeClassName( document.getElementById( _active   ), 'visible' );
     addClassName( tab, 'active-tab' );
     addClassName( document.getElementById( tab.folder   ), 'visible' );
     _active = tab.folder;
   }
   ...
};




IN CONTROL 2009                                                                        112
FUNDAMENTAL JAVASCRIPT




The code
function TabInterface( el, i ){
   ...
   function swap( e ){
     e = ( e ) ? e : event;
     var tab = e.target || e.srcElement;
     removeClassName( document.getElementById( _active + '-tab' ), 'active-tab' );
     removeClassName( document.getElementById( _active ), 'visible' );
     addClassName( tab, 'active-tab' );
     addClassName( document.getElementById( tab.folder ), 'visible' );
     _active = tab.folder;
   }
   ...
};




IN CONTROL 2009                                                                      112
FUNDAMENTAL JAVASCRIPT




Greater flexibility
function TabInterface( el, i ){
   function initialize(){
     ...
     for( var k=0, aLen = arr.length; k<aLen; k++ ){
       ...
       var heading = folder.getElementsByTagName( _tag )[0];
           tab.innerHTML = heading.innerHTML;
           if( heading.getAttribute( 'title' ) ){
           addClassName( heading, 'hidden' );
             tab.innerHTML = heading.getAttribute( 'title' )
           _index.appendChild( tab );
           } else {
       ...   tab.innerHTML = heading.innerHTML;
     }       addClassName( heading, 'hidden' );
   }       }
   ...     _index.appendChild( tab );
};     ...
     }
   }
   ...
};




IN CONTROL 2009                                                113
FUNDAMENTAL JAVASCRIPT




Greater flexibility
function TabInterface( el, i ){
   function initialize(){
     ...
     for( var k=0, aLen = arr.length; k<aLen; k++ ){
       ...
       var heading = folder.getElementsByTagName( _tag )[0];
           if( heading.getAttribute( 'title' ) ){
             tab.innerHTML = heading.getAttribute( 'title' )
           } else {
             tab.innerHTML = heading.innerHTML;
             addClassName( heading, 'hidden' );
           }
           _index.appendChild( tab );
       ...
     }
   }
   ...
};




IN CONTROL 2009                                                113
FUNDAMENTAL JAVASCRIPT




Running it
// Load up TabInterface
if( document.getElementById &&
    document.getElementsByTagName &&
    document.createElement ){
  var cabinets = Array();
  addDOMLoadEvent( function(){
    var collection = document.getElementsByTagName( '*' );
    for( var i=0, cLen = collection.length; i<cLen; i++ ){
       if( collection[i] &&
           /s*tabbeds*/.test( collection[i].className ) ){
         cabinets.push( new TabInterface( collection[i], i ) );
       }
    }
  } );
}




IN CONTROL 2009                                                   114
FUNDAMENTAL JAVASCRIPT




Running it
// Load up TabInterface
if( document.getElementById &&
    document.getElementsByTagName &&
    document.createElement ){
  var cabinets = Array();
  addDOMLoadEvent( function(){
    var collection = document.getElementsByTagName( '*' );
    for( var i=0, cLen = collection.length; i<cLen; i++ ){
       if( collection[i] &&
           /s*tabbeds*/.test( collection[i].className ) ){
         cabinets.push( new TabInterface( collection[i], i ) );
       }
    }
  } );
}




IN CONTROL 2009                                                   114
FUNDAMENTAL JAVASCRIPT




Running it
// Load up TabInterface
if( document.getElementById &&
    document.getElementsByTagName &&
    document.createElement ){
  var cabinets = Array();
  addDOMLoadEvent( function(){
    var collection = document.getElementsByTagName( '*' );
    for( var i=0, cLen = collection.length; i<cLen; i++ ){
       if( collection[i] &&
           /s*tabbeds*/.test( collection[i].className ) ){
         cabinets.push( new TabInterface( collection[i], i ) );
       }
    }
  } );
}




IN CONTROL 2009                                                   114
FUNDAMENTAL JAVASCRIPT




Running it
// Load up TabInterface
if( document.getElementById &&
    document.getElementsByTagName &&
    document.createElement ){
  var cabinets = Array();
  addDOMLoadEvent( function(){
    var collection = document.getElementsByTagName( '*' );
    for( var i=0, cLen = collection.length; i<cLen; i++ ){
       if( collection[i] &&
           /s*tabbeds*/.test( collection[i].className ) ){
         cabinets.push( new TabInterface( collection[i], i ) );
       }
    }
  } );
}




IN CONTROL 2009                                                   114
FUNDAMENTAL JAVASCRIPT




The full experience




IN CONTROL 2009          115
QUESTIONS?
FUNDAMENTAL JAVASCRIPT




Example 2: Collapsing Form




IN CONTROL 2009              117
FUNDAMENTAL JAVASCRIPT




Collapsing Form as HTML




IN CONTROL 2009           118
FUNDAMENTAL JAVASCRIPT




Collapsing Form with CSS




IN CONTROL 2009            119
FUNDAMENTAL JAVASCRIPT




Collapsing Form with CSS




IN CONTROL 2009            120
FUNDAMENTAL JAVASCRIPT




Collapsing Form with CSS




IN CONTROL 2009            121
FUNDAMENTAL JAVASCRIPT




HTML hooks




IN CONTROL 2009          122
FUNDAMENTAL JAVASCRIPT




HTML hooks




                         form.collapsing
IN CONTROL 2009                            122
FUNDAMENTAL JAVASCRIPT




HTML hooks




                         fieldset.optional
IN CONTROL 2009                              122
FUNDAMENTAL JAVASCRIPT




Understanding the flow




IN CONTROL 2009          123
FUNDAMENTAL JAVASCRIPT




The code
var Easy = {
   addClassName: function( e, c ){
     var classes = ( !e.className ) ? [] : e.className.split( ' ' );
     classes.push( c );
     e.className = classes.join( ' ' );
   },
   removeClassName: function( e, c ){
     var classes = e.className.split( ' ' );
     for( var i=classes.length-1; i>=0; i-- ){
       if( classes[i] == c ) classes.splice( i, 1 );
     }
     e.className = classes.join( ' ' );
   },
   hasClassName: function( e, c ){
     var classes = e.className.split( ' ' );
     for( var i=classes.length-1; i>=0; i-- ){
       if( classes[i] == c ) return true;
     }
     return false;
   }
};



IN CONTROL 2009                                                        124
FUNDAMENTAL JAVASCRIPT




The code
var Easy = {
   addClassName: function( e, c ){
     var classes = ( !e.className ) ? [] : e.className.split( ' ' );
     classes.push( c );
     e.className = classes.join( ' ' );
   },
   removeClassName: function( e, c ){
     var classes = e.className.split( ' ' );
     for( var i=classes.length-1; i>=0; i-- ){
       if( classes[i] == c ) classes.splice( i, 1 );
     }
     e.className = classes.join( ' ' );
   },
   hasClassName: function( e, c ){
     var classes = e.className.split( ' ' );
     for( var i=classes.length-1; i>=0; i-- ){
       if( classes[i] == c ) return true;
     }
     return false;
   }
};



IN CONTROL 2009                                                        124
FUNDAMENTAL JAVASCRIPT




The code
var Easy = {
   addClassName: function( e, c ){
     var classes = ( !e.className ) ? [] : e.className.split( ' ' );
     classes.push( c );
     e.className = classes.join( ' ' );
   },
   removeClassName: function( e, c ){
     var classes = e.className.split( ' ' );
     for( var i=classes.length-1; i>=0; i-- ){
       if( classes[i] == c ) classes.splice( i, 1 );
     }
     e.className = classes.join( ' ' );
   },
   hasClassName: function( e, c ){
     var classes = e.className.split( ' ' );
     for( var i=classes.length-1; i>=0; i-- ){
       if( classes[i] == c ) return true;
     }
     return false;
   }
};



IN CONTROL 2009                                                        124
FUNDAMENTAL JAVASCRIPT




The code
var Easy = {
   addClassName: function( e, c ){
     var classes = ( !e.className ) ? [] : e.className.split( ' ' );
     classes.push( c );
     e.className = classes.join( ' ' );
   },
   removeClassName: function( e, c ){
     var classes = e.className.split( ' ' );
     for( var i=classes.length-1; i>=0; i-- ){
       if( classes[i] == c ) classes.splice( i, 1 );
     }
     e.className = classes.join( ' ' );
   },
   hasClassName: function( e, c ){
     var classes = e.className.split( ' ' );
     for( var i=classes.length-1; i>=0; i-- ){
       if( classes[i] == c ) return true;
     }
     return false;
   }
};



IN CONTROL 2009                                                        124
FUNDAMENTAL JAVASCRIPT




The code
var Easy = {
   addClassName: function( e, c ){
     var classes = ( !e.className ) ? [] : e.className.split( ' ' );
     classes.push( c );
     e.className = classes.join( ' ' );
   },
   removeClassName: function( e, c ){
     var classes = e.className.split( ' ' );
     for( var i=classes.length-1; i>=0; i-- ){
       if( classes[i] == c ) classes.splice( i, 1 );
     }
     e.className = classes.join( ' ' );
   },
   hasClassName: function( e, c ){
     var classes = e.className.split( ' ' );
     for( var i=classes.length-1; i>=0; i-- ){
       if( classes[i] == c ) return true;
     }
     return false;
   }
};



IN CONTROL 2009                                                        124
FUNDAMENTAL JAVASCRIPT




The code
var CollapsingForm = Class.create();
CollapsingForm.prototype = {

  link:             document.createElement( 'a' ),
  linkText:         [ document.createTextNode( 'More options' ),
                      document.createTextNode( 'Fewer options' ) ],
  hidden:           [],
  state:            false,
  id:               false,

};




IN CONTROL 2009                                                       125
FUNDAMENTAL JAVASCRIPT




The code
var CollapsingForm = Class.create();
CollapsingForm.prototype = {

  link:             document.createElement( 'a' ),
  linkText:         [ document.createTextNode( 'More options' ),
                      document.createTextNode( 'Fewer options' ) ],
  hidden:           [],
  state:            false,
  id:               false,

};




IN CONTROL 2009                                                       125
FUNDAMENTAL JAVASCRIPT




The code
var CollapsingForm = Class.create();
CollapsingForm.prototype = {

  link:             document.createElement( 'a' ),
  linkText:         [ document.createTextNode( 'More options' ),
                      document.createTextNode( 'Fewer options' ) ],
  hidden:           [],
  state:            false,
  id:               false,

};




IN CONTROL 2009                                                       125
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   initialize: function( form, i ){
     // set the id
     this.id = i;
     // get the fieldsets
     var coll = form.getElementsByTagName( 'fieldset' );
     // look for hiddens
     var hide = false;
     for( var i=coll.length-1; i>=0; i-- ){
       if( coll[i].className.indexOf( 'hide-me' ) != -1 ){
         hide = true;
         Easy.addClassName( coll[i], 'hidden' );
         Easy.removeClassName( coll[i], 'hide-me' );
         this.hidden.push( coll[i] );
       }
     }
     // more to come
   }
};




IN CONTROL 2009                                              126
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   initialize: function( form, i ){
     // set the id
     this.id = i;
     // get the fieldsets
     var coll = form.getElementsByTagName( 'fieldset' );
     // look for hiddens
     var hide = false;
     for( var i=coll.length-1; i>=0; i-- ){
       if( coll[i].className.indexOf( 'hide-me' ) != -1 ){
         hide = true;
         Easy.addClassName( coll[i], 'hidden' );
         Easy.removeClassName( coll[i], 'hide-me' );
         this.hidden.push( coll[i] );
       }
     }
     // more to come
   }
};




IN CONTROL 2009                                              126
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   initialize: function( form, i ){
     // set the id
     this.id = i;
     // get the fieldsets
     var coll = form.getElementsByTagName( 'fieldset' );
     // look for hiddens
     var hide = false;
     for( var i=coll.length-1; i>=0; i-- ){
       if( coll[i].className.indexOf( 'hide-me' ) != -1 ){
         hide = true;
         Easy.addClassName( coll[i], 'hidden' );
         Easy.removeClassName( coll[i], 'hide-me' );
         this.hidden.push( coll[i] );
       }
     }
     // more to come
   }
};




IN CONTROL 2009                                              126
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   initialize: function( form, i ){
     // set the id
     this.id = i;
     // get the fieldsets
     var coll = form.getElementsByTagName( 'fieldset' );
     // look for hiddens
     var hide = false;
     for( var i=coll.length-1; i>=0; i-- ){
       if( coll[i].className.indexOf( 'hide-me' ) != -1 ){
         hide = true;
         Easy.addClassName( coll[i], 'hidden' );
         Easy.removeClassName( coll[i], 'hide-me' );
         this.hidden.push( coll[i] );
       }
     }
     // more to come
   }
};




IN CONTROL 2009                                              126
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   initialize: function( form, i ){
     ...
     // stop if no hiddens
     if( hide === false ) return;
     this.state = 'less';
     // create & append the link to the first fieldset
     this.link = document.createElement( 'a' );
     this.link.className = 'show-hide-link';
     this.link.setAttribute( 'href', '#' );
     Event.observe( this.link, 'click',
                    this.toggle.bindAsEventListener( this ), false );
     this.link.appendChild( this.linkText[0] );
     coll[0].appendChild( this.link );
     Easy.addClassName( form, 'collapsible' );
     Easy.removeClassName( form, 'collapsing' );
   }
};




IN CONTROL 2009                                                         127
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   initialize: function( form, i ){
     ...
     // stop if no hiddens
     if( hide === false ) return;
     this.state = 'less';
     // create & append the link to the first fieldset
     this.link = document.createElement( 'a' );
     this.link.className = 'show-hide-link';
     this.link.setAttribute( 'href', '#' );
     Event.observe( this.link, 'click',
                    this.toggle.bindAsEventListener( this ), false );
     this.link.appendChild( this.linkText[0] );
     coll[0].appendChild( this.link );
     Easy.addClassName( form, 'collapsible' );
     Easy.removeClassName( form, 'collapsing' );
   }
};




IN CONTROL 2009                                                         127
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   initialize: function( form, i ){
     ...
     // stop if no hiddens
     if( hide === false ) return;
     this.state = 'less';
     // create & append the link to the first fieldset
     this.link = document.createElement( 'a' );
     this.link.className = 'show-hide-link';
     this.link.setAttribute( 'href', '#' );
     Event.observe( this.link, 'click',
                    this.toggle.bindAsEventListener( this ), false );
     this.link.appendChild( this.linkText[0] );
     coll[0].appendChild( this.link );
     Easy.addClassName( form, 'collapsible' );
     Easy.removeClassName( form, 'collapsing' );
   }
};




IN CONTROL 2009                                                         127
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   initialize: function( form, i ){
     ...
     // stop if no hiddens
     if( hide === false ) return;
     this.state = 'less';
     // create & append the link to the first fieldset
     this.link = document.createElement( 'a' );
     this.link.className = 'show-hide-link';
     this.link.setAttribute( 'href', '#' );
     Event.observe( this.link, 'click',
                    this.toggle.bindAsEventListener( this ), false );
     this.link.appendChild( this.linkText[0] );
     coll[0].appendChild( this.link );
     Easy.addClassName( form, 'collapsible' );
     Easy.removeClassName( form, 'collapsing' );
   }
};




IN CONTROL 2009                                                         127
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   initialize: function( form, i ){
     ...
   },
   toggle:     function(){
     if( this.state == 'less' ){
       this.showMore();
     } else {
       this.showLess();
     }
   },
   showMore:   function(){
     // code to come
   },
   showLess:   function(){
     // code to come
   }
};




IN CONTROL 2009                       128
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   initialize: function( form, i ){
     ...
   },
   toggle:     function(){
     if( this.state == 'less' ){
       this.showMore();
     } else {
       this.showLess();
     }
   },
   showMore:   function(){
     // code to come
   },
   showLess:   function(){
     // code to come
   }
};




IN CONTROL 2009                       128
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   showMore:   function(){
     for( var i=0; i<this.hidden.length; i++ ){
       Easy.removeClassName( this.hidden[i], 'hidden' );
     }
     this.link.replaceChild( this.linkText[1], this.link.childNodes[0] );
     this.state = 'more';
   },
   showLess:   function(){
     for( var i=0; i<this.hidden.length; i++ ){
       Easy.addClassName( this.hidden[i], 'hidden' );
     }
     this.link.replaceChild( this.linkText[0], this.link.childNodes[0] );
     this.state = 'less';
   }
};




IN CONTROL 2009                                                             129
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   showMore:   function(){
     for( var i=0; i<this.hidden.length; i++ ){
       Easy.removeClassName( this.hidden[i], 'hidden' );
     }
     this.link.replaceChild( this.linkText[1], this.link.childNodes[0] );
     this.state = 'more';
   },
   showLess:   function(){
     for( var i=0; i<this.hidden.length; i++ ){
       Easy.addClassName( this.hidden[i], 'hidden' );
     }
     this.link.replaceChild( this.linkText[0], this.link.childNodes[0] );
     this.state = 'less';
   }
};




IN CONTROL 2009                                                             129
FUNDAMENTAL JAVASCRIPT




The code
CollapsingForm.prototype = {
   ...
   showMore:   function(){
     for( var i=0; i<this.hidden.length; i++ ){
       Easy.removeClassName( this.hidden[i], 'hidden' );
     }
     this.link.replaceChild( this.linkText[1], this.link.childNodes[0] );
     this.state = 'more';
   },
   showLess:   function(){
     for( var i=0; i<this.hidden.length; i++ ){
       Easy.addClassName( this.hidden[i], 'hidden' );
     }
     this.link.replaceChild( this.linkText[0], this.link.childNodes[0] );
     this.state = 'less';
   }
};




IN CONTROL 2009                                                             129
FUNDAMENTAL JAVASCRIPT




Collapsing Form with JS




IN CONTROL 2009           130
QUESTIONS?
WORKING
WITH LIBRARIES
FUNDAMENTAL JAVASCRIPT




    Popular Libraries
๏   jQuery (jquery.com)
๏   Prototype (prototypejs.org) & Scriptaculous (script.aculo.us)
๏   YUI (developer.yahoo.com/yui)
๏   Dojo (dojotoolkit.org)
๏   Spry (labs.adobe.com/technologies/spry)
๏   MooTools (mootools.net)
๏   MochiKit (mochikit.com)




    IN CONTROL 2009                                                 133
FUNDAMENTAL JAVASCRIPT




    Popular Libraries
๏   jQuery - fast & easy to write, selector-based
๏   Prototype & Scriptaculous - powerful, Ruby-like
๏   YUI - powerful, backed by Yahoo!
๏   Dojo - powerful, backed by IBM
๏   Spry - supported in Dreamweaver, backed by Adobe
๏   MochiKit - powerful, Python-like




    IN CONTROL 2009                                    134
FUNDAMENTAL JAVASCRIPT




    Popular Libraries
๏   jQuery - fast & easy to write, selector-based
๏   Prototype & Scriptaculous - powerful, Ruby-like
๏   YUI - powerful, backed by Yahoo!




    IN CONTROL 2009                                   134
FUNDAMENTAL JAVASCRIPT




    Getters 2.0
๏   jQuery:
    ‣ $(selector)

    ‣ $(selector).attr(attribute)

๏   Prototype:
    ‣ $(id)       or $$(selector)
    ‣ $$(selector).readAttribute(attribute)

๏   YUI:
    ‣ YAHOO.util.Dom.get(id)        or YAHOO.util.Selector.query(selector)
    ‣ YAHOO.util.Dom.getAttribute(element,         attribute)

    IN CONTROL 2009                                                          135
FUNDAMENTAL JAVASCRIPT




    Setters 2.0
๏   jQuery:
    ‣ $(x).text(text)        or $(x).html(html) or $(x).append([el|text])
    ‣ $(x).attr([attr,       value|map])
๏   Prototype:
    ‣ $(x).insert([text|element]) // after by default

    ‣ $(x).writeAttribute([attr,        value|map])
๏   YUI:
    ‣ YAHOO.util.Dom.insertAfter(        [str|el], reference)
    ‣ YAHOO.util.Dom.addClass(el,        class)

    IN CONTROL 2009                                                         136
LET’S REVISIT
 OUR FIRST
  EXAMPLE
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]
Fundamental JavaScript [In Control 2009]

More Related Content

What's hot

Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesAnkit Rastogi
 
Paris Web - Javascript as a programming language
Paris Web - Javascript as a programming languageParis Web - Javascript as a programming language
Paris Web - Javascript as a programming languageMarco Cedaro
 
Introduction to web programming with JavaScript
Introduction to web programming with JavaScriptIntroduction to web programming with JavaScript
Introduction to web programming with JavaScriptT11 Sessions
 
JavaScript - From Birth To Closure
JavaScript - From Birth To ClosureJavaScript - From Birth To Closure
JavaScript - From Birth To ClosureRobert Nyman
 
Scalable JavaScript Design Patterns
Scalable JavaScript Design PatternsScalable JavaScript Design Patterns
Scalable JavaScript Design PatternsAddy Osmani
 
JavaScript 101
JavaScript 101JavaScript 101
JavaScript 101ygv2000
 
Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to JavascriptAmit Tyagi
 
JavaScript Library Overview
JavaScript Library OverviewJavaScript Library Overview
JavaScript Library Overviewjeresig
 
JavaScript guide 2020 Learn JavaScript
JavaScript guide 2020 Learn JavaScriptJavaScript guide 2020 Learn JavaScript
JavaScript guide 2020 Learn JavaScriptLaurence Svekis ✔
 
Javascript Module Patterns
Javascript Module PatternsJavascript Module Patterns
Javascript Module PatternsNicholas Jansma
 
How AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsHow AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsRan Mizrahi
 
Beginning Object-Oriented JavaScript
Beginning Object-Oriented JavaScriptBeginning Object-Oriented JavaScript
Beginning Object-Oriented JavaScriptStoyan Stefanov
 
Design patterns in java script, jquery, angularjs
Design patterns in java script, jquery, angularjsDesign patterns in java script, jquery, angularjs
Design patterns in java script, jquery, angularjsRavi Bhadauria
 

What's hot (20)

Ten useful JavaScript tips & best practices
Ten useful JavaScript tips & best practicesTen useful JavaScript tips & best practices
Ten useful JavaScript tips & best practices
 
Paris Web - Javascript as a programming language
Paris Web - Javascript as a programming languageParis Web - Javascript as a programming language
Paris Web - Javascript as a programming language
 
Introduction to web programming with JavaScript
Introduction to web programming with JavaScriptIntroduction to web programming with JavaScript
Introduction to web programming with JavaScript
 
JavaScript - From Birth To Closure
JavaScript - From Birth To ClosureJavaScript - From Birth To Closure
JavaScript - From Birth To Closure
 
Javascript Design Patterns
Javascript Design PatternsJavascript Design Patterns
Javascript Design Patterns
 
Scalable JavaScript Design Patterns
Scalable JavaScript Design PatternsScalable JavaScript Design Patterns
Scalable JavaScript Design Patterns
 
JavaScript 101
JavaScript 101JavaScript 101
JavaScript 101
 
Java script
Java scriptJava script
Java script
 
Java script
Java scriptJava script
Java script
 
Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to Javascript
 
Javascript
JavascriptJavascript
Javascript
 
JavaScript Library Overview
JavaScript Library OverviewJavaScript Library Overview
JavaScript Library Overview
 
JavaScript guide 2020 Learn JavaScript
JavaScript guide 2020 Learn JavaScriptJavaScript guide 2020 Learn JavaScript
JavaScript guide 2020 Learn JavaScript
 
Javascript
JavascriptJavascript
Javascript
 
Javascript Module Patterns
Javascript Module PatternsJavascript Module Patterns
Javascript Module Patterns
 
How AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsHow AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design Patterns
 
Beginning Object-Oriented JavaScript
Beginning Object-Oriented JavaScriptBeginning Object-Oriented JavaScript
Beginning Object-Oriented JavaScript
 
Java script -23jan2015
Java script -23jan2015Java script -23jan2015
Java script -23jan2015
 
Design patterns in java script, jquery, angularjs
Design patterns in java script, jquery, angularjsDesign patterns in java script, jquery, angularjs
Design patterns in java script, jquery, angularjs
 
Javascript
JavascriptJavascript
Javascript
 

Viewers also liked

She Looks Just Like Me 2017
She Looks Just Like Me 2017She Looks Just Like Me 2017
She Looks Just Like Me 2017Reem Alattas
 
Evolutionary Algorithms
Evolutionary AlgorithmsEvolutionary Algorithms
Evolutionary AlgorithmsReem Alattas
 
High Performance JavaScript - jQuery Conference SF Bay Area 2010
High Performance JavaScript - jQuery Conference SF Bay Area 2010High Performance JavaScript - jQuery Conference SF Bay Area 2010
High Performance JavaScript - jQuery Conference SF Bay Area 2010Nicholas Zakas
 
JavaScript Prototype and Module Pattern
JavaScript Prototype and Module PatternJavaScript Prototype and Module Pattern
JavaScript Prototype and Module PatternNarendra Sisodiya
 
JavaScript Functions
JavaScript Functions JavaScript Functions
JavaScript Functions Reem Alattas
 
High Performance JavaScript - WebDirections USA 2010
High Performance JavaScript - WebDirections USA 2010High Performance JavaScript - WebDirections USA 2010
High Performance JavaScript - WebDirections USA 2010Nicholas Zakas
 
JavaScript Conditional Statements
JavaScript Conditional StatementsJavaScript Conditional Statements
JavaScript Conditional StatementsMarlon Jamera
 
JavaScript Programming
JavaScript ProgrammingJavaScript Programming
JavaScript ProgrammingSehwan Noh
 

Viewers also liked (8)

She Looks Just Like Me 2017
She Looks Just Like Me 2017She Looks Just Like Me 2017
She Looks Just Like Me 2017
 
Evolutionary Algorithms
Evolutionary AlgorithmsEvolutionary Algorithms
Evolutionary Algorithms
 
High Performance JavaScript - jQuery Conference SF Bay Area 2010
High Performance JavaScript - jQuery Conference SF Bay Area 2010High Performance JavaScript - jQuery Conference SF Bay Area 2010
High Performance JavaScript - jQuery Conference SF Bay Area 2010
 
JavaScript Prototype and Module Pattern
JavaScript Prototype and Module PatternJavaScript Prototype and Module Pattern
JavaScript Prototype and Module Pattern
 
JavaScript Functions
JavaScript Functions JavaScript Functions
JavaScript Functions
 
High Performance JavaScript - WebDirections USA 2010
High Performance JavaScript - WebDirections USA 2010High Performance JavaScript - WebDirections USA 2010
High Performance JavaScript - WebDirections USA 2010
 
JavaScript Conditional Statements
JavaScript Conditional StatementsJavaScript Conditional Statements
JavaScript Conditional Statements
 
JavaScript Programming
JavaScript ProgrammingJavaScript Programming
JavaScript Programming
 

Similar to Fundamental JavaScript [In Control 2009]

Even Faster Web Sites at jQuery Conference '09
Even Faster Web Sites at jQuery Conference '09Even Faster Web Sites at jQuery Conference '09
Even Faster Web Sites at jQuery Conference '09Steve Souders
 
Client-side JavaScript Vulnerabilities
Client-side JavaScript VulnerabilitiesClient-side JavaScript Vulnerabilities
Client-side JavaScript VulnerabilitiesOry Segal
 
Optaros Surf Code Camp Lab 4
Optaros Surf Code Camp Lab 4Optaros Surf Code Camp Lab 4
Optaros Surf Code Camp Lab 4Jeff Potts
 
ActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group PresentationActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group Presentationipolevoy
 
Even Faster Web Sites at The Ajax Experience
Even Faster Web Sites at The Ajax ExperienceEven Faster Web Sites at The Ajax Experience
Even Faster Web Sites at The Ajax ExperienceSteve Souders
 
Javascript
JavascriptJavascript
JavascriptSushma M
 
eXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction TrainingeXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction TrainingHoat Le
 
Joomla Template Development
Joomla Template DevelopmentJoomla Template Development
Joomla Template DevelopmentLinda Coonen
 
Build and deploy Python Django project
Build and deploy Python Django projectBuild and deploy Python Django project
Build and deploy Python Django projectXiaoqi Zhao
 
Optimising Your Front End Workflow With Symfony, Twig, Bower and Gulp
Optimising Your Front End Workflow With Symfony, Twig, Bower and GulpOptimising Your Front End Workflow With Symfony, Twig, Bower and Gulp
Optimising Your Front End Workflow With Symfony, Twig, Bower and GulpMatthew Davis
 
Fronteers 20091105 (1)
Fronteers 20091105 (1)Fronteers 20091105 (1)
Fronteers 20091105 (1)guestbf04d7
 
Mixing Objective-C, Swift and Japan
Mixing Objective-C, Swift and JapanMixing Objective-C, Swift and Japan
Mixing Objective-C, Swift and JapanTingTzu Chang
 
Best Practices for Front-End Django Developers
Best Practices for Front-End Django DevelopersBest Practices for Front-End Django Developers
Best Practices for Front-End Django DevelopersChristine Cheung
 
Introduction to Web Programming with Perl
Introduction to Web Programming with PerlIntroduction to Web Programming with Perl
Introduction to Web Programming with PerlDave Cross
 
Document Object Model
Document Object ModelDocument Object Model
Document Object Modelyht4ever
 

Similar to Fundamental JavaScript [In Control 2009] (20)

Even Faster Web Sites at jQuery Conference '09
Even Faster Web Sites at jQuery Conference '09Even Faster Web Sites at jQuery Conference '09
Even Faster Web Sites at jQuery Conference '09
 
Client-side JavaScript Vulnerabilities
Client-side JavaScript VulnerabilitiesClient-side JavaScript Vulnerabilities
Client-side JavaScript Vulnerabilities
 
Optaros Surf Code Camp Lab 4
Optaros Surf Code Camp Lab 4Optaros Surf Code Camp Lab 4
Optaros Surf Code Camp Lab 4
 
ActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group PresentationActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group Presentation
 
Even Faster Web Sites at The Ajax Experience
Even Faster Web Sites at The Ajax ExperienceEven Faster Web Sites at The Ajax Experience
Even Faster Web Sites at The Ajax Experience
 
Javascript
JavascriptJavascript
Javascript
 
eXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction TrainingeXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction Training
 
Spring and DWR
Spring and DWRSpring and DWR
Spring and DWR
 
Joomla Template Development
Joomla Template DevelopmentJoomla Template Development
Joomla Template Development
 
HTML 5
HTML 5HTML 5
HTML 5
 
Build and deploy Python Django project
Build and deploy Python Django projectBuild and deploy Python Django project
Build and deploy Python Django project
 
Optimising Your Front End Workflow With Symfony, Twig, Bower and Gulp
Optimising Your Front End Workflow With Symfony, Twig, Bower and GulpOptimising Your Front End Workflow With Symfony, Twig, Bower and Gulp
Optimising Your Front End Workflow With Symfony, Twig, Bower and Gulp
 
Fronteers 20091105 (1)
Fronteers 20091105 (1)Fronteers 20091105 (1)
Fronteers 20091105 (1)
 
Mixing Objective-C, Swift and Japan
Mixing Objective-C, Swift and JapanMixing Objective-C, Swift and Japan
Mixing Objective-C, Swift and Japan
 
Best Practices for Front-End Django Developers
Best Practices for Front-End Django DevelopersBest Practices for Front-End Django Developers
Best Practices for Front-End Django Developers
 
Looking into HTML5
Looking into HTML5Looking into HTML5
Looking into HTML5
 
EPiServer Web Parts
EPiServer Web PartsEPiServer Web Parts
EPiServer Web Parts
 
Introduction to Web Programming with Perl
Introduction to Web Programming with PerlIntroduction to Web Programming with Perl
Introduction to Web Programming with Perl
 
Document Object Model
Document Object ModelDocument Object Model
Document Object Model
 
M02 un04 p04
M02 un04 p04M02 un04 p04
M02 un04 p04
 

More from Aaron Gustafson

Delivering Critical Information and Services [JavaScript & Friends 2021]
Delivering Critical Information and Services [JavaScript & Friends 2021]Delivering Critical Information and Services [JavaScript & Friends 2021]
Delivering Critical Information and Services [JavaScript & Friends 2021]Aaron Gustafson
 
Adapting to Reality [Guest Lecture, March 2021]
Adapting to Reality [Guest Lecture, March 2021]Adapting to Reality [Guest Lecture, March 2021]
Adapting to Reality [Guest Lecture, March 2021]Aaron Gustafson
 
Designing the Conversation [Beyond Tellerrand 2019]
Designing the Conversation [Beyond Tellerrand 2019]Designing the Conversation [Beyond Tellerrand 2019]
Designing the Conversation [Beyond Tellerrand 2019]Aaron Gustafson
 
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]Aaron Gustafson
 
Progressive Web Apps: Where Do I Begin?
Progressive Web Apps: Where Do I Begin?Progressive Web Apps: Where Do I Begin?
Progressive Web Apps: Where Do I Begin?Aaron Gustafson
 
Media in the Age of PWAs [ImageCon 2019]
Media in the Age of PWAs [ImageCon 2019]Media in the Age of PWAs [ImageCon 2019]
Media in the Age of PWAs [ImageCon 2019]Aaron Gustafson
 
Adapting to Reality [Starbucks Lunch & Learn]
Adapting to Reality [Starbucks Lunch & Learn]Adapting to Reality [Starbucks Lunch & Learn]
Adapting to Reality [Starbucks Lunch & Learn]Aaron Gustafson
 
Conversational Semantics for the Web [CascadiaJS 2018]
Conversational Semantics for the Web [CascadiaJS 2018]Conversational Semantics for the Web [CascadiaJS 2018]
Conversational Semantics for the Web [CascadiaJS 2018]Aaron Gustafson
 
Better Performance === Greater Accessibility [Inclusive Design 24 2018]
Better Performance === Greater Accessibility [Inclusive Design 24 2018]Better Performance === Greater Accessibility [Inclusive Design 24 2018]
Better Performance === Greater Accessibility [Inclusive Design 24 2018]Aaron Gustafson
 
PWA: Where Do I Begin? [Microsoft Ignite 2018]
PWA: Where Do I Begin? [Microsoft Ignite 2018]PWA: Where Do I Begin? [Microsoft Ignite 2018]
PWA: Where Do I Begin? [Microsoft Ignite 2018]Aaron Gustafson
 
Designing the Conversation [Concatenate 2018]
Designing the Conversation [Concatenate 2018]Designing the Conversation [Concatenate 2018]
Designing the Conversation [Concatenate 2018]Aaron Gustafson
 
Designing the Conversation [Accessibility DC 2018]
Designing the Conversation [Accessibility DC 2018]Designing the Conversation [Accessibility DC 2018]
Designing the Conversation [Accessibility DC 2018]Aaron Gustafson
 
Performance as User Experience [AEADC 2018]
Performance as User Experience [AEADC 2018]Performance as User Experience [AEADC 2018]
Performance as User Experience [AEADC 2018]Aaron Gustafson
 
The Web Should Just Work for Everyone
The Web Should Just Work for EveryoneThe Web Should Just Work for Everyone
The Web Should Just Work for EveryoneAaron Gustafson
 
Performance as User Experience [AEA SEA 2018]
Performance as User Experience [AEA SEA 2018]Performance as User Experience [AEA SEA 2018]
Performance as User Experience [AEA SEA 2018]Aaron Gustafson
 
Performance as User Experience [An Event Apart Denver 2017]
Performance as User Experience [An Event Apart Denver 2017]Performance as User Experience [An Event Apart Denver 2017]
Performance as User Experience [An Event Apart Denver 2017]Aaron Gustafson
 
Advanced Design Methods 1, Day 2
Advanced Design Methods 1, Day 2Advanced Design Methods 1, Day 2
Advanced Design Methods 1, Day 2Aaron Gustafson
 
Advanced Design Methods 1, Day 1
Advanced Design Methods 1, Day 1Advanced Design Methods 1, Day 1
Advanced Design Methods 1, Day 1Aaron Gustafson
 
Designing the Conversation [Paris Web 2017]
Designing the Conversation [Paris Web 2017]Designing the Conversation [Paris Web 2017]
Designing the Conversation [Paris Web 2017]Aaron Gustafson
 
Exploring Adaptive Interfaces [Generate 2017]
Exploring Adaptive Interfaces [Generate 2017]Exploring Adaptive Interfaces [Generate 2017]
Exploring Adaptive Interfaces [Generate 2017]Aaron Gustafson
 

More from Aaron Gustafson (20)

Delivering Critical Information and Services [JavaScript & Friends 2021]
Delivering Critical Information and Services [JavaScript & Friends 2021]Delivering Critical Information and Services [JavaScript & Friends 2021]
Delivering Critical Information and Services [JavaScript & Friends 2021]
 
Adapting to Reality [Guest Lecture, March 2021]
Adapting to Reality [Guest Lecture, March 2021]Adapting to Reality [Guest Lecture, March 2021]
Adapting to Reality [Guest Lecture, March 2021]
 
Designing the Conversation [Beyond Tellerrand 2019]
Designing the Conversation [Beyond Tellerrand 2019]Designing the Conversation [Beyond Tellerrand 2019]
Designing the Conversation [Beyond Tellerrand 2019]
 
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]
Getting Started with Progressive Web Apps [Beyond Tellerrand 2019]
 
Progressive Web Apps: Where Do I Begin?
Progressive Web Apps: Where Do I Begin?Progressive Web Apps: Where Do I Begin?
Progressive Web Apps: Where Do I Begin?
 
Media in the Age of PWAs [ImageCon 2019]
Media in the Age of PWAs [ImageCon 2019]Media in the Age of PWAs [ImageCon 2019]
Media in the Age of PWAs [ImageCon 2019]
 
Adapting to Reality [Starbucks Lunch & Learn]
Adapting to Reality [Starbucks Lunch & Learn]Adapting to Reality [Starbucks Lunch & Learn]
Adapting to Reality [Starbucks Lunch & Learn]
 
Conversational Semantics for the Web [CascadiaJS 2018]
Conversational Semantics for the Web [CascadiaJS 2018]Conversational Semantics for the Web [CascadiaJS 2018]
Conversational Semantics for the Web [CascadiaJS 2018]
 
Better Performance === Greater Accessibility [Inclusive Design 24 2018]
Better Performance === Greater Accessibility [Inclusive Design 24 2018]Better Performance === Greater Accessibility [Inclusive Design 24 2018]
Better Performance === Greater Accessibility [Inclusive Design 24 2018]
 
PWA: Where Do I Begin? [Microsoft Ignite 2018]
PWA: Where Do I Begin? [Microsoft Ignite 2018]PWA: Where Do I Begin? [Microsoft Ignite 2018]
PWA: Where Do I Begin? [Microsoft Ignite 2018]
 
Designing the Conversation [Concatenate 2018]
Designing the Conversation [Concatenate 2018]Designing the Conversation [Concatenate 2018]
Designing the Conversation [Concatenate 2018]
 
Designing the Conversation [Accessibility DC 2018]
Designing the Conversation [Accessibility DC 2018]Designing the Conversation [Accessibility DC 2018]
Designing the Conversation [Accessibility DC 2018]
 
Performance as User Experience [AEADC 2018]
Performance as User Experience [AEADC 2018]Performance as User Experience [AEADC 2018]
Performance as User Experience [AEADC 2018]
 
The Web Should Just Work for Everyone
The Web Should Just Work for EveryoneThe Web Should Just Work for Everyone
The Web Should Just Work for Everyone
 
Performance as User Experience [AEA SEA 2018]
Performance as User Experience [AEA SEA 2018]Performance as User Experience [AEA SEA 2018]
Performance as User Experience [AEA SEA 2018]
 
Performance as User Experience [An Event Apart Denver 2017]
Performance as User Experience [An Event Apart Denver 2017]Performance as User Experience [An Event Apart Denver 2017]
Performance as User Experience [An Event Apart Denver 2017]
 
Advanced Design Methods 1, Day 2
Advanced Design Methods 1, Day 2Advanced Design Methods 1, Day 2
Advanced Design Methods 1, Day 2
 
Advanced Design Methods 1, Day 1
Advanced Design Methods 1, Day 1Advanced Design Methods 1, Day 1
Advanced Design Methods 1, Day 1
 
Designing the Conversation [Paris Web 2017]
Designing the Conversation [Paris Web 2017]Designing the Conversation [Paris Web 2017]
Designing the Conversation [Paris Web 2017]
 
Exploring Adaptive Interfaces [Generate 2017]
Exploring Adaptive Interfaces [Generate 2017]Exploring Adaptive Interfaces [Generate 2017]
Exploring Adaptive Interfaces [Generate 2017]
 

Recently uploaded

The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DaySri Ambati
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Fact vs. Fiction: Autodetecting Hallucinations in LLMs
Fact vs. Fiction: Autodetecting Hallucinations in LLMsFact vs. Fiction: Autodetecting Hallucinations in LLMs
Fact vs. Fiction: Autodetecting Hallucinations in LLMsZilliz
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Visualising and forecasting stocks using Dash
Visualising and forecasting stocks using DashVisualising and forecasting stocks using Dash
Visualising and forecasting stocks using Dashnarutouzumaki53779
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 

Recently uploaded (20)

The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Fact vs. Fiction: Autodetecting Hallucinations in LLMs
Fact vs. Fiction: Autodetecting Hallucinations in LLMsFact vs. Fiction: Autodetecting Hallucinations in LLMs
Fact vs. Fiction: Autodetecting Hallucinations in LLMs
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Visualising and forecasting stocks using Dash
Visualising and forecasting stocks using DashVisualising and forecasting stocks using Dash
Visualising and forecasting stocks using Dash
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 

Fundamental JavaScript [In Control 2009]

  • 1. FUNDAMENTAL JAVASCRIPT Aaron Gustafson
  • 2. DOM SCRIPTING (a.k.a. Document Manipulation via JavaScript)
  • 3. FUNDAMENTAL JAVASCRIPT DHTML ๏ …was all about animation and interactivity ๏ ...was invented by marketing wonks ๏ ...is really three technologies: JavaScript, CSS & HTML ๏ ...carried a lot of baggage: browser-specific, forked code, screen only & non-standard markup ๏ ...was a maintenance nightmare IN CONTROL 2009 3
  • 4. FUNDAMENTAL JAVASCRIPT DOM Scripting ๏ …is the web standards approach to manipulating documents ๏ ...only requires a scripting language and valid markup ๏ ...is browser independent ๏ ...makes use of progressive enhancement ๏ ...just makes sense IN CONTROL 2009 4
  • 5. FUNDAMENTAL JAVASCRIPT The document <!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Strict//ENquot; quot;http://www.w3.org/TR/XHTML1/DTD/XHTML1-strict.dtdquot;> <html xmlns=quot;http://www.w3.org/1999/XHTMLquot; xml:lang=quot;enquot; lang=quot;enquot;> <head> <title>Page Title</title> <meta http-equiv=quot;content-typequot; content=quot;text/html; charset=utf-8quot; /> <meta http-equiv=quot;Content-Languagequot; content=quot;en-usquot; /> </head> <body> <h1>This is a heading</h1> <p>This is a paragraph with a <a href=quot;http://easy-reader.netquot;>link</a></p> <ul> <li>a list item</li> <li>another list item</li> <li>a third list item</li> </ul> </body> </html> IN CONTROL 2009 5
  • 6. FUNDAMENTAL JAVASCRIPT The DOM html IN CONTROL 2009 6
  • 7. FUNDAMENTAL JAVASCRIPT The DOM html head body title meta meta h1 p ul a li li li IN CONTROL 2009 6
  • 8. FUNDAMENTAL JAVASCRIPT The DOM p this is a paragraph a . of text with a href=quot;http://easy-reader.netquot; link IN CONTROL 2009 6
  • 9. FUNDAMENTAL JAVASCRIPT CSS getter { setter } IN CONTROL 2009 7
  • 10. FUNDAMENTAL JAVASCRIPT CSS p { color: red; } IN CONTROL 2009 7
  • 11. FUNDAMENTAL JAVASCRIPT CSS #footer { font-size: small; } IN CONTROL 2009 7
  • 13. FUNDAMENTAL JAVASCRIPT DOM Scripting var myNode = document.getter(); IN CONTROL 2009 8
  • 14. FUNDAMENTAL JAVASCRIPT DOM Scripting myNode.setter(); IN CONTROL 2009 8
  • 15. FUNDAMENTAL JAVASCRIPT Getters ๏ document.getElementById( ID ); ๏ document.getElementsByTagName( tagName ); ๏ element.getAttribute( attributeName ); IN CONTROL 2009 9
  • 16. FUNDAMENTAL JAVASCRIPT Using getters ๏ var content = document.getElementById( 'content' ); ๏ var abbrs = document.getElementsByTagName( 'abbr' ); ๏ var title = abbrs[0].getAttribute( 'title' ); IN CONTROL 2009 10
  • 17. FUNDAMENTAL JAVASCRIPT Language comparison ๏ English Get the element with the ID “content”. ๏ CSS #content { } ๏ DOM document.getElementById( 'content' ) IN CONTROL 2009 11
  • 18. FUNDAMENTAL JAVASCRIPT Language comparison ๏ English Get all the paragraphs in a document. ๏ CSS p { } ๏ DOM document.getElementsByTagName( 'p' ); IN CONTROL 2009 12
  • 19. FUNDAMENTAL JAVASCRIPT Language comparison ๏ English Get all the paragraphs within the element with the ID “content”. ๏ CSS #content p { } ๏ DOM document.getElementById( 'content' ) .getElementsByTagName( 'p' ); IN CONTROL 2009 13
  • 20. FUNDAMENTAL JAVASCRIPT Content generation ๏ Bad: ‣ document.write(); ‣ innerHTML IN CONTROL 2009 14
  • 21. FUNDAMENTAL JAVASCRIPT Content generation ๏ Good: ‣ document.createElement( tagName ); ‣ document.createTextNode( text ); ‣ element.setAttribute( name, value ); IN CONTROL 2009 15
  • 22. FUNDAMENTAL JAVASCRIPT Generation in action ๏ var abbr = document.createElement( 'abbr' ); ๏ var text = document.createTextNode( 'TN' ); ๏ abbr.setAttribute( 'title', 'Tennessee' ); IN CONTROL 2009 16
  • 23. FUNDAMENTAL JAVASCRIPT Adding to the DOM ๏ element.appendChild( newNode ); ๏ element.insertBefore( newNode, targetNode ); IN CONTROL 2009 17
  • 24. FUNDAMENTAL JAVASCRIPT Adding to the DOM var abbr = document.createElement( 'abbr' ); var text = document.createTextNode( 'TN' ); abbr.setAttribute( 'title', 'Tennessee' ); abbr.appendChild( text ); var p = document.getElementsByTagName( 'p' )[0]; p.appendChild( abbr ); IN CONTROL 2009 18
  • 25. TIME FOR AN EXAMPLE
  • 26. FUNDAMENTAL JAVASCRIPT The idea Make use of the cite attribute in blockquotes. IN CONTROL 2009 20
  • 27. FUNDAMENTAL JAVASCRIPT The document <!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Strict//ENquot; quot;http://www.w3.org/TR/XHTML1/DTD/XHTML1-strict.dtdquot;> <html xmlns=quot;http://www.w3.org/1999/XHTMLquot; xml:lang=quot;enquot; lang=quot;enquot;> <head> <title>Example 1</title> <meta http-equiv=quot;content-typequot; content=quot;text/html; charset=utf-8quot; /> <meta http-equiv=quot;Content-Languagequot; content=quot;en-usquot; /> </head> <body> <blockquote cite=quot;http://en.wikipedia.org/wiki/Progressive_Enhancementquot;> <p>Progressive Enhancement, as a label for a strategy for Web design, was coined by Steven Champeon in a series of articles and presentations for Webmonkey and the SxSW Interactive conference.</p> </blockquote> </body> </html> IN CONTROL 2009 21
  • 28. FUNDAMENTAL JAVASCRIPT The page Progressive Enhancement, as a label for a strategy for Web design, was coined by Steven Champeon in a series of articles and presentations for Webmonkey and the SxSW Interactive conference. IN CONTROL 2009 22
  • 29. FUNDAMENTAL JAVASCRIPT The document <!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Strict//ENquot; quot;http://www.w3.org/TR/XHTML1/DTD/XHTML1-strict.dtdquot;> <html xmlns=quot;http://www.w3.org/1999/XHTMLquot; xml:lang=quot;enquot; lang=quot;enquot;> <head> <title>Example 1</title> <meta http-equiv=quot;content-typequot; content=quot;text/html; charset=utf-8quot; /> <meta http-equiv=quot;Content-Languagequot; content=quot;en-usquot; /> </head> <body> <blockquote cite=quot;http://en.wikipedia.org/wiki/Progressive_Enhancementquot;> <p>Progressive Enhancement, as a label for a strategy for Web design, was coined by Steven Champeon in a series of articles and presentations for Webmonkey and the SxSW Interactive conference.</p> </blockquote> </body> </html> IN CONTROL 2009 23
  • 30. FUNDAMENTAL JAVASCRIPT The idea 1. Find all the blockquotes in a document 2. Get the value of the cite attribute 3. Create a new anchor element node 4. Set the href attribute of the anchor 5. Create a new text node with the word “source” 6. Insert the text into the anchor 7. Insert the anchor into the blockquote. IN CONTROL 2009 24
  • 31. FUNDAMENTAL JAVASCRIPT The idea 1. Find all the blockquotes in a document 2. Get the value of the cite attribute 3. Create a new anchor element node 4. Set the href attribute of the anchor 5. Create a new text node with the word “source” 6. Insert the text into the anchor 7. Insert the anchor into the blockquote. IN CONTROL 2009 25
  • 32. FUNDAMENTAL JAVASCRIPT The idea 1. Find all the blockquotes in a document getElementsByTagName 2. Get the value of the cite attribute 3. Create a new anchor element node 4. Set the href attribute of the anchor 5. Create a new text node with the word “source” 6. Insert the text into the anchor 7. Insert the anchor into the blockquote. IN CONTROL 2009 25
  • 33. FUNDAMENTAL JAVASCRIPT The idea 1. Find all the blockquotes in a document getElementsByTagName 2. Get the value of the cite attribute getAttribute 3. Create a new anchor element node 4. Set the href attribute of the anchor 5. Create a new text node with the word “source” 6. Insert the text into the anchor 7. Insert the anchor into the blockquote. IN CONTROL 2009 25
  • 34. FUNDAMENTAL JAVASCRIPT The idea 1. Find all the blockquotes in a document getElementsByTagName 2. Get the value of the cite attribute getAttribute 3. Create a new anchor element node createElement 4. Set the href attribute of the anchor 5. Create a new text node with the word “source” 6. Insert the text into the anchor 7. Insert the anchor into the blockquote. IN CONTROL 2009 25
  • 35. FUNDAMENTAL JAVASCRIPT The idea 1. Find all the blockquotes in a document getElementsByTagName 2. Get the value of the cite attribute getAttribute 3. Create a new anchor element node createElement 4. Set the href attribute of the anchor setAttribute 5. Create a new text node with the word “source” 6. Insert the text into the anchor 7. Insert the anchor into the blockquote. IN CONTROL 2009 25
  • 36. FUNDAMENTAL JAVASCRIPT The idea 1. Find all the blockquotes in a document getElementsByTagName 2. Get the value of the cite attribute getAttribute 3. Create a new anchor element node createElement 4. Set the href attribute of the anchor setAttribute 5. Create a new text node with the word “source” createTextNode 6. Insert the text into the anchor 7. Insert the anchor into the blockquote. IN CONTROL 2009 25
  • 37. FUNDAMENTAL JAVASCRIPT The idea 1. Find all the blockquotes in a document getElementsByTagName 2. Get the value of the cite attribute getAttribute 3. Create a new anchor element node createElement 4. Set the href attribute of the anchor setAttribute 5. Create a new text node with the word “source” createTextNode 6. Insert the text into the anchor appendChild 7. Insert the anchor into the blockquote. IN CONTROL 2009 25
  • 38. FUNDAMENTAL JAVASCRIPT The idea 1. Find all the blockquotes in a document getElementsByTagName 2. Get the value of the cite attribute getAttribute 3. Create a new anchor element node createElement 4. Set the href attribute of the anchor setAttribute 5. Create a new text node with the word “source” createTextNode 6. Insert the text into the anchor appendChild 7. Insert the anchor into the blockquote. appendChild IN CONTROL 2009 25
  • 39. FUNDAMENTAL JAVASCRIPT The code var quotes = document.getElementsByTagName( 'blockquote' ); for( var i=0; i < quotes.length; i++ ){ var source = quotes[i].getAttribute( 'cite' ); if( source ){ var link = document.createElement( 'a' ); link.setAttribute( 'href', source ); var text = document.createTextNode( 'source' ); link.appendChild( text ); quotes[i].appendChild( link ); } } IN CONTROL 2009 26
  • 40. FUNDAMENTAL JAVASCRIPT The code var quotes = document.getElementsByTagName( 'blockquote' ); for( var i=0; i < quotes.length; i++ ){ var source = quotes[i].getAttribute( 'cite' ); if( source ){ var link = document.createElement( 'a' ); link.setAttribute( 'href', source ); var text = document.createTextNode( 'source' ); link.appendChild( text ); var para = document.createElement( 'p' ); para.className = 'attribution'; para.appendChild( link ); quotes[i].appendChild( para ); } } IN CONTROL 2009 27
  • 41. FUNDAMENTAL JAVASCRIPT The code function sourceQuotes(){ var quotes = document.getElementsByTagName( 'blockquote' ); for( var i=0; i < quotes.length; i++ ){ var source = quotes[i].getAttribute( 'cite' ); if( source ){ var link = document.createElement( 'a' ); link.setAttribute( 'href', source ); var text = document.createTextNode( 'source' ); link.appendChild( text ); var para = document.createElement( 'p' ); para.className = 'attribution'; para.appendChild( link ); quotes[i].appendChild( para ); } } } window.onload = sourceQuotes; IN CONTROL 2009 28
  • 42. FUNDAMENTAL JAVASCRIPT The result Progressive Enhancement, as a label for a strategy for Web design, was coined by Steven Champeon in a series of articles and presentations for Webmonkey and the SxSW Interactive conference. IN CONTROL 2009 29
  • 43. FUNDAMENTAL JAVASCRIPT The result Progressive Enhancement, as a label for a strategy for Web design, was coined by Steven Champeon in a series of articles and presentations for Webmonkey and the SxSW Interactive conference. source IN CONTROL 2009 30
  • 46. PROGRESSIVE ENHANCEMENT VS. GRACEFUL DEGRADATION
  • 48. FUNDAMENTAL JAVASCRIPT 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 IN CONTROL 2009 34
  • 49. WEB STANDARDS: FUELING INNOVATION WEB BUILDER 2.0 35
  • 50. WEB STANDARDS: FUELING INNOVATION WEB BUILDER 2.0 35
  • 53. CONTENT IS WHY WE BUILD WEBSITES AND SHOULD BE OUR CENTRAL FOCUS
  • 54. WEB STANDARDS: FUELING INNOVATION WEB BUILDER 2.0 38
  • 55. WEB STANDARDS: FUELING INNOVATION WEB BUILDER 2.0 39
  • 56. HOW DOES IT WORK?
  • 57. WEB STANDARDS: FUELING INNOVATION WEB BUILDER 2.0 41
  • 58. FUNDAMENTAL JAVASCRIPT Flavorful nugget of content (semantic goodness) IN CONTROL 2009 42
  • 59. FUNDAMENTAL JAVASCRIPT Rich, indulgent design IN CONTROL 2009 43
  • 60. FUNDAMENTAL JAVASCRIPT Sweet interactivity (keeps it from melting in your hands) IN CONTROL 2009 44
  • 61. WEB STANDARDS: FUELING INNOVATION WEB BUILDER 2.0 45
  • 63. WEB STANDARDS: FUELING INNOVATION WEB BUILDER 2.0 47
  • 64. WEB STANDARDS: FUELING INNOVATION stuffandnonsense.co.uk/archives/web_standards_trifle.html WEB BUILDER 2.0 48
  • 65. WHY A PEANUT M&M?
  • 66. FUNDAMENTAL JAVASCRIPT The peanut is good for ๏ diabetics IN CONTROL 2009 50
  • 67. FUNDAMENTAL JAVASCRIPT The peanut is good for ๏ diabetics ๏ search engine spiders IN CONTROL 2009 50
  • 68. FUNDAMENTAL JAVASCRIPT The peanut is good for ๏ diabetics ๏ search engine spiders ๏ mobile devices IN CONTROL 2009 50
  • 69. IT’S A BASIC LEVEL OF SUPPORT
  • 70. FUNDAMENTAL JAVASCRIPT The chocolate is good for IN CONTROL 2009 52
  • 71. FUNDAMENTAL JAVASCRIPT The chocolate is good for ๏ diabetics IN CONTROL 2009 52
  • 72. FUNDAMENTAL JAVASCRIPT Rich, chocolaty goodness ๏ some browsers only handle a certain level of CSS ๏ some companies turn off JavaScript IN CONTROL 2009 52
  • 73. IT CAN BE BEAUTIFUL (and progressive)
  • 74. FUNDAMENTAL JAVASCRIPT The candy coating IN CONTROL 2009 54
  • 75. FUNDAMENTAL JAVASCRIPT The candy coating ๏ JavaScript can turn a website into an experience IN CONTROL 2009 54
  • 76. FUNDAMENTAL JAVASCRIPT The candy coating ๏ JavaScript can turn a website into an experience ๏ we can deliver our scripts a la carte IN CONTROL 2009 54
  • 79. FUNDAMENTAL JAVASCRIPT A long time ago, in a cubicle far, far away... Dear George Lucas, please don’t sue me. Kthxbye. IN CONTROL 2009 57
  • 80. FUNDAMENTAL JAVASCRIPT A long time ago, in a cubicle far, far away... Dear George Lucas, please don’t sue me. Kthxbye. IN CONTROL 2009 57
  • 83. PROGRESSIVE ENHANCEMENT REMINDS US TO FOCUS ON THE CONTENT
  • 84. FUNDAMENTAL JAVASCRIPT Back to basics IN CONTROL 2009 60
  • 85. FUNDAMENTAL JAVASCRIPT Back to basics XHTML + HTTP IN CONTROL 2009 60
  • 86. FUNDAMENTAL JAVASCRIPT Back to basics solid foundation IN CONTROL 2009 60
  • 87. FUNDAMENTAL JAVASCRIPT ALL CODE NEEDED TO UNDERSTAND AND USE A SITE SHOULD EXIST BEFORE ANY SCRIPTS RUN IN CONTROL 2009 61
  • 88. FUNDAMENTAL JAVASCRIPT PERIOD. IN CONTROL 2009 61
  • 92. FUNDAMENTAL JAVASCRIPT Without JavaScript Doh! IN CONTROL 2009 63
  • 93. FUNDAMENTAL JAVASCRIPT And looking at the IN CONTROL 2009 64
  • 94. FUNDAMENTAL JAVASCRIPT And looking at the Ug h ! IN CONTROL 2009 64
  • 98. ENTER UNOBTRUSIVE JAVASCRIPT ( ) the cornerstone of Progressive Enhancement with JavaScript
  • 99. FUNDAMENTAL JAVASCRIPT Don’t do this <a href=quot;javascript:someFunction();quot;>some text</a> or <a href=quot;javascript:void(null);quot; onclick=quot;someFunction();quot;>some text</a> or <a href=quot;#quot; onclick=quot;someFunction();quot;>some text</a> IN CONTROL 2009 67
  • 100. FUNDAMENTAL JAVASCRIPT An improvement, but still... <a href=quot;http://offsite.comquot; onclick=quot;newWin( this.href ); return false;quot;> some text</a> IN CONTROL 2009 68
  • 101. FUNDAMENTAL JAVASCRIPT Getting warmer... window.onload = handleExternalLinks; function handleExternalLinks(){ var server = document.location.hostname; var anchors = document.getElementsByTagName(quot;aquot;); var i, href; for( i=0; i < anchors.length; i++ ){ href = anchors[i].href; if( href.indexOf(quot;http://quot; + server) == -1 && href.indexOf(quot;https://quot; + server) == -1 ){ // HREF is not a file on my server anchors[i].onclick = function(){ newWin( this.href ); }; } } } IN CONTROL 2009 69
  • 102. FUNDAMENTAL JAVASCRIPT Getting warmer... window.onload = handleExternalLinks; function handleExternalLinks(){ var server = document.location.hostname; var anchors = document.getElementsByTagName(quot;aquot;); var i, href; for( i=0; i < anchors.length; i++ ){ href = anchors[i].href; if( href.indexOf(quot;http://quot; + server) == -1 && href.indexOf(quot;https://quot; + server) == -1 ){ // HREF is not a file on my server anchors[i].onclick = function(){ newWin( this.href ); }; } } } IN CONTROL 2009 69
  • 103. FUNDAMENTAL JAVASCRIPT Getting warmer... window.onload = handleExternalLinks; function handleExternalLinks(){ var server = document.location.hostname; var anchors = document.getElementsByTagName(quot;aquot;); var i, href; for( i=0; i < anchors.length; i++ ){ href = anchors[i].href; if( href.indexOf(quot;http://quot; + server) == -1 && href.indexOf(quot;https://quot; + server) == -1 ){ // HREF is not a file on my server anchors[i].onclick = function(){ newWin( this.href ); }; } } } IN CONTROL 2009 69
  • 104. FUNDAMENTAL JAVASCRIPT Getting warmer... window.onload = handleExternalLinks; function handleExternalLinks(){ var server = document.location.hostname; var anchors = document.getElementsByTagName(quot;aquot;); var i, href; for( i=0; i < anchors.length; i++ ){ href = anchors[i].href; if( href.indexOf(quot;http://quot; + server) == -1 && href.indexOf(quot;https://quot; + server) == -1 ){ // HREF is not a file on my server anchors[i].onclick = function(){ newWin( this.href ); }; } } } IN CONTROL 2009 69
  • 105. FUNDAMENTAL JAVASCRIPT Getting warmer... window.onload = handleExternalLinks; function handleExternalLinks(){ var server = document.location.hostname; var anchors = document.getElementsByTagName(quot;aquot;); var i, href; for( i=0; i < anchors.length; i++ ){ href = anchors[i].href; if( href.indexOf(quot;http://quot; + server) == -1 && href.indexOf(quot;https://quot; + server) == -1 ){ // HREF is not a file on my server anchors[i].onclick = function(){ newWin( this.href ); }; } } } IN CONTROL 2009 69
  • 106. FUNDAMENTAL JAVASCRIPT Getting warmer... window.onload = handleExternalLinks; function handleExternalLinks(){ var server = document.location.hostname; var anchors = document.getElementsByTagName(quot;aquot;); var i, href; for( i=0; i < anchors.length; i++ ){ href = anchors[i].href; if( href.indexOf(quot;http://quot; + server) == -1 && href.indexOf(quot;https://quot; + server) == -1 ){ // HREF is not a file on my server anchors[i].onclick = function(){ newWin( this.href ); }; } } } IN CONTROL 2009 69
  • 107. FUNDAMENTAL JAVASCRIPT Getting warmer... window.onload = handleExternalLinks; function handleExternalLinks(){ var server = document.location.hostname; var anchors = document.getElementsByTagName(quot;aquot;); var i, href; for( i=0; i < anchors.length; i++ ){ href = anchors[i].href; if( href.indexOf(quot;http://quot; + server) == -1 && href.indexOf(quot;https://quot; + server) == -1 ){ // HREF is not a file on my server anchors[i].onclick = function(){ newWin( this.href ); }; } } } IN CONTROL 2009 69
  • 108. FUNDAMENTAL JAVASCRIPT Getting warmer... window.onload = handleExternalLinks; function handleExternalLinks(){ var server = document.location.hostname; var anchors = document.getElementsByTagName(quot;aquot;); var i, href; for( i=0; i < anchors.length; i++ ){ href = anchors[i].href; if( href.indexOf(quot;http://quot; + server) == -1 && href.indexOf(quot;https://quot; + server) == -1 ){ // HREF is not a file on my server anchors[i].onclick = function(){ newWin( this.href ); }; } } } IN CONTROL 2009 69
  • 109. FUNDAMENTAL JAVASCRIPT You’re hot 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 ); } } IN CONTROL 2009 70
  • 110. FUNDAMENTAL JAVASCRIPT You’re hot 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 ); } } IN CONTROL 2009 70
  • 111. FUNDAMENTAL JAVASCRIPT You’re hot 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 ); } } IN CONTROL 2009 70
  • 112. FUNDAMENTAL JAVASCRIPT You’re hot 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 ); } } IN CONTROL 2009 70
  • 113. FUNDAMENTAL JAVASCRIPT You’re hot 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 ); } } IN CONTROL 2009 70
  • 114. FUNDAMENTAL JAVASCRIPT You’re hot 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 ); } } IN CONTROL 2009 70
  • 115. WEB STANDARDS: FUELING INNOVATION WEB BUILDER 2.0 71
  • 116.
  • 117.
  • 118. JavaScript CSS
  • 119. FUNDAMENTAL JAVASCRIPT Remember stuff like this? <a href=quot;foo.htmlquot; style=quot;color:blue;quot; onmouseover=quot;this.style.color='red'quot; onmouseout=quot;this.style.color='blue'quot;>Foo</a> IN CONTROL 2009 73
  • 120. FUNDAMENTAL JAVASCRIPT Remember stuff like this? <a href=quot;foo.htmlquot; style=quot;color:blue;quot; onmouseover=quot;this.style.color='red'quot; onmouseout=quot;this.style.color='blue'quot;>Foo</a> Obvisouly, we should be doing this instead: a, a:link, a:visited { color: blue; } a:hover { color: red; } IN CONTROL 2009 73
  • 121. FUNDAMENTAL JAVASCRIPT Isn’t this the same? for( i=0; i<objects.length; i++){ objects[i].style.display = 'none'; } IN CONTROL 2009 74
  • 122. FUNDAMENTAL JAVASCRIPT Small improvement for( i=0; i<objects.length; i++){ objects[i].style.position = 'absolute'; objects[i].style.left = '-999em'; } IN CONTROL 2009 75
  • 123. FUNDAMENTAL JAVASCRIPT Separation CSS: .hidden { position: absolute; left: -999em; } JavaScript: for( i=0; i<objects.length; i++){ objects[i].addClassName( 'hidden' ); } IN CONTROL 2009 76
  • 124. FUNDAMENTAL JAVASCRIPT Maintenance options ๏ external style rules added to your 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 IN CONTROL 2009 77
  • 125. FUNDAMENTAL JAVASCRIPT Option 1: Add by hand At the end of your screen layout CSS file: /* =START WickedCool Script CSS (do not remove) */ .wicked { color: red; font: bold 4em/2 quot;Comic Sansquot;; } .cool { color: blue; font: bold 4em/2 quot;Comic Sansquot;; } /* =END WickedCool Script CSS */ IN CONTROL 2009 78
  • 126. FUNDAMENTAL JAVASCRIPT Option 2: Include by hand Added to the head of your document: <script type=quot;text/javascriptquot; src=quot;WickedCool.jsquot;></script> <link rel=quot;stylesheetquot; type=quot;text/cssquot; media=quot;screenquot; href=quot;WickedCool.cssquot; /> IN CONTROL 2009 79
  • 127. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include function FindPath( filename ){ var path = false; var scripts = document.getElementsByTagName( 'script' ); for( var i=0; i<scripts.length; i++ ){ if( scripts[i].getAttribute( 'src' ) && scripts[i].getAttribute( 'src' ) .indexOf( filename ) != -1 ){ path = scripts[i].getAttribute( 'src' ) .replace( new RegExp( filename ), '' ); break; } } return path; } IN CONTROL 2009 80
  • 128. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include function FindPath( filename ){ var path = false; var scripts = document.getElementsByTagName( 'script' ); for( var i=0; i<scripts.length; i++ ){ if( scripts[i].getAttribute( 'src' ) && scripts[i].getAttribute( 'src' ) .indexOf( filename ) != -1 ){ path = scripts[i].getAttribute( 'src' ) .replace( new RegExp( filename ), '' ); break; } } return path; } IN CONTROL 2009 80
  • 129. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include function FindPath( filename ){ var path = false; var scripts = document.getElementsByTagName( 'script' ); for( var i=0; i<scripts.length; i++ ){ if( scripts[i].getAttribute( 'src' ) && scripts[i].getAttribute( 'src' ) .indexOf( filename ) != -1 ){ path = scripts[i].getAttribute( 'src' ) .replace( new RegExp( filename ), '' ); break; } } return path; } IN CONTROL 2009 80
  • 130. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include function FindPath( filename ){ var path = false; var scripts = document.getElementsByTagName( 'script' ); for( var i=0; i<scripts.length; i++ ){ if( scripts[i].getAttribute( 'src' ) && scripts[i].getAttribute( 'src' ) .indexOf( filename ) != -1 ){ path = scripts[i].getAttribute( 'src' ) .replace( new RegExp( filename ), '' ); break; } } return path; } IN CONTROL 2009 80
  • 131. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include function FindPath( filename ){ var path = false; var scripts = document.getElementsByTagName( 'script' ); for( var i=0; i<scripts.length; i++ ){ if( scripts[i].getAttribute( 'src' ) && scripts[i].getAttribute( 'src' ) .indexOf( filename ) != -1 ){ path = scripts[i].getAttribute( 'src' ) .replace( new RegExp( filename ), '' ); break; } } return path; } IN CONTROL 2009 80
  • 132. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include function FindPath( filename ){ var path = false; var scripts = document.getElementsByTagName( 'script' ); for( var i=0; i<scripts.length; i++ ){ if( scripts[i].getAttribute( 'src' ) && scripts[i].getAttribute( 'src' ) .indexOf( filename ) != -1 ){ path = scripts[i].getAttribute( 'src' ) .replace( new RegExp( filename ), '' ); break; } } return path; } IN CONTROL 2009 80
  • 133. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include function FindPath( filename ){ var path = false; var scripts = document.getElementsByTagName( 'script' ); for( var i=0; i<scripts.length; i++ ){ if( scripts[i].getAttribute( 'src' ) && scripts[i].getAttribute( 'src' ) .indexOf( filename ) != -1 ){ path = scripts[i].getAttribute( 'src' ) .replace( new RegExp( filename ), '' ); break; } } return path; } IN CONTROL 2009 80
  • 134. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include function FindPath( filename ){ var path = false; var scripts = document.getElementsByTagName( 'script' ); for( var i=0; i<scripts.length; i++ ){ if( scripts[i].getAttribute( 'src' ) && scripts[i].getAttribute( 'src' ) .indexOf( filename ) != -1 ){ path = scripts[i].getAttribute( 'src' ) .replace( new RegExp( filename ), '' ); break; } } return path; } IN CONTROL 2009 80
  • 135. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include var WickedCool = { jsFile: 'WickedCool.js', cssFile: 'WickedCool.css', basePath: false, initialize: function(){ // determine the path this.basePath = FindPath( this.jsFile ); // add the CSS file var css = document.createElement( 'link' ); css.setAttribute( 'rel', 'stylesheet' ); css.setAttribute( 'type', 'text/css' ); css.setAttribute( 'media', 'screen' ); css.setAttribute( 'href', this.basePath + this.cssFile ); document.getElementsByTagName( 'head' )[0] .appendChild( css ); // do the rest of the wicked cool stuff } }; IN CONTROL 2009 81
  • 136. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include var WickedCool = { jsFile: 'WickedCool.js', cssFile: 'WickedCool.css', basePath: false, initialize: function(){ // determine the path this.basePath = FindPath( this.jsFile ); // add the CSS file var css = document.createElement( 'link' ); css.setAttribute( 'rel', 'stylesheet' ); css.setAttribute( 'type', 'text/css' ); css.setAttribute( 'media', 'screen' ); css.setAttribute( 'href', this.basePath + this.cssFile ); document.getElementsByTagName( 'head' )[0] .appendChild( css ); // do the rest of the wicked cool stuff } }; IN CONTROL 2009 81
  • 137. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include var WickedCool = { jsFile: 'WickedCool.js', cssFile: 'WickedCool.css', basePath: false, initialize: function(){ // determine the path this.basePath = FindPath( this.jsFile ); // add the CSS file var css = document.createElement( 'link' ); css.setAttribute( 'rel', 'stylesheet' ); css.setAttribute( 'type', 'text/css' ); css.setAttribute( 'media', 'screen' ); css.setAttribute( 'href', this.basePath + this.cssFile ); document.getElementsByTagName( 'head' )[0] .appendChild( css ); // do the rest of the wicked cool stuff } }; IN CONTROL 2009 81
  • 138. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include var WickedCool = { jsFile: 'WickedCool.js', cssFile: 'WickedCool.css', basePath: false, initialize: function(){ // determine the path this.basePath = FindPath( this.jsFile ); // add the CSS file var css = document.createElement( 'link' ); css.setAttribute( 'rel', 'stylesheet' ); css.setAttribute( 'type', 'text/css' ); css.setAttribute( 'media', 'screen' ); css.setAttribute( 'href', this.basePath + this.cssFile ); document.getElementsByTagName( 'head' )[0] .appendChild( css ); // do the rest of the wicked cool stuff } }; IN CONTROL 2009 81
  • 139. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include var WickedCool = { jsFile: 'WickedCool.js', cssFile: 'WickedCool.css', basePath: false, initialize: function(){ // determine the path this.basePath = FindPath( this.jsFile ); // add the CSS file var css = document.createElement( 'link' ); css.setAttribute( 'rel', 'stylesheet' ); css.setAttribute( 'type', 'text/css' ); css.setAttribute( 'media', 'screen' ); css.setAttribute( 'href', this.basePath + this.cssFile ); document.getElementsByTagName( 'head' )[0] .appendChild( css ); // do the rest of the wicked cool stuff } }; IN CONTROL 2009 81
  • 140. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include var WickedCool = { jsFile: 'WickedCool.js', cssFile: 'WickedCool.css', basePath: false, initialize: function(){ // determine the path this.basePath = FindPath( this.jsFile ); // add the CSS file var css = document.createElement( 'link' ); css.setAttribute( 'rel', 'stylesheet' ); css.setAttribute( 'type', 'text/css' ); css.setAttribute( 'media', 'screen' ); css.setAttribute( 'href', this.basePath + this.cssFile ); document.getElementsByTagName( 'head' )[0] .appendChild( css ); // do the rest of the wicked cool stuff } }; IN CONTROL 2009 81
  • 141. FUNDAMENTAL JAVASCRIPT Option 3: Scripted include var WickedCool = { jsFile: 'WickedCool.js', cssFile: 'WickedCool.css', basePath: false, initialize: function(){ // determine the path this.basePath = FindPath( this.jsFile ); // add the CSS file var css = document.createElement( 'link' ); css.setAttribute( 'rel', 'stylesheet' ); css.setAttribute( 'type', 'text/css' ); css.setAttribute( 'media', 'screen' ); css.setAttribute( 'href', this.basePath + this.cssFile ); document.getElementsByTagName( 'head' )[0] .appendChild( css ); // do the rest of the wicked cool stuff } }; IN CONTROL 2009 81
  • 142. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed function addCSS( styles ){ var el = document.createElement( 'style' ); el.setAttribute( 'type', 'text/css' ); if( el.styleSheet ){ el.styleSheet.cssText = styles; } else { el.appendChild( document.createTextNode( styles ) ); } document.getElementsByTagName( 'head' )[0] .appendChild( el ); } based on the work of Nicholas Zakas IN CONTROL 2009 82
  • 143. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed function addCSS( styles ){ var el = document.createElement( 'style' ); el.setAttribute( 'type', 'text/css' ); if( el.styleSheet ){ el.styleSheet.cssText = styles; } else { el.appendChild( document.createTextNode( styles ) ); } document.getElementsByTagName( 'head' )[0] .appendChild( el ); } based on the work of Nicholas Zakas IN CONTROL 2009 82
  • 144. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed function addCSS( styles ){ var el = document.createElement( 'style' ); el.setAttribute( 'type', 'text/css' ); if( el.styleSheet ){ el.styleSheet.cssText = styles; } else { el.appendChild( document.createTextNode( styles ) ); } document.getElementsByTagName( 'head' )[0] .appendChild( el ); } based on the work of Nicholas Zakas IN CONTROL 2009 82
  • 145. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed function addCSS( styles ){ var el = document.createElement( 'style' ); el.setAttribute( 'type', 'text/css' ); if( el.styleSheet ){ el.styleSheet.cssText = styles; } else { el.appendChild( document.createTextNode( styles ) ); } document.getElementsByTagName( 'head' )[0] .appendChild( el ); } based on the work of Nicholas Zakas IN CONTROL 2009 82
  • 146. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed function addCSS( styles ){ var el = document.createElement( 'style' ); el.setAttribute( 'type', 'text/css' ); if( el.styleSheet ){ el.styleSheet.cssText = styles; } else { el.appendChild( document.createTextNode( styles ) ); } document.getElementsByTagName( 'head' )[0] .appendChild( el ); } based on the work of Nicholas Zakas IN CONTROL 2009 82
  • 147. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed function addCSS( styles ){ var el = document.createElement( 'style' ); el.setAttribute( 'type', 'text/css' ); if( el.styleSheet ){ el.styleSheet.cssText = styles; } else { el.appendChild( document.createTextNode( styles ) ); } document.getElementsByTagName( 'head' )[0] .appendChild( el ); } based on the work of Nicholas Zakas IN CONTROL 2009 82
  • 148. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed var WickedCool = { _css: '.wicked { color: red; ' + ' font: bold 4em/2 quot;Comic Sansquot;; } ' + '.cool { color: blue; ' + ' font: bold 4em/2' quot;Comic Sansquot;; }', initialize: function(){ // add the CSS addCSS( this._css ); // do the rest of the wicked cool stuff } }; based on the work of Nicholas Zakas IN CONTROL 2009 83
  • 149. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed var WickedCool = { _css: '.wicked { color: red; ' + ' font: bold 4em/2 quot;Comic Sansquot;; } ' + '.cool { color: blue; ' + ' font: bold 4em/2' quot;Comic Sansquot;; }', initialize: function(){ // add the CSS addCSS( this._css ); // do the rest of the wicked cool stuff } }; based on the work of Nicholas Zakas IN CONTROL 2009 83
  • 150. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed var WickedCool = { _css: '.wicked { color: red; ' + ' font: bold 4em/2 quot;Comic Sansquot;; } ' + '.cool { color: blue; ' + ' font: bold 4em/2' quot;Comic Sansquot;; }', initialize: function(){ // add the CSS addCSS( this._css ); // do the rest of the wicked cool stuff } }; based on the work of Nicholas Zakas IN CONTROL 2009 83
  • 151. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed var WickedCool = { _css: '.wicked { color: red; ' + ' font: bold 4em/2 quot;Comic Sansquot;; } ' + '.cool { color: blue; ' + ' font: bold 4em/2' quot;Comic Sansquot;; }', initialize: function(){ // add the CSS addCSS( this._css ); // do the rest of the wicked cool stuff } }; based on the work of Nicholas Zakas IN CONTROL 2009 83
  • 152. FUNDAMENTAL JAVASCRIPT Option 4: Scripted embed var WickedCool = { _css: '.wicked { color: red; ' + ' font: bold 4em/2 quot;Comic Sansquot;; } ' + '.cool { color: blue; ' + ' font: bold 4em/2' quot;Comic Sansquot;; }', initialize: function(){ // add the CSS addCSS( this._css ); // do the rest of the wicked cool stuff } }; based on the work of Nicholas Zakas IN CONTROL 2009 83
  • 153. BUT KEEP IN MIND
  • 154. YOU NEED TO AVOID APPLYING SCRIPT-RELATED STYLES
  • 155. UNTIL YOU KNOW YOUR SCRIPT CAN RUN AND IT HAS INITIALIZED PROPERLY
  • 156. FUNDAMENTAL JAVASCRIPT How do we do that? ๏ make your style rules specific: .TabInterface-folder { ... } or #TabInterface .tab { ... } #TabInterface .tab.active { ... } IN CONTROL 2009 85
  • 157. FUNDAMENTAL JAVASCRIPT How do we do that? <div id=quot;mainquot; class=quot;tabbedquot;> becomes <div id=quot;mainquot; class=quot;tabbed-onquot;> IN CONTROL 2009 86
  • 158. FUNDAMENTAL JAVASCRIPT How do we do that? 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 IN CONTROL 2009 86
  • 159. WEB STANDARDS: FUELING INNOVATION WEB BUILDER 2.0 87
  • 160. FUNDAMENTAL JAVASCRIPT Look for methods function someFunction(){ if( !document.getElementsByTagName ) return; // code that uses document.getElementsByTagName() ... } IN CONTROL 2009 88
  • 161. FUNDAMENTAL JAVASCRIPT Look for methods function someFunction(){ if( !document.getElementsByTagName || !document.getElementById ) return; /* code that uses document.getElementsByTagName() and document.getElementById() */ } IN CONTROL 2009 89
  • 162. FUNDAMENTAL JAVASCRIPT Look for elements function someFunction(){ if( !document.getElementsByTagName || !document.getElementsByTagName( 'p' ) ) return; /* code that uses document.getElementsByTagName() and requires the presence of a P element */ ... } IN CONTROL 2009 90
  • 163. FUNDAMENTAL JAVASCRIPT Look for identified elements function someFunction(){ if( !document.getElementById || !document.getElementById( 'content' ) ) return; // code that requires the presence of #content ... } IN CONTROL 2009 91
  • 164. FUNDAMENTAL JAVASCRIPT Look for objects function someFunction(){ if( typeof( Prototype ) == 'undefined' ) return; // code that uses Prototype ... } IN CONTROL 2009 92
  • 165. FUNDAMENTAL JAVASCRIPT Look for object versions function someFunction(){ if( typeof( jQuery ) == 'undefined' || parseFloat( jQuery.jquery ) < 1.2 ) return; // code that uses jQuery 1.2 or higher ... } IN CONTROL 2009 93
  • 166. FUNDAMENTAL JAVASCRIPT Look before you leap window.onload = function(){ if( document.getElementsByTagName && document.getElementById ){ someFunction(); } }; IN CONTROL 2009 94
  • 167. FUNDAMENTAL JAVASCRIPT PE with JavaScript ๏ Start with the content, then work your way out ๏ Get unobtrusive ๏ Keep some distance between your styles & your scripts ๏ Always wear your detective hat IN CONTROL 2009 95
  • 168. HOW DOES IT ALL COME TOGETHER?
  • 169. FUNDAMENTAL JAVASCRIPT Example 1: Tab Interface IN CONTROL 2009 97
  • 170. FUNDAMENTAL JAVASCRIPT Traditional approach <h1>Pumpkin Pie</h1> <div class=quot;containerquot;> <div class=quot;sectionquot;> <h2>Overview</h2> <img src=quot;pie.jpgquot; alt=quot;quot;> <p>Whether you're hosting a festive party or a casual get-together with friends, our Pumpkin Pie will make entertaining easy!</p> ... </div> ... <ul class=quot;tabsquot;> <li><a href=quot;#quot;>Overview</a></li> <li><a href=quot;#quot;>Ingredients</a></li> <li><a href=quot;#quot;>Directions</a></li> <li><a href=quot;#quot;>Nutrition</a></li> </ul> </div> IN CONTROL 2009 98
  • 171. FUNDAMENTAL JAVASCRIPT Traditional approach <h1>Pumpkin Pie</h1> <div class=quot;containerquot;> <div class=quot;sectionquot;> <h2>Overview</h2> <img src=quot;pie.jpgquot; alt=quot;quot;> <p>Whether you're hosting a festive party or a casual get-together with friends, our Pumpkin Pie will make entertaining easy!</p> ... </div> ... <ul class=quot;tabsquot;> <li><a href=quot;#quot;>Overview</a></li> <li><a href=quot;#quot;>Ingredients</a></li> <li><a href=quot;#quot;>Directions</a></li> <li><a href=quot;#quot;>Nutrition</a></li> </ul> </div> IN CONTROL 2009 98
  • 172. FUNDAMENTAL JAVASCRIPT Traditional approach <h1>Pumpkin Pie</h1> <div class=quot;containerquot;> <div class=quot;sectionquot;> <h2>Overview</h2> <img src=quot;pie.jpgquot; alt=quot;quot;> <p>Whether you're hosting a festive party or a casual get-together with friends, our Pumpkin Pie will make entertaining easy!</p> ... </div> ... <ul class=quot;tabsquot;> <li><a href=quot;#quot;>Overview</a></li> <li><a href=quot;#quot;>Ingredients</a></li> <li><a href=quot;#quot;>Directions</a></li> <li><a href=quot;#quot;>Nutrition</a></li> </ul> </div> IN CONTROL 2009 98
  • 173. FUNDAMENTAL JAVASCRIPT Traditional approach <h1>Pumpkin Pie</h1> <div class=quot;containerquot;> <div class=quot;sectionquot;> <h2>Overview</h2> <img src=quot;pie.jpgquot; alt=quot;quot;> <p>Whether you're hosting a festive party or a casual get-together with friends, our Pumpkin Pie will make entertaining easy!</p> ... </div> ... <ul class=quot;tabsquot;> <li><a href=quot;#quot;>Overview</a></li> <li><a href=quot;#quot;>Ingredients</a></li> <li><a href=quot;#quot;>Directions</a></li> <li><a href=quot;#quot;>Nutrition</a></li> </ul> </div> IN CONTROL 2009 98
  • 175. FUNDAMENTAL JAVASCRIPT A little typography IN CONTROL 2009 100
  • 176. FUNDAMENTAL JAVASCRIPT Typography & color IN CONTROL 2009 101
  • 178. FUNDAMENTAL JAVASCRIPT No style .tabbed IN CONTROL 2009 102
  • 179. FUNDAMENTAL JAVASCRIPT The actual source <h1>Pumpkin Pie</h1> <div class=quot;tabbedquot;> <h2>Overview</h2> <img src=quot;pie.jpgquot; alt=quot;quot; /> <p>Whether you're hosting a festive party or a casual get-together with friends, our Pumpkin Pie will make entertaining easy!</p> ... <h2>Ingredients</h2> <ul> <li>1 (9<abbr title=quot;inchquot;>in</abbr>) unbaked deep dish pie crust</li> <li>½ cup white sugar</li> <li>1 <abbr title=quot;teaspoonquot;>tsp</abbr> ground cinnamon</li> ... </ul> <h2>Directions</h2> ... </div> IN CONTROL 2009 103
  • 180. FUNDAMENTAL JAVASCRIPT The actual source <h1>Pumpkin Pie</h1> <div class=quot;tabbedquot;> <h2>Overview</h2> <img src=quot;pie.jpgquot; alt=quot;quot; /> <p>Whether you're hosting a festive party or a casual get-together with friends, our Pumpkin Pie will make entertaining easy!</p> ... <h2>Ingredients</h2> <ul> <li>1 (9<abbr title=quot;inchquot;>in</abbr>) unbaked deep dish pie crust</li> <li>½ cup white sugar</li> <li>1 <abbr title=quot;teaspoonquot;>tsp</abbr> ground cinnamon</li> ... </ul> <h2>Directions</h2> ... </div> IN CONTROL 2009 103
  • 181. FUNDAMENTAL JAVASCRIPT Understanding the flow IN CONTROL 2009 104
  • 182. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ // Public Properties this.Version = '0.3'; // version // Private Properties var _i = i; // incrementor var _cabinet = el; // the quot;cabinetquot; element (container) var _id = false; // ID of _cabinet var _active = false; // ID of the active quot;folderquot; var _tag = false; // tag we'll split it on // the tab list var _index = document.createElement( 'ul' ); // prototype elements var _els = { li: document.createElement( 'li' ), div: document.createElement( 'div' ) }; // methods to go here }; IN CONTROL 2009 105
  • 183. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ // Public Properties this.Version = '0.3'; // version // Private Properties var _i = i; // incrementor var _cabinet = el; // the quot;cabinetquot; element (container) var _id = false; // ID of _cabinet var _active = false; // ID of the active quot;folderquot; var _tag = false; // tag we'll split it on // the tab list var _index = document.createElement( 'ul' ); // prototype elements var _els = { li: document.createElement( 'li' ), div: document.createElement( 'div' ) }; // methods to go here }; IN CONTROL 2009 105
  • 184. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ // Public Properties this.Version = '0.3'; // version // Private Properties var _i = i; // incrementor var _cabinet = el; // the quot;cabinetquot; element (container) var _id = false; // ID of _cabinet var _active = false; // ID of the active quot;folderquot; var _tag = false; // tag we'll split it on // the tab list var _index = document.createElement( 'ul' ); // prototype elements var _els = { li: document.createElement( 'li' ), div: document.createElement( 'div' ) }; // methods to go here }; IN CONTROL 2009 105
  • 185. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ // Public Properties this.Version = '0.3'; // version // Private Properties var _i = i; // incrementor var _cabinet = el; // the quot;cabinetquot; element (container) var _id = false; // ID of _cabinet var _active = false; // ID of the active quot;folderquot; var _tag = false; // tag we'll split it on // the tab list var _index = document.createElement( 'ul' ); // prototype elements var _els = { li: document.createElement( 'li' ), div: document.createElement( 'div' ) }; // methods to go here }; IN CONTROL 2009 105
  • 186. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ // Public Properties this.Version = '0.3'; // version // Private Properties var _i = i; // incrementor var _cabinet = el; // the quot;cabinetquot; element (container) var _id = false; // ID of _cabinet var _active = false; // ID of the active quot;folderquot; var _tag = false; // tag we'll split it on // the tab list var _index = document.createElement( 'ul' ); // prototype elements var _els = { li: document.createElement( 'li' ), div: document.createElement( 'div' ) }; // methods to go here }; IN CONTROL 2009 105
  • 187. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ ... function initialize(){ // code to come } function addClassName( e, c ){ var classes = ( !e.className ) ? [] : e.className.split( ' ' ); classes.push( c ); e.className = classes.join( ' ' ); } function removeClassName( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) classes.splice( i, 1 ); } e.className = classes.join( ' ' ); } // start it up initialize(); }; IN CONTROL 2009 106
  • 188. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ ... function initialize(){ // code to come } function addClassName( e, c ){ var classes = ( !e.className ) ? [] : e.className.split( ' ' ); classes.push( c ); e.className = classes.join( ' ' ); } function removeClassName( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) classes.splice( i, 1 ); } e.className = classes.join( ' ' ); } // start it up initialize(); }; IN CONTROL 2009 106
  • 189. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ ... function initialize(){ // code to come } function addClassName( e, c ){ var classes = ( !e.className ) ? [] : e.className.split( ' ' ); classes.push( c ); e.className = classes.join( ' ' ); } function removeClassName( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) classes.splice( i, 1 ); } e.className = classes.join( ' ' ); } // start it up initialize(); }; IN CONTROL 2009 106
  • 190. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ ... function initialize(){ // code to come } function addClassName( e, c ){ var classes = ( !e.className ) ? [] : e.className.split( ' ' ); classes.push( c ); e.className = classes.join( ' ' ); } function removeClassName( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) classes.splice( i, 1 ); } e.className = classes.join( ' ' ); } // start it up initialize(); }; IN CONTROL 2009 106
  • 191. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ ... function initialize(){ // code to come } function addClassName( e, c ){ var classes = ( !e.className ) ? [] : e.className.split( ' ' ); classes.push( c ); e.className = classes.join( ' ' ); } function removeClassName( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) classes.splice( i, 1 ); } e.className = classes.join( ' ' ); } // start it up initialize(); }; IN CONTROL 2009 106
  • 192. FUNDAMENTAL JAVASCRIPT THE CODE function TabInterface( el, i ){ function initialize(){ // set the id _id = el.getAttribute( 'id' ) || 'folder-' + _i; if( !el.getAttribute( 'id' ) ) el.setAttribute( 'id', _id ); // trim whitespace var node = _cabinet.firstChild; while( node ){ var nextNode = node.nextSibling; if( node.nodeType == 3 && !/S/.test( node.nodeValue ) ) _cabinet.removeChild( node ); node = nextNode; } } ... }; IN CONTROL 2009 107
  • 193. FUNDAMENTAL JAVASCRIPT THE CODE function TabInterface( el, i ){ function initialize(){ // set the id _id = el.getAttribute( 'id' ) || 'folder-' + _i; if( !el.getAttribute( 'id' ) ) el.setAttribute( 'id', _id ); // trim whitespace var node = _cabinet.firstChild; while( node ){ var nextNode = node.nextSibling; if( node.nodeType == 3 && !/S/.test( node.nodeValue ) ) _cabinet.removeChild( node ); node = nextNode; } } ... }; IN CONTROL 2009 107
  • 194. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ function initialize(){ ... // find the first heading var headers = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ]; var hLen = headers.length; for( var i=0; i<hLen; i++ ){ if( _cabinet.firstChild.nodeName.toLowerCase() == headers[i] ){ _tag = headers[i]; break; } } } ... }; IN CONTROL 2009 108
  • 195. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ function initialize(){ ... // establish the folders var rexp = new RegExp( '<(' + _tag + ')', 'ig' ); var arr = _cabinet.innerHTML.replace( rexp, quot;||||<$1quot; ).split( '||||' ); arr.shift(); _cabinet.innerHTML = ''; removeClassName( _cabinet, 'tabbed' ); addClassName( _cabinet, 'tabbed-on' ); } ... }; IN CONTROL 2009 109
  • 196. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ function initialize(){ ... for( var k=0, aLen = arr.length; k<aLen; k++ ){ // build the div var folder = _els.div.cloneNode( true ); addClassName( folder, 'folder' ); folder.setAttribute( 'id', _id + '-' + k ); folder.innerHTML = arr[k]; _cabinet.appendChild( folder ); // build the tab var tab = _els.li.cloneNode( true ); tab.folder = folder.getAttribute( 'id' ); tab.setAttribute( 'id', tab.folder + '-tab' ); tab.onclick = swap; // set the action var heading = folder.getElementsByTagName( _tag )[0]; tab.innerHTML = heading.innerHTML; addClassName( heading, 'hidden' ); _index.appendChild( tab ); } } ... IN CONTROL 2009 110
  • 197. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ function initialize(){ ... for( var k=0, aLen = arr.length; k<aLen; k++ ){ // build the div var folder = _els.div.cloneNode( true ); addClassName( folder, 'folder' ); folder.setAttribute( 'id', _id + '-' + k ); folder.innerHTML = arr[k]; _cabinet.appendChild( folder ); // build the tab var tab = _els.li.cloneNode( true ); tab.folder = folder.getAttribute( 'id' ); tab.setAttribute( 'id', tab.folder + '-tab' ); tab.onclick = swap; // set the action var heading = folder.getElementsByTagName( _tag )[0]; tab.innerHTML = heading.innerHTML; addClassName( heading, 'hidden' ); _index.appendChild( tab ); } } ... IN CONTROL 2009 110
  • 198. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ function initialize(){ ... for( var k=0, aLen = arr.length; k<aLen; k++ ){ // build the div var folder = _els.div.cloneNode( true ); addClassName( folder, 'folder' ); folder.setAttribute( 'id', _id + '-' + k ); folder.innerHTML = arr[k]; _cabinet.appendChild( folder ); // build the tab var tab = _els.li.cloneNode( true ); tab.folder = folder.getAttribute( 'id' ); tab.setAttribute( 'id', tab.folder + '-tab' ); tab.onclick = swap; // set the action var heading = folder.getElementsByTagName( _tag )[0]; tab.innerHTML = heading.innerHTML; addClassName( heading, 'hidden' ); _index.appendChild( tab ); } } ... IN CONTROL 2009 110
  • 199. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ function initialize(){ ... for( var k=0, aLen = arr.length; k<aLen; k++ ){ // build the div var folder = _els.div.cloneNode( true ); addClassName( folder, 'folder' ); folder.setAttribute( 'id', _id + '-' + k ); folder.innerHTML = arr[k]; _cabinet.appendChild( folder ); // build the tab var tab = _els.li.cloneNode( true ); tab.folder = folder.getAttribute( 'id' ); tab.setAttribute( 'id', tab.folder + '-tab' ); tab.onclick = swap; // set the action var heading = folder.getElementsByTagName( _tag )[0]; tab.innerHTML = heading.innerHTML; addClassName( heading, 'hidden' ); _index.appendChild( tab ); } } ... IN CONTROL 2009 110
  • 200. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ function initialize(){ ... for( var k=0, aLen = arr.length; k<aLen; k++ ){ ... // active? if( k == 0 ){ addClassName( folder, 'visible' ); _active = folder.getAttribute( 'id' ); addClassName( tab, 'active-tab' ); } } // add the index _index.className = 'tab-list'; _cabinet.appendChild( _index ); } ... }; IN CONTROL 2009 111
  • 201. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ function initialize(){ ... for( var k=0, aLen = arr.length; k<aLen; k++ ){ ... // active? if( k == 0 ){ addClassName( folder, 'visible' ); _active = folder.getAttribute( 'id' ); addClassName( tab, 'active-tab' ); } } // add the index _index.className = 'tab-list'; _cabinet.appendChild( _index ); } ... }; IN CONTROL 2009 111
  • 202. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ ... function swap( e ){ e = ( e ) ? e : event; var tab = e.target || e.srcElement; removeClassName( document.getElementById( _active + '-tab' ), 'active-tab' ); removeClassName( document.getElementById( _active ), 'visible' ); addClassName( tab, 'active-tab' ); addClassName( document.getElementById( tab.folder ), 'visible' ); _active = tab.folder; } ... }; IN CONTROL 2009 112
  • 203. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ ... function swap( e ){ e = ( e ) ? e : event; var tab = e.target || e.srcElement; removeClassName( document.getElementById( _active + '-tab' ), 'active-tab' ); removeClassName( document.getElementById( _active ), 'visible' ); addClassName( tab, 'active-tab' ); addClassName( document.getElementById( tab.folder ), 'visible' ); _active = tab.folder; } ... }; IN CONTROL 2009 112
  • 204. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ ... function swap( e ){ e = ( e ) ? e : event; var tab = e.target || e.srcElement; removeClassName( document.getElementById( _active + '-tab' ), 'active-tab' ); removeClassName( document.getElementById( _active ), 'visible' ); addClassName( tab, 'active-tab' ); addClassName( document.getElementById( tab.folder ), 'visible' ); _active = tab.folder; } ... }; IN CONTROL 2009 112
  • 205. FUNDAMENTAL JAVASCRIPT The code function TabInterface( el, i ){ ... function swap( e ){ e = ( e ) ? e : event; var tab = e.target || e.srcElement; removeClassName( document.getElementById( _active + '-tab' ), 'active-tab' ); removeClassName( document.getElementById( _active ), 'visible' ); addClassName( tab, 'active-tab' ); addClassName( document.getElementById( tab.folder ), 'visible' ); _active = tab.folder; } ... }; IN CONTROL 2009 112
  • 206. FUNDAMENTAL JAVASCRIPT Greater flexibility function TabInterface( el, i ){ function initialize(){ ... for( var k=0, aLen = arr.length; k<aLen; k++ ){ ... var heading = folder.getElementsByTagName( _tag )[0]; tab.innerHTML = heading.innerHTML; if( heading.getAttribute( 'title' ) ){ addClassName( heading, 'hidden' ); tab.innerHTML = heading.getAttribute( 'title' ) _index.appendChild( tab ); } else { ... tab.innerHTML = heading.innerHTML; } addClassName( heading, 'hidden' ); } } ... _index.appendChild( tab ); }; ... } } ... }; IN CONTROL 2009 113
  • 207. FUNDAMENTAL JAVASCRIPT Greater flexibility function TabInterface( el, i ){ function initialize(){ ... for( var k=0, aLen = arr.length; k<aLen; k++ ){ ... var heading = folder.getElementsByTagName( _tag )[0]; if( heading.getAttribute( 'title' ) ){ tab.innerHTML = heading.getAttribute( 'title' ) } else { tab.innerHTML = heading.innerHTML; addClassName( heading, 'hidden' ); } _index.appendChild( tab ); ... } } ... }; IN CONTROL 2009 113
  • 208. FUNDAMENTAL JAVASCRIPT Running it // Load up TabInterface if( document.getElementById && document.getElementsByTagName && document.createElement ){ var cabinets = Array(); addDOMLoadEvent( function(){ var collection = document.getElementsByTagName( '*' ); for( var i=0, cLen = collection.length; i<cLen; i++ ){ if( collection[i] && /s*tabbeds*/.test( collection[i].className ) ){ cabinets.push( new TabInterface( collection[i], i ) ); } } } ); } IN CONTROL 2009 114
  • 209. FUNDAMENTAL JAVASCRIPT Running it // Load up TabInterface if( document.getElementById && document.getElementsByTagName && document.createElement ){ var cabinets = Array(); addDOMLoadEvent( function(){ var collection = document.getElementsByTagName( '*' ); for( var i=0, cLen = collection.length; i<cLen; i++ ){ if( collection[i] && /s*tabbeds*/.test( collection[i].className ) ){ cabinets.push( new TabInterface( collection[i], i ) ); } } } ); } IN CONTROL 2009 114
  • 210. FUNDAMENTAL JAVASCRIPT Running it // Load up TabInterface if( document.getElementById && document.getElementsByTagName && document.createElement ){ var cabinets = Array(); addDOMLoadEvent( function(){ var collection = document.getElementsByTagName( '*' ); for( var i=0, cLen = collection.length; i<cLen; i++ ){ if( collection[i] && /s*tabbeds*/.test( collection[i].className ) ){ cabinets.push( new TabInterface( collection[i], i ) ); } } } ); } IN CONTROL 2009 114
  • 211. FUNDAMENTAL JAVASCRIPT Running it // Load up TabInterface if( document.getElementById && document.getElementsByTagName && document.createElement ){ var cabinets = Array(); addDOMLoadEvent( function(){ var collection = document.getElementsByTagName( '*' ); for( var i=0, cLen = collection.length; i<cLen; i++ ){ if( collection[i] && /s*tabbeds*/.test( collection[i].className ) ){ cabinets.push( new TabInterface( collection[i], i ) ); } } } ); } IN CONTROL 2009 114
  • 212. FUNDAMENTAL JAVASCRIPT The full experience IN CONTROL 2009 115
  • 214. FUNDAMENTAL JAVASCRIPT Example 2: Collapsing Form IN CONTROL 2009 117
  • 215. FUNDAMENTAL JAVASCRIPT Collapsing Form as HTML IN CONTROL 2009 118
  • 216. FUNDAMENTAL JAVASCRIPT Collapsing Form with CSS IN CONTROL 2009 119
  • 217. FUNDAMENTAL JAVASCRIPT Collapsing Form with CSS IN CONTROL 2009 120
  • 218. FUNDAMENTAL JAVASCRIPT Collapsing Form with CSS IN CONTROL 2009 121
  • 220. FUNDAMENTAL JAVASCRIPT HTML hooks form.collapsing IN CONTROL 2009 122
  • 221. FUNDAMENTAL JAVASCRIPT HTML hooks fieldset.optional IN CONTROL 2009 122
  • 222. FUNDAMENTAL JAVASCRIPT Understanding the flow IN CONTROL 2009 123
  • 223. FUNDAMENTAL JAVASCRIPT The code var Easy = { addClassName: function( e, c ){ var classes = ( !e.className ) ? [] : e.className.split( ' ' ); classes.push( c ); e.className = classes.join( ' ' ); }, removeClassName: function( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) classes.splice( i, 1 ); } e.className = classes.join( ' ' ); }, hasClassName: function( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) return true; } return false; } }; IN CONTROL 2009 124
  • 224. FUNDAMENTAL JAVASCRIPT The code var Easy = { addClassName: function( e, c ){ var classes = ( !e.className ) ? [] : e.className.split( ' ' ); classes.push( c ); e.className = classes.join( ' ' ); }, removeClassName: function( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) classes.splice( i, 1 ); } e.className = classes.join( ' ' ); }, hasClassName: function( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) return true; } return false; } }; IN CONTROL 2009 124
  • 225. FUNDAMENTAL JAVASCRIPT The code var Easy = { addClassName: function( e, c ){ var classes = ( !e.className ) ? [] : e.className.split( ' ' ); classes.push( c ); e.className = classes.join( ' ' ); }, removeClassName: function( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) classes.splice( i, 1 ); } e.className = classes.join( ' ' ); }, hasClassName: function( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) return true; } return false; } }; IN CONTROL 2009 124
  • 226. FUNDAMENTAL JAVASCRIPT The code var Easy = { addClassName: function( e, c ){ var classes = ( !e.className ) ? [] : e.className.split( ' ' ); classes.push( c ); e.className = classes.join( ' ' ); }, removeClassName: function( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) classes.splice( i, 1 ); } e.className = classes.join( ' ' ); }, hasClassName: function( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) return true; } return false; } }; IN CONTROL 2009 124
  • 227. FUNDAMENTAL JAVASCRIPT The code var Easy = { addClassName: function( e, c ){ var classes = ( !e.className ) ? [] : e.className.split( ' ' ); classes.push( c ); e.className = classes.join( ' ' ); }, removeClassName: function( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) classes.splice( i, 1 ); } e.className = classes.join( ' ' ); }, hasClassName: function( e, c ){ var classes = e.className.split( ' ' ); for( var i=classes.length-1; i>=0; i-- ){ if( classes[i] == c ) return true; } return false; } }; IN CONTROL 2009 124
  • 228. FUNDAMENTAL JAVASCRIPT The code var CollapsingForm = Class.create(); CollapsingForm.prototype = { link: document.createElement( 'a' ), linkText: [ document.createTextNode( 'More options' ), document.createTextNode( 'Fewer options' ) ], hidden: [], state: false, id: false, }; IN CONTROL 2009 125
  • 229. FUNDAMENTAL JAVASCRIPT The code var CollapsingForm = Class.create(); CollapsingForm.prototype = { link: document.createElement( 'a' ), linkText: [ document.createTextNode( 'More options' ), document.createTextNode( 'Fewer options' ) ], hidden: [], state: false, id: false, }; IN CONTROL 2009 125
  • 230. FUNDAMENTAL JAVASCRIPT The code var CollapsingForm = Class.create(); CollapsingForm.prototype = { link: document.createElement( 'a' ), linkText: [ document.createTextNode( 'More options' ), document.createTextNode( 'Fewer options' ) ], hidden: [], state: false, id: false, }; IN CONTROL 2009 125
  • 231. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... initialize: function( form, i ){ // set the id this.id = i; // get the fieldsets var coll = form.getElementsByTagName( 'fieldset' ); // look for hiddens var hide = false; for( var i=coll.length-1; i>=0; i-- ){ if( coll[i].className.indexOf( 'hide-me' ) != -1 ){ hide = true; Easy.addClassName( coll[i], 'hidden' ); Easy.removeClassName( coll[i], 'hide-me' ); this.hidden.push( coll[i] ); } } // more to come } }; IN CONTROL 2009 126
  • 232. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... initialize: function( form, i ){ // set the id this.id = i; // get the fieldsets var coll = form.getElementsByTagName( 'fieldset' ); // look for hiddens var hide = false; for( var i=coll.length-1; i>=0; i-- ){ if( coll[i].className.indexOf( 'hide-me' ) != -1 ){ hide = true; Easy.addClassName( coll[i], 'hidden' ); Easy.removeClassName( coll[i], 'hide-me' ); this.hidden.push( coll[i] ); } } // more to come } }; IN CONTROL 2009 126
  • 233. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... initialize: function( form, i ){ // set the id this.id = i; // get the fieldsets var coll = form.getElementsByTagName( 'fieldset' ); // look for hiddens var hide = false; for( var i=coll.length-1; i>=0; i-- ){ if( coll[i].className.indexOf( 'hide-me' ) != -1 ){ hide = true; Easy.addClassName( coll[i], 'hidden' ); Easy.removeClassName( coll[i], 'hide-me' ); this.hidden.push( coll[i] ); } } // more to come } }; IN CONTROL 2009 126
  • 234. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... initialize: function( form, i ){ // set the id this.id = i; // get the fieldsets var coll = form.getElementsByTagName( 'fieldset' ); // look for hiddens var hide = false; for( var i=coll.length-1; i>=0; i-- ){ if( coll[i].className.indexOf( 'hide-me' ) != -1 ){ hide = true; Easy.addClassName( coll[i], 'hidden' ); Easy.removeClassName( coll[i], 'hide-me' ); this.hidden.push( coll[i] ); } } // more to come } }; IN CONTROL 2009 126
  • 235. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... initialize: function( form, i ){ ... // stop if no hiddens if( hide === false ) return; this.state = 'less'; // create & append the link to the first fieldset this.link = document.createElement( 'a' ); this.link.className = 'show-hide-link'; this.link.setAttribute( 'href', '#' ); Event.observe( this.link, 'click', this.toggle.bindAsEventListener( this ), false ); this.link.appendChild( this.linkText[0] ); coll[0].appendChild( this.link ); Easy.addClassName( form, 'collapsible' ); Easy.removeClassName( form, 'collapsing' ); } }; IN CONTROL 2009 127
  • 236. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... initialize: function( form, i ){ ... // stop if no hiddens if( hide === false ) return; this.state = 'less'; // create & append the link to the first fieldset this.link = document.createElement( 'a' ); this.link.className = 'show-hide-link'; this.link.setAttribute( 'href', '#' ); Event.observe( this.link, 'click', this.toggle.bindAsEventListener( this ), false ); this.link.appendChild( this.linkText[0] ); coll[0].appendChild( this.link ); Easy.addClassName( form, 'collapsible' ); Easy.removeClassName( form, 'collapsing' ); } }; IN CONTROL 2009 127
  • 237. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... initialize: function( form, i ){ ... // stop if no hiddens if( hide === false ) return; this.state = 'less'; // create & append the link to the first fieldset this.link = document.createElement( 'a' ); this.link.className = 'show-hide-link'; this.link.setAttribute( 'href', '#' ); Event.observe( this.link, 'click', this.toggle.bindAsEventListener( this ), false ); this.link.appendChild( this.linkText[0] ); coll[0].appendChild( this.link ); Easy.addClassName( form, 'collapsible' ); Easy.removeClassName( form, 'collapsing' ); } }; IN CONTROL 2009 127
  • 238. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... initialize: function( form, i ){ ... // stop if no hiddens if( hide === false ) return; this.state = 'less'; // create & append the link to the first fieldset this.link = document.createElement( 'a' ); this.link.className = 'show-hide-link'; this.link.setAttribute( 'href', '#' ); Event.observe( this.link, 'click', this.toggle.bindAsEventListener( this ), false ); this.link.appendChild( this.linkText[0] ); coll[0].appendChild( this.link ); Easy.addClassName( form, 'collapsible' ); Easy.removeClassName( form, 'collapsing' ); } }; IN CONTROL 2009 127
  • 239. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { initialize: function( form, i ){ ... }, toggle: function(){ if( this.state == 'less' ){ this.showMore(); } else { this.showLess(); } }, showMore: function(){ // code to come }, showLess: function(){ // code to come } }; IN CONTROL 2009 128
  • 240. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { initialize: function( form, i ){ ... }, toggle: function(){ if( this.state == 'less' ){ this.showMore(); } else { this.showLess(); } }, showMore: function(){ // code to come }, showLess: function(){ // code to come } }; IN CONTROL 2009 128
  • 241. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... showMore: function(){ for( var i=0; i<this.hidden.length; i++ ){ Easy.removeClassName( this.hidden[i], 'hidden' ); } this.link.replaceChild( this.linkText[1], this.link.childNodes[0] ); this.state = 'more'; }, showLess: function(){ for( var i=0; i<this.hidden.length; i++ ){ Easy.addClassName( this.hidden[i], 'hidden' ); } this.link.replaceChild( this.linkText[0], this.link.childNodes[0] ); this.state = 'less'; } }; IN CONTROL 2009 129
  • 242. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... showMore: function(){ for( var i=0; i<this.hidden.length; i++ ){ Easy.removeClassName( this.hidden[i], 'hidden' ); } this.link.replaceChild( this.linkText[1], this.link.childNodes[0] ); this.state = 'more'; }, showLess: function(){ for( var i=0; i<this.hidden.length; i++ ){ Easy.addClassName( this.hidden[i], 'hidden' ); } this.link.replaceChild( this.linkText[0], this.link.childNodes[0] ); this.state = 'less'; } }; IN CONTROL 2009 129
  • 243. FUNDAMENTAL JAVASCRIPT The code CollapsingForm.prototype = { ... showMore: function(){ for( var i=0; i<this.hidden.length; i++ ){ Easy.removeClassName( this.hidden[i], 'hidden' ); } this.link.replaceChild( this.linkText[1], this.link.childNodes[0] ); this.state = 'more'; }, showLess: function(){ for( var i=0; i<this.hidden.length; i++ ){ Easy.addClassName( this.hidden[i], 'hidden' ); } this.link.replaceChild( this.linkText[0], this.link.childNodes[0] ); this.state = 'less'; } }; IN CONTROL 2009 129
  • 244. FUNDAMENTAL JAVASCRIPT Collapsing Form with JS IN CONTROL 2009 130
  • 247. FUNDAMENTAL JAVASCRIPT Popular Libraries ๏ jQuery (jquery.com) ๏ Prototype (prototypejs.org) & Scriptaculous (script.aculo.us) ๏ YUI (developer.yahoo.com/yui) ๏ Dojo (dojotoolkit.org) ๏ Spry (labs.adobe.com/technologies/spry) ๏ MooTools (mootools.net) ๏ MochiKit (mochikit.com) IN CONTROL 2009 133
  • 248. FUNDAMENTAL JAVASCRIPT Popular Libraries ๏ jQuery - fast & easy to write, selector-based ๏ Prototype & Scriptaculous - powerful, Ruby-like ๏ YUI - powerful, backed by Yahoo! ๏ Dojo - powerful, backed by IBM ๏ Spry - supported in Dreamweaver, backed by Adobe ๏ MochiKit - powerful, Python-like IN CONTROL 2009 134
  • 249. FUNDAMENTAL JAVASCRIPT Popular Libraries ๏ jQuery - fast & easy to write, selector-based ๏ Prototype & Scriptaculous - powerful, Ruby-like ๏ YUI - powerful, backed by Yahoo! IN CONTROL 2009 134
  • 250. FUNDAMENTAL JAVASCRIPT Getters 2.0 ๏ jQuery: ‣ $(selector) ‣ $(selector).attr(attribute) ๏ Prototype: ‣ $(id) or $$(selector) ‣ $$(selector).readAttribute(attribute) ๏ YUI: ‣ YAHOO.util.Dom.get(id) or YAHOO.util.Selector.query(selector) ‣ YAHOO.util.Dom.getAttribute(element, attribute) IN CONTROL 2009 135
  • 251. FUNDAMENTAL JAVASCRIPT Setters 2.0 ๏ jQuery: ‣ $(x).text(text) or $(x).html(html) or $(x).append([el|text]) ‣ $(x).attr([attr, value|map]) ๏ Prototype: ‣ $(x).insert([text|element]) // after by default ‣ $(x).writeAttribute([attr, value|map]) ๏ YUI: ‣ YAHOO.util.Dom.insertAfter( [str|el], reference) ‣ YAHOO.util.Dom.addClass(el, class) IN CONTROL 2009 136
  • 252. LET’S REVISIT OUR FIRST EXAMPLE

Editor's Notes

  1. As an example of how graceful degradation would look at a website, here&#x2019;s the &#x201C;hi-fi&#x201D; version of my own site. Graceful degradation would assume that my site should look roughly like this in all modern browsers and roughly like this [switch] in older browsers. It&#x2019;s usable, but isn&#x2019;t great. We can do better.
  2. By contrast, PE would tell me to look at this site from the content-out and work to determine the best way to meet my users&#x2019; needs. It&#x2019;s about your site and its content adapting to users instead of forcing users to get by with the scraps you&#x2019;ve left them.
  3. By contrast, PE would tell me to look at this site from the content-out and work to determine the best way to meet my users&#x2019; needs. It&#x2019;s about your site and its content adapting to users instead of forcing users to get by with the scraps you&#x2019;ve left them.
  4. By contrast, PE would tell me to look at this site from the content-out and work to determine the best way to meet my users&#x2019; needs. It&#x2019;s about your site and its content adapting to users instead of forcing users to get by with the scraps you&#x2019;ve left them.
  5. By contrast, PE would tell me to look at this site from the content-out and work to determine the best way to meet my users&#x2019; needs. It&#x2019;s about your site and its content adapting to users instead of forcing users to get by with the scraps you&#x2019;ve left them.
  6. Developing a website is a lot like waiting tables... * some people drink a lot* some drink very littlewe need to anticipate and meet our customers&#x2019; needs in as seemless a way possible. They should never have to ask us for more water. That&#x2019;s customer service. Taking it a bit further...
  7. As a waiter, you&#x2019;d never throw water in a customer&#x2019;s face. That would be bad customer service. But websites do it all the time when they don&#x2019;t build with PE in mind. We&#x2019;ll touch on an example shortly.
  8. You need to wield your power wisely. Let me spin a yarn...
  9. DHTML, which arrived in the mid-90s, was awful. How many were doing JavaScript at the time? How many liked it? How many looked @ JavaScript and said &#x201C;no way&#x201D;? I don&#x2019;t blame you, it was spaghetti code. Code forking. Forked ourselves. Truth be told, however, our HTML was spaghetti too.
  10. DHTML, which arrived in the mid-90s, was awful. How many were doing JavaScript at the time? How many liked it? How many looked @ JavaScript and said &#x201C;no way&#x201D;? I don&#x2019;t blame you, it was spaghetti code. Code forking. Forked ourselves. Truth be told, however, our HTML was spaghetti too.
  11. Things are better now, but we have new challenges. We need to move from thinking about what Javascript can do that&#x2019;s cool to how it should be used to improve the user experience. [slide] And there&#x2019;s a balance there that PE helps with maintaining as it does put a focus on content.
  12. Things are better now, but we have new challenges. We need to move from thinking about what Javascript can do that&#x2019;s cool to how it should be used to improve the user experience. [slide] And there&#x2019;s a balance there that PE helps with maintaining as it does put a focus on content.
  13. Things are better now, but we have new challenges. We need to move from thinking about what Javascript can do that&#x2019;s cool to how it should be used to improve the user experience. [slide] And there&#x2019;s a balance there that PE helps with maintaining as it does put a focus on content.
  14. The reason I got in to JS: solid foundation to build neat stuff on - XHTML & HTTP. Ajax is cool, but we should never lose sight of the fact that these are the two core technologies that drive the web. Without either, websites would cease to be.
  15. The reason I got in to JS: solid foundation to build neat stuff on - XHTML & HTTP. Ajax is cool, but we should never lose sight of the fact that these are the two core technologies that drive the web. Without either, websites would cease to be.
  16. The reason I got in to JS: solid foundation to build neat stuff on - XHTML & HTTP. Ajax is cool, but we should never lose sight of the fact that these are the two core technologies that drive the web. Without either, websites would cease to be.
  17. And if you try to leapfrog over either, you&#x2019;re doomed. This is one statement I always want you to keep in mind when you&#x2019;re working with JavaScript. And here&#x2019;s an example of why:
  18. And if you try to leapfrog over either, you&#x2019;re doomed. This is one statement I always want you to keep in mind when you&#x2019;re working with JavaScript. And here&#x2019;s an example of why:
  19. What happens if JS is off? Unfortunately you still see this all over the web... if I hear of any of you doing it, I will track you down.
  20. For a while, we thought this was a good improvement over the previous because at least there was an action for the user if Javascript was off, but it&#x2019;s not maintainable.
  21. We then started to think about externalizing the scripting to functions like this.
  22. We then started to think about externalizing the scripting to functions like this.
  23. We then started to think about externalizing the scripting to functions like this.
  24. We then started to think about externalizing the scripting to functions like this.
  25. We then started to think about externalizing the scripting to functions like this.
  26. We then started to think about externalizing the scripting to functions like this.
  27. We then started to think about externalizing the scripting to functions like this.
  28. We then started to think about externalizing the scripting to functions like this.
  29. We then started to think about externalizing the scripting to functions like this.
  30. We then started to think about externalizing the scripting to functions like this.
  31. We then started to think about externalizing the scripting to functions like this.
  32. We then started to think about externalizing the scripting to functions like this.
  33. We can do so much better with far less code.
  34. We can do so much better with far less code.
  35. We can do so much better with far less code.
  36. We can do so much better with far less code.
  37. We can do so much better with far less code.
  38. We can do so much better with far less code.
  39. We can do so much better with far less code.
  40. We can do so much better with far less code.
  41. Who remembers this little treat? I&#x2019;d like you to think about your web work like the McDLT, where JavaScript and CSS are separated as much as humanly possible. Why? because it makes a lot of things easier.
  42. Who remembers this little treat? I&#x2019;d like you to think about your web work like the McDLT, where JavaScript and CSS are separated as much as humanly possible. Why? because it makes a lot of things easier.
  43. Who remembers this little treat? I&#x2019;d like you to think about your web work like the McDLT, where JavaScript and CSS are separated as much as humanly possible. Why? because it makes a lot of things easier.
  44. CSS was poorly understood back then, but we know better now...don&#x2019;t we? Don&#x2019;t be so sure.
  45. CSS was poorly understood back then, but we know better now...don&#x2019;t we? Don&#x2019;t be so sure.
  46. This was taken from a popular JavaScript library. I won&#x2019;t say which, but most of them have stuff like this. That&#x2019;s an accessibility issue
  47. But what if best practices change? Your Javascript needs to be flexible to be maintainable. Just like the McDLT, JavaScript and CSS come together to create a tasty treat, but to be at their best, they need a little separation.
  48. in this example, I&#x2019;m using a function (addClassName) that adds CLASS names in a maintainable way (Prototype has an element method like this)
  49. Simple and straightforward. Scripts like sIFR that require some manual edits to the CSS take this path. Requires diligence in implementation to keep errors out.
  50. Numerous widget scripts and libraries take this path (Lightbox, for instance). Still requires implementation to be error-free.
  51. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  52. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  53. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  54. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  55. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  56. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  57. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  58. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  59. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  60. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  61. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  62. Relies only on the JS and CSS being in the same folder. It doesn&#x2019;t matter where though.
  63. Implementation example.
  64. Implementation example.
  65. Implementation example.
  66. Implementation example.
  67. Implementation example.
  68. Implementation example.
  69. Implementation example.
  70. Implementation example.
  71. Implementation example.
  72. Implementation example.
  73. A little messier, but still very maintainable.
  74. A little messier, but still very maintainable.
  75. A little messier, but still very maintainable.
  76. A little messier, but still very maintainable.
  77. A little messier, but still very maintainable.
  78. A little messier, but still very maintainable.
  79. A little messier, but still very maintainable.
  80. A little messier, but still very maintainable.
  81. your CSS would be added in the configuration of the script and would be easy to maintain and update along with the script as it is a single file. You are still including the two together, but it is a little more separation than writing inline styles.
  82. your CSS would be added in the configuration of the script and would be easy to maintain and update along with the script as it is a single file. You are still including the two together, but it is a little more separation than writing inline styles.
  83. your CSS would be added in the configuration of the script and would be easy to maintain and update along with the script as it is a single file. You are still including the two together, but it is a little more separation than writing inline styles.
  84. your CSS would be added in the configuration of the script and would be easy to maintain and update along with the script as it is a single file. You are still including the two together, but it is a little more separation than writing inline styles.
  85. your CSS would be added in the configuration of the script and would be easy to maintain and update along with the script as it is a single file. You are still including the two together, but it is a little more separation than writing inline styles.
  86. your CSS would be added in the configuration of the script and would be easy to maintain and update along with the script as it is a single file. You are still including the two together, but it is a little more separation than writing inline styles.
  87. separate your style rules from others by prefacing them in some way with the name of the script
  88. Prototype stores its version info as a string
  89. Using Jesse Skinner&#x2019;s addDOMLoadEvent()
  90. Using Jesse Skinner&#x2019;s addDOMLoadEvent()
  91. Using Jesse Skinner&#x2019;s addDOMLoadEvent()
  92. Using Jesse Skinner&#x2019;s addDOMLoadEvent()
  93. Using Jesse Skinner&#x2019;s addDOMLoadEvent()
  94. Using Jesse Skinner&#x2019;s addDOMLoadEvent()
  95. Using Jesse Skinner&#x2019;s addDOMLoadEvent()
  96. Using Jesse Skinner&#x2019;s addDOMLoadEvent()
  97. Using Jesse Skinner&#x2019;s addDOMLoadEvent()
  98. Talk about client and lack of modern computers & mobile.