DOM Scripting
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

DOM Scripting

  • 3,182 views
Uploaded on

DOM scripting and writing unobtrusive Javascript

DOM scripting and writing unobtrusive Javascript

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
3,182
On Slideshare
3,136
From Embeds
46
Number of Embeds
6

Actions

Shares
Downloads
66
Comments
0
Likes
1

Embeds 46

http://jquery-arulmurugant.blogspot.com 19
http://jquery-arulmurugant.blogspot.ru 11
http://jquery-arulmurugant.blogspot.in 10
http://www.slideshare.net 4
http://192.168.10.100 1
http://www.scoop.it 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. DOM Scripting Dave Berthiaume Thomson West Application Technology October 12, 2007
  • 2. Source Book http://www.advanceddomscripting.com
  • 3. Topics
    • Unobtrusive Javascript
    • Namespaces
    • Creating a Script Library
    • Documentation
    • Dealing with styles, style sheets
  • 4. Unobtrusive Javascript
    • Dictionary definition of “unobtrusive”:
      • Not undesirably noticeable or blatant; inconspicuous.
  • 5. Unobtrusive Javascript
    • Scripts should be unobtrusive to the user and avoid unnecessary flashy and annoying features
    • Scripts should allow page to continue to work (perhaps not as elegantly) on older browsers
    • Scripts should be unobtrusive in markup. Provide a level of separation between the script and the markup.
  • 6. Progressive Enhancement Graceful Degradation
    • What YAHOO! Says:
    • Support does not mean that everybody gets the same thing. Expecting two users using different browser software to have an identical experience fails to embrace or acknowledge the heterogeneous essence of the Web. In fact, requiring the same experience for all users creates a barrier to participation. Availability and accessibility of content should be our key priority .
    • Graceful degradation prioritizes presentation, and permits less widely-used browsers to receive less (and give less to the user).
    • Progressive enhancement puts content at the center, and allows most browsers to receive more (and show more to the user).
    • While close in meaning, progressive enhancement is a healthier and more forward-looking approach.
    • http://developer.yahoo.com/yui/articles/gbs/index.html
  • 7. Goals For DOM Scripts
    • Standards compliant
      • Future proof
      • Ability to support new, better browsers
    • Maintainable
      • Reusable, easy to understand methods
    • Accessible
      • Easy, efficient access for everyone
    • Usable
      • Usable both by end users and developers
  • 8. Common Pitfalls
    • <script> tags inline in body of document
    • Reliance on browser sniffing rather than capability detection to test for Javascript feature compatibility
    • Hard-coded “javascript:” prefixes in the “href” attributes of anchor elements
    • Redundant, repetitive, highly customized Javascript
  • 9. Separate Behavior From Markup
    • The number one thing you can do to improve any project involving Javascript is to separate the behavior from the markup
    • Often overlooked or not given enough attention
    • Already a best practice for XHTML/CSS. Javascript should follow the same separation rules
  • 10. Including Javascript
    • Very Bad (inside <body>, no separation, leads to repetitive code):
      • <body> <script type=&quot;text/javascript&quot;>
      • function popup(url) {
      • window.open(url); }
      • </script>
    • Arguably better (in one location (<head>), no separation):
      • <head> <script type=&quot;text/javascript&quot;>
      • function popup(url) {
      • window.open(url); }
      • </script>
    • Good:
      • <script src=&quot;popupLoadEvent.js&quot; type=&quot;text/javascript&quot;></script>
  • 11. Case Study
    • Want to open a popup window:
    • <a href=&quot;http://advanceddomscripting.com&quot; target=&quot;_blank&quot;>
    • What is the potential problem here?
  • 12. Case Study
    • <a href=&quot;http://advanceddomscripting.com&quot; target=&quot;_blank&quot;>
    • Will not validate if you’re using a XHTML Strict DOCTYPE
    • “ target” attribute is deprecated and not allowed in XHTML 1.0)
    • So what? Why should I care?
    • Following web standards is now considered a best practice
    • NextGen likely to require valid markup?
    • Minimal amount of effort involved to do it right, why not?
  • 13. Case Study
    • Another method:
    • <a href=&quot;javascript:window.open( 'http://advanceddomscripting.com');&quot;>
    • What is the problem here?
  • 14. Case Study
    • <a href=javascript:window.open('http://advanceddomscripting.com');&quot;>
    • javascript: prefix can handle only one function, nothing more
    • javascript: prefix, while widely supported, is not part of the ECMAScript standard
    • Creates a direct reliance on Javascript to navigate or activate the anchor
    • If function returns a value, page may be overridden with the result
  • 15. Case Study
    • Another alternative: Add function in js file:
      • function popup(url) {
      • window.open(url);
      • //do not return anything!
      • }
    • Reference new function:
    • <a href= &quot;javascript:popup('http://advanceddomscripting.com');&quot;>
    • But we’re still using the javascript: prefix
  • 16. Case Study
    • Using the “onclick” handler is a little better, but not ideal:
    • <a href=&quot;http://advanceddomscripting.com&quot; onclick=&quot;this.href=‘ javascript:popup(’http://advanceddomscripting.com’);’&quot;>
    • “ onclick” executes first
    • By using “this.href” from within the “onclick” event, will work even if Javascript is disabled
    • Still requires inline Javascript
  • 17. Case Study
    • <a href=&quot;http://advanceddomscripting.com&quot; onclick=&quot;popup(this.href); return false;&quot;>
    • Better solution. Retrieves value of “href” attribute from within the “onclick” attribute
    • Must return false to prevent default action
    • Still requires inline Javascript
  • 18. Case Study
    • Problems with all these techniques:
      • Not unobtrusive
      • Still coded directly into document
      • Inline event handlers provide no separation of behavior and structure
    • Solution:
      • Use unobtrusive techniques to add event handlers when the window loads
  • 19. Case Study: Solution
    • <a href=&quot;http://advanceddomscripting.com&quot; class=&quot;popup&quot;>
    • //add a load event to alter the page
    • TLR.addEvent(window,'load',function(W3CEvent) {
    • //locate all the anchor tags with the popup class in the document
    • var popups = TLR.getElementsByClassName('popup', 'a');
    • for(var i=0 ; i<popups.length ; i++ ) {
    • //add a click event listener to each anchor
    • TLR.addEvent(popups[i],'click',function(W3CEvent) {
    • //open the window using the href attribute
    • window.open(this.href);
    • //cancel the default event
    • TLR.eventPreventDefault(W3CEvent);
    • });
    • }
    • });
  • 20. Case Study: Solution Examined
    • <a href=&quot;http://advanceddomscripting.com&quot; class=&quot;popup&quot;>
    • Clean separation of behavior and structure
    • No inline javascript (except for inclusion of js file)
    • Will degrade gracefully if Javascript is not available, since anchor still links to correct URL
    • Enhances behavior by adding click event listener on all the anchor tags with the “popup” class
    • Enables unique styling of popup anchors with CSS:
    • .popup {
    • background: transparent url(popup.png) no-repeat right center;
    • }
  • 21. addEvent Function
    • function addEvent( node, type, listener ) {
    • // Check compatibility to ensure graceful degradation
    • if(!isCompatible()) { return false }
    • if(!(node = $(node))) return false;
    • if (node.addEventListener) {
    • // W3C method
    • node.addEventListener( type, listener, false );
    • return true;
    • } else if(node.attachEvent) {
    • // MSIE method
    • node['e'+type+listener] = listener;
    • node[type+listener] = function(){node['e'+type+listener]( window.event );}
    • node.attachEvent( 'on'+type, node[type+listener] );
    • return true;
    • }
    • return false; // Didn't have either so return false
    • };
  • 22. Namespaces
    • Function naming conflicts can be an issue with extensive use of Javascript and third party libraries
    • Javascript does not complain if a function is declared multiple times
    • What happens if there are 3 different declarations of function “foo”, and a call is made to foo() at runtime?
  • 23. Namespaces
    • Function naming conflicts can be an issue with extensive use of Javascript and third party libraries
    • Javascript does not complain if a function is declared multiple times
    • What happens if there are 3 different declarations of function “foo”, and a call is made to foo() at runtime?
      • The last declaration is used
  • 24. Namespaces
    • A lot of frustration can be avoided by keeping two simple things in mind:
      • Be unique
        • Pick a name for your space that’s not going to be used elsewhere (Yahoo uses YAHOO, and Google Maps uses a G prefix for everything). We’ll use TLR for this presentation.
      • Don’t share
        • By that, I mean don’t share everything
        • Share (expose) only what you want to share
        • Keep internal functions “hidden”, exposing public API only
  • 25. Namespaces
    • (function() {
    • // some code
    • } ) ();
    • What’s going on here?
  • 26. Namespaces
    • (function() {
    • // some code } ) ();
    • Self-executing anonymous function
    • First set of () returns the unnamed function to the script
    • Last set of () executes the returned function immediately
    • Example:
    • (function(arg) {
    • alert(arg);
    • } ) (‘This will show in the alert box’);
  • 27. Namespaces
    • (function() {
    • // your code inside the wrapper
    • } ) ();
    • Custom functions or objects within this special function wrapper will not be accessible to anyone else outside the special wrapper- unless you allow access.
    • Great for “local variables”
    • Also known as a “closure”
  • 28. Evolution of a Javascript Coder
    • “ Everything is a reference!”
    • “ You can do OO code!”
    • “ Huh, so that’s how Object Prototypes work!”
    • “ Thank God for closures!”
    • From “Building a JavaScript Library ” presentation by John Resig: http://ejohn.org/blog/building-a-javascript-library/
  • 29. Namespaces
    • (function(){
    • function $(id) {
    • return document.getElementbyId(id);
    • };
    • function alertNodeName(id) {
    • alert($(id).nodeName);
    • };
    • window[‘TLR'] = {};
    • window[‘TLR'][‘showNodeName'] = alertNodeName;
    • } ) ();
    • TLR.showNodeName(‘example’);
  • 30. Namespaces
    • showNodeName will have access to anything within the function wrapper and anything declared outside the wrapper as well
    • Anything declared outside of the “TLR” wrapper will not have access to the $() function
    • In essence, we’ve “faked” a Javascript namespace (TLR), which encapsulates our functions
    • As a bonus, the code compresses well with Javascript compressors (such as Dojo)
  • 31. Namespaces
    • Use as few global variables as feasible
    • One namespace is optimal (see: Dojo, Yahoo UI, jQuery)
    • Questions to ask:
      • Can my code coexist with other random code on the site?
      • Can my code coexist with other copies of my own library?
      • Can my code be embedded inside another namespace?
  • 32. Reusable Javascript Library
    • Library, not framework
      • Roll our own?
      • Third party?
        • jQuery ( http://www.jquery.com )
        • Prototype.js ( http://www.prototypejs.org )
        • Others?
  • 33. Library Advantages
    • A well-built library shields developers from having to worry about cross-browser issues
    • Library file cached by browser
    • If well-supported and documented, can provide a great productivity boost
  • 34. Library Drawbacks
    • You might not be able to figure out how to use a particular library.
    • If you can figure out how to use a library, you still might not be getting the most out of it because you don’t know what options it really gives you.
    • The library you end up using might have bugs which you don’t understand and can’t fix.
    • You might inadvertently use it in an unsafe way and end up with cross-site scripting bugs or other security problems.
    • Library “bloat”
  • 35. Library Documentation
    • Presently no great way to generate documentation from source code
    • Tools available to produce documentation out of comments in the source code
      • JSDoc / Natural Docs
      • Problems documenting inheritance
      • Troubles documenting the objects (functions, variables) defined in Javascript namespaces
  • 36. Library Documentation
    • jGrouseDoc ( http://jgrouse.com/#jgdoc )
    • Learned lessons from using JSDoc and Natural Docs
    • So many ways in Javascript to implement object orientation, namespaces, etc, there is no point trying to parse Javascript code itself
    • Simpler and more reliable just to parse the comments in the source code (similar to Natural Docs)
    • Documentation is produced from javadoc-style comments that are already familiar to many developers
    • Allows documenting of Javascript classes, regardless which approach or framework is being used
    • More flexibility when documenting objects in namespaces
    • The output is highly customizable. The rendering is based on XSL Transformation, so users can simply modify appropriate XSL template.
    • The tool is implemented as Ant task
  • 37. jGrouseDoc Code Comments
  • 38. jGrouseDoc Documentation
  • 39. jQuery Documentation
    • jQuery
    • Produces documentation in XML
    • With common format available, others built:
      • API browsers ( http://www.visualjquery.com )
      • Cheat sheets
      • Widgets
      • PDF
      • Translations
    • An API for the API
  • 40. Library Documentation Goals
    • What to strive for:
      • Documentation in a clear format
      • Enable users to build new views from core documentation
      • No API view is perfect, need good “How-Tos” as well
  • 41. Keeping Style Out of Your Scripts
    • Keeping style separate from markup is easy using CLASS, ID and external style sheets
    • In scripts it’s just as important to separate stylistic changes from behavioral changes
    • Scripts will influence the appearance of a document, but they shouldn’t do so in a way that forces you to edit the DOM script when tweaking the design
    • Influence appearance without directly changing stylistic properties
  • 42. The ‘style’ Property
    • element.style.color = ‘red’;
    • Problems with modifying the style property:
      • Embeds stylistic design into your behavioral DOM script (sometimes makes sense for behavior-related properties like positioning, or a very isolated change)
      • The ‘style’ property isn’t what you might think it is
        • It o nly provides access to properties declared inline in the element’s style attribute. Doesn’t contain any CSS properties from the cascade. You can’t use it to retrieve the overall computed style of the element.
  • 43. Other ‘style’ Quirks
    • element.style.backgroundColor = ‘yellow’;
    • Uses camel case instead of the CSS hyphenated syntax (‘background-color’)
    • DOM2 provides a setProperty method:
    • element.style.setProperty(‘background-color’,’yellow’);
      • The problem here is that IE does not support the setProperty method
    • Need a shortcut method for cross-browser compatibility
  • 44. Cross-Browser Method
    • // set style By ID
    • TLR.setStyleById('test',{
    • 'background-color':'green',
    • 'border':'2px solid black',
    • 'color':'white',
    • 'display':'inline'
    • });
    • Hyphenated version will be converted to camel case as necessary using a TLR.camelize() method
    • But this still embeds the style in your code
    • Easier to mess with your CSS files rather than hunt through your DOM scripts
    • OK to mix for positioning, like reacting to mouse movements
    • Font manipulation, color changes, etc, do not belong directly in scripts
  • 45. className Switching
    • Use DOM switch script to modify the className property of desired elements
      • Allows alteration of appearance based on predefined rules in your style sheets
      • Allows for reuse of the same script across multiple designs since design is not part of the script
  • 46. className Switching Example
    • .normal { background-color: black; } .normal.modified { background-color: red; }
    • var element = TLR.$(‘example’); element.className += ‘ modified’;
  • 47. className Switching
    • Good idea to use common classes to indicate changes (ex: You may decide ‘hover’ is a reserved word)
    • #cart.hover { background-color: yellow; } #sidebar.hover { text-decoration: underline; }
    • ‘ Hover’ class will now act as a pseudo-class, like the CSS ‘a:hover’ pseudo-class
  • 48. className Switching
    • Maintains proper separation and opens the presentation to CSS designers using the site’s style sheets
    • Switching can be hard to manage:
    • var element = TLR.$(‘example’); element.className += ‘ modified’;
      • Reusable methods are needed:
        • getClassNames(element)
        • hasClassName(element, class)
        • addClassName(element, class)
        • removeClassName(element, class)
  • 49. className Switching Examples
      • var testElement = TLR.$('test');
      • if(TLR.hasClassName(testElement,'newClass')) { TLR.removeClassName(testElement, 'newClass');
      • }
      • // Retrieve the classes var classNames = TLR.getClassNames(testElement)); for(var i=0 ; i<classNames.length ; i++ ) { TLR.removeClassName(testElement, classNames[i]);
      • }
      • // Modify the class name to indicate
      • // change and apply CSS
      • TLR.addClassName(testElement,'modified');
  • 50. Style Sheet Switching
    • For larger scale changes, it doesn’t make sense to iterate over the DOM tree, manually modifying styles of individual elements
    • Much easier to simply switch the active style sheet for a completely different one
      • Use ‘rel’ property of the <link> element to define alternate style sheets and switch between them
      • Apply a class to the <body> tag and modify CSS selectors depending on the body class
      • Dynamically add and remove style sheets
  • 51. Alternate Style Sheets
    • Link elements:
    • <link type=“text/css” href=“foo.css” media=“screen”>
    • Link elements also contain lesser known attributes:
      • ‘ rel’ indicates the relationship between the style sheet and the document
      • ‘ disabled’ indicates whether the style sheet is active
      • ‘ title’ is the title associated with the style sheet
  • 52. Alternate Style Sheets
    • To apply a syle sheet immediately:
    • <link rel=‘stylesheet’…
    • To define an alternate style sheet:
    • <link rel=‘alternate stylesheet’…
      • Browser will load the style sheet, and set the ‘disabled’ flag to true
      • Will not be immediately applied to the document
    • ‘ title’ attribute has no effect on the style sheet, but can be used to switch between them
  • 53. Style Switcher Demonstration
  • 54. Switching the Body className
    • Same as className switching discussed earlier, but we’re switching the className only on the <body> tag
    • To apply styles based on the body tag, include one style sheet that has the body’s class selector in all the declarations
  • 55. Switching the Body className
    • body.tlr h1 { font-size: 2em; } body.west h1 { font-size: 3em; }
    • TLR.addEvent(‘trl-anchor’, ’click’, function() { TLR.addClassName(document.body, ‘tlr’); }); TLR.addEvent(‘west-anchor’, ’click’, function() { TLR.addClassName(document.body, ‘west’); });
    • Can be applied at any document level, not just <body>
  • 56. Dynamically Loading and Removing
    • Use createElement() to create a new <link> element
    • Methods to add/remove:
    • TLR.addStyleSheet(‘css/style.css’, ‘screen’);
    • TLR.removeStyleSheet(‘css/style.css’, ‘screen’);
    • By loading and unloading various style sheets, you can switch among as many style sheets as you like
  • 57. Modifying CSS Rules
    • If need to modify appearance of several related elements, may be easier to modify the actual CSS rule in the style sheet
    • Very useful if you want specific properties to change, but still want cascade to apply to some things
  • 58. Modifying CSS Rules
    • Example:
      • Want to dynamically style links on a page
        • Make all links bold
        • Remove underlines from links
        • Add underline on hover over links
  • 59. Modifying CSS Rules
    • Could use DOM script to add or edit the CSS rules in your style sheet
      • This gets tricky
      • Document could contain several style sheets ( document.stylesheets property)
      • Unless you know which style sheet you want to manipulate, you’ll have to loop through all of them, looking for appropriate selectors
  • 60. New Method
    • getStyleSheets(url, media)
      • Returns an array of style sheets that match the given ‘href’ and optional ‘media’ properties of the style sheet objects
      • For inline <style> blocks (which you shouldn’t be using), href will be that of the page
      • Now you can find the style sheets you need and modify them
  • 61. Modifying Styles
    • More new methods (each uses getStyleSheets):
      • editCSSRule(selector, styles, url, media)
      • addCSSRule(selector, styles, index, url, media)
    • Applying these methods:
    • TLR.addEvent(window,'load',function() { TLR.editCSSRule('a',{
    • 'font-weight':'bold’ });
    • TLR.editCSSRule('a:link',{
    • 'text-decoration':'none’ });
    • TLR.addCSSRule('a:hover', {'text-decoration':'underline'});
    • });
  • 62. Modifying Styles
    • TLR.editCSSRule(‘a’,{’background-color’:’yellow’});
    • All anchors will receive the new color unless another style in the cascade overrides the color
    • Modifying the ‘style’ property of the element itself can’t implement changes such as this
    • Can only modify a rule that has been explicitly declared in a style sheet
  • 63. Modifying Styles
    • Modifying each individual style property
    • Switching the body class
    • Editing the CSS rules
    • Each have their advantages
    • Have to decide which solution is best in each particular instance
  • 64. Accessing the Computed Style
    • Prior to modification of an element, you may want to determine the current style properties
    • The ‘style’ property only applies to styles defined inline
    • Getting style info from the CSS rules themselves would be a long, complicated process
  • 65. Accessing the Computed Style
    • DOM2 provides a method in the document.defaultView called getComputedStyle() that returns the computed style properties for a given element, not just those defined inline
    • The problem, as usual, is that Microsoft has its own version using the element’s ‘currentstyle’ property
  • 66. Accessing the Computed Style
    • The solution is a new method that hides the details of the browser implementations:
    • getStyle(element, property)
    • Example (get computed background color):
    • var element = TLR.$(‘sample’); var color = TLR.getStyle(element, ‘background-color’);
  • 67. Questions