• Share
  • Email
  • Embed
  • Like
  • Private Content
Fundamental JavaScript [In Control 2009]
 

Fundamental JavaScript [In Control 2009]

on

  • 5,214 views

In this session, Aaron Gustafson introduces attendees to the client-side scripting language known as JavaScript. After being taken on a quick tour through the language's features and syntax, attendees ...

In this session, Aaron Gustafson introduces attendees to the client-side scripting language known as JavaScript. After being taken on a quick tour through the language's features and syntax, attendees will be introduced through a series of examples to ways in which JavaScript can progressively enhance the user experience and really make their designs sing. This session also introduces attendees to several JavaScript libraries and demonstrate how to execute the same task in each.

Statistics

Views

Total Views
5,214
Views on SlideShare
5,199
Embed Views
15

Actions

Likes
23
Downloads
306
Comments
0

4 Embeds 15

http://www.brijj.com 10
http://bypace.com 3
http://www.slideshare.net 1
http://localhost 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

CC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike LicenseCC Attribution-NonCommercial-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • As an example of how graceful degradation would look at a website, here’s the “hi-fi” version of my own site. <br /> <br /> 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’s usable, but isn’t great. We can do better. <br />
  • 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’ needs. It’s about your site and its content adapting to users instead of forcing users to get by with the scraps you’ve left them. <br />
  • 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’ needs. It’s about your site and its content adapting to users instead of forcing users to get by with the scraps you’ve left them. <br />
  • 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’ needs. It’s about your site and its content adapting to users instead of forcing users to get by with the scraps you’ve left them. <br />
  • 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’ needs. It’s about your site and its content adapting to users instead of forcing users to get by with the scraps you’ve left them. <br />
  • <br />
  • Developing a website is a lot like waiting tables... <br /> <br /> * some people drink a lot* some drink very littlewe need to anticipate and meet our customers’ needs in as seemless a way possible. They should never have to ask us for more water. That’s customer service. <br /> <br /> Taking it a bit further... <br />
  • As a waiter, you’d never throw water in a customer’s face. That would be bad customer service. But websites do it all the time when they don’t build with PE in mind. <br /> <br /> We’ll touch on an example shortly. <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • You need to wield your power wisely. <br /> <br /> Let me spin a yarn... <br />
  • DHTML, which arrived in the mid-90s, was awful. <br /> <br /> How many were doing JavaScript at the time? How many liked it? How many looked @ JavaScript and said “no way”? <br /> <br /> I don’t blame you, it was spaghetti code. Code forking. Forked ourselves. Truth be told, however, our HTML was spaghetti too. <br />
  • DHTML, which arrived in the mid-90s, was awful. <br /> <br /> How many were doing JavaScript at the time? How many liked it? How many looked @ JavaScript and said “no way”? <br /> <br /> I don’t blame you, it was spaghetti code. Code forking. Forked ourselves. Truth be told, however, our HTML was spaghetti too. <br />
  • Things are better now, but we have new challenges. We need to move from thinking about what Javascript can do that’s cool to how it should be used to improve the user experience. <br /> <br /> [slide] And there’s a balance there that PE helps with maintaining as it does put a focus on content. <br />
  • Things are better now, but we have new challenges. We need to move from thinking about what Javascript can do that’s cool to how it should be used to improve the user experience. <br /> <br /> [slide] And there’s a balance there that PE helps with maintaining as it does put a focus on content. <br />
  • Things are better now, but we have new challenges. We need to move from thinking about what Javascript can do that’s cool to how it should be used to improve the user experience. <br /> <br /> [slide] And there’s a balance there that PE helps with maintaining as it does put a focus on content. <br />
  • <br />
  • The reason I got in to JS: solid foundation to build neat stuff on - XHTML & HTTP. <br /> <br /> 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. <br />
  • The reason I got in to JS: solid foundation to build neat stuff on - XHTML & HTTP. <br /> <br /> 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. <br />
  • The reason I got in to JS: solid foundation to build neat stuff on - XHTML & HTTP. <br /> <br /> 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. <br />
  • And if you try to leapfrog over either, you’re doomed. <br /> <br /> This is one statement I always want you to keep in mind when you’re working with JavaScript. And here’s an example of why: <br />
  • And if you try to leapfrog over either, you’re doomed. <br /> <br /> This is one statement I always want you to keep in mind when you’re working with JavaScript. And here’s an example of why: <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • What happens if JS is off? <br /> <br /> Unfortunately you still see this all over the web... if I hear of any of you doing it, I will track you down. <br />
  • 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’s not maintainable. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We then started to think about externalizing the scripting to functions like this. <br />
  • We can do so much better with far less code. <br />
  • We can do so much better with far less code. <br />
  • We can do so much better with far less code. <br />
  • We can do so much better with far less code. <br />
  • We can do so much better with far less code. <br />
  • We can do so much better with far less code. <br />
  • We can do so much better with far less code. <br />
  • We can do so much better with far less code. <br />
  • <br />
  • Who remembers this little treat? <br /> <br /> I’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. <br />
  • Who remembers this little treat? <br /> <br /> I’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. <br />
  • Who remembers this little treat? <br /> <br /> I’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. <br />
  • CSS was poorly understood back then, but we know better now...don’t we? Don’t be so sure. <br />
  • CSS was poorly understood back then, but we know better now...don’t we? Don’t be so sure. <br />
  • This was taken from a popular JavaScript library. I won’t say which, but most of them have stuff like this. <br /> <br /> That’s an accessibility issue <br />
  • But what if best practices change? <br /> <br /> 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. <br />
  • in this example, I’m using a function (addClassName) that adds CLASS names in a maintainable way <br /> (Prototype has an element method like this) <br />
  • <br />
  • Simple and straightforward. Scripts like sIFR that require some manual edits to the CSS take this path. <br /> <br /> Requires diligence in implementation to keep errors out. <br />
  • Numerous widget scripts and libraries take this path (Lightbox, for instance). <br /> <br /> Still requires implementation to be error-free. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Relies only on the JS and CSS being in the same folder. It doesn’t matter where though. <br />
  • Implementation example. <br />
  • Implementation example. <br />
  • Implementation example. <br />
  • Implementation example. <br />
  • Implementation example. <br />
  • Implementation example. <br />
  • Implementation example. <br />
  • Implementation example. <br />
  • Implementation example. <br />
  • Implementation example. <br />
  • A little messier, but still very maintainable. <br />
  • A little messier, but still very maintainable. <br />
  • A little messier, but still very maintainable. <br />
  • A little messier, but still very maintainable. <br />
  • A little messier, but still very maintainable. <br />
  • A little messier, but still very maintainable. <br />
  • A little messier, but still very maintainable. <br />
  • A little messier, but still very maintainable. <br />
  • 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. <br />
  • 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. <br />
  • 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. <br />
  • 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. <br />
  • 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. <br />
  • 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. <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • separate your style rules from others by prefacing them in some way with the name of the script <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • Prototype stores its version info as a string <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • Using Jesse Skinner’s addDOMLoadEvent() <br />
  • Using Jesse Skinner’s addDOMLoadEvent() <br />
  • Using Jesse Skinner’s addDOMLoadEvent() <br />
  • Using Jesse Skinner’s addDOMLoadEvent() <br />
  • Using Jesse Skinner’s addDOMLoadEvent() <br />
  • Using Jesse Skinner’s addDOMLoadEvent() <br />
  • Using Jesse Skinner’s addDOMLoadEvent() <br />
  • Using Jesse Skinner’s addDOMLoadEvent() <br />
  • Using Jesse Skinner’s addDOMLoadEvent() <br />
  • <br />
  • <br />
  • Talk about client and lack of modern computers & mobile. <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />

Fundamental JavaScript [In Control 2009] Fundamental JavaScript [In Control 2009] Presentation Transcript

  • 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 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 138
  • 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 139
  • 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 140
  • FUNDAMENTAL JAVASCRIPT The optimized code ... var i, quotes = document.getElementsByTagName( 'blockquote' ), a = document.createElement( 'a' ), p = document.createElement( 'p' ); a.appendChild( document.createTextNode('source') ); p.className = 'attribution'; for( i=0; i < quotes.length; i++ ){ var source = quotes[i].getAttribute( 'cite' ); if( source ){ var link = a.cloneNode( true ); link.setAttribute( 'href', source ); var para = p.cloneNode( true ); para.appendChild( link ); quotes[i].appendChild( para ); } } ... IN CONTROL 2009 141
  • FUNDAMENTAL JAVASCRIPT In jQuery ... var $this, $p = $('<p class=quot;attributionquot;><a href=quot;#quot;>source</a></p>'); $('blockquote[cite]').each(function(){ $this = $(this).append( $p.clone() ); $this.find('.attribution a') .attr( 'href', $this.attr( 'cite' ) ); }); ... IN CONTROL 2009 142
  • FUNDAMENTAL JAVASCRIPT In Prototype ... var $el, $link, $para, $a = $( document.createElement('a') ).insert( 'source' ), $p = $( document.createElement('p') ).addClassName( 'attribution' ); $$('blockquote[cite]').each(function($el){ $link = $a.cloneNode( true ); $para = $p.cloneNode( true ); $link.writeAttribute( 'href', $el.readAttribute( 'cite' ) ); $para.insert( $link ); $el.insert( $para ); }); ... IN CONTROL 2009 143
  • FUNDAMENTAL JAVASCRIPT In YUI ... var i, $D = YAHOO.util.Dom, $ = YAHOO.util.Selector.query, quotes = $( 'blockquote[cite]' ), a = document.createElement( 'a' ), p = document.createElement( 'p' ); a.appendChild( document.createTextNode('source') ); $D.addClass( p, 'attribution' ); for( i=0; i < quotes.length; i++ ){ var link = a.cloneNode( true ); link.setAttribute( 'href', quotes[i].getAttribute( 'cite' ) ); var para = p.cloneNode( true ); para.appendChild( link ); quotes[i].appendChild( para ); } ... IN CONTROL 2009 144
  • FUNDAMENTAL JAVASCRIPT Running the function ๏ DOM: ‣ window.onload = sourceQuotes; ๏ jQuery: ‣ $(document).ready( sourceQuotes ); ‣ $( sourceQuotes ); ๏ Prototype: ‣ document.observe( 'dom:loaded', sourceQuotes ); ๏ YUI: ‣ YAHOO.util.Event.onDOMReady( sourceQuotes ); IN CONTROL 2009 145
  • FUNDAMENTAL JAVASCRIPT Keep in mind ๏ Helper/convenience methods are often shorter, but are sometimes less explicit (e.g. $()) ‣ Comment. Comment! COMMENT! ๏ Libraries often obscure what’s really going on under the hood and can make it more difficult to debug your code ‣ Read the source, learn what it’s doing for you ๏ Libraries trade off convenience for file size; they also often have numerous features you may never use ‣ If you can write something without a library and it works, don’t use a library ‣ Check for minified files and/or isolated modules IN CONTROL 2009 146
  • NOW GET OUT THERE AND WRITE SOMETHING COOL
  • FUNDAMENTAL JAVASCRIPT Aaron Gustafson Slides available at http://slideshare.net/AaronGustafson This presentation is licensed under Creative Commons Attribution-Noncommercial-Share Alike 3.0