Section 27.6. DOM Scripting in Action


27.6. DOM Scripting in Action

To better appreciate the power of DOM Scripting, take a look at two relatively simple examples . Instead of breaking down the JavaScript into chunks, helpful JavaScript comments have been added that discuss what the script is doing at each step in the process. The reasoning for this is twofold: it lets you see the script as a whole and it gets you used to seeing comments in code (a habit which is worth picking up to ease long-term maintenance).

27.6.1. Example 1: Style Sheet Switcher

This function is an extreme simplification of the technique employed in Invasion of the Body Switchers (alistapart.com/articles/bodyswitchers) by Andy Clarke and James Edwards. It also makes use of John Resig's addEvent( ) function (quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html) for simple event management. It uses a single external CSS file to handle three different font sizes for the browser. We are going to change the font size of the page by changing a class on the body element.

We start with the external style sheet (switcher.css):

 body.normal {   font-size: 80%; } body.large {   font-size: 100%; } body.huge {   font-size: 150%; } h1 {   font-size: 2em; } p {   font-size: 1em; } 

Then we have our XHTML page, with a link to our CSS file, and a placeholder script referring to our JavaScript file (switcher.js):

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head>   <title>Switcher Example</title>   <meta http-equiv="content-type" content="text/html;     charset=iso-8859-1" />   <meta http-equiv="Content-Language" content="en-us" />   <link rel="stylesheet" type="text/css" media="screen"     href="switcher.css" />   <script type="text/javascript" src="/books/4/439/1/html/2/switcher.js"></script> </head> <body >   <div >     <h1>Title</h1>     <p>This is a paragraph.</p>     <p>This is another paragraph.</p>   </div>   <div>     <form  action="switch.php">       <fieldset>         <legend>Please choose a font size</legend>         <select name="size">           <option value="normal" selected="selected">Normal</option>           <option value="large">Large</option>           <option value="huge">Huge</option>         </select>         <input type="submit" value="Apply It" />       </fieldset>     </form>   </div> </body> </html> 

Before we get to the JavaScript, let's take a quick look at the XHTML being used. Notice that the switcher form has an action (switcher.php). Even though we will be taking control of this form with JavaScript, we've provided a server-side alternative for non-JavaScript-enabled browsers. This is a prime example of graceful degradation.

All right, now on to the JavaScript. As this script will have only one use per page, I am going to create it as an object literal (see Chapter 26):

 var switcher = {   body:       false, // the body element of the page   form:       false, // the switcher form   controller: false, // the controlling form element   init:       function(  ){ // the initialization function     /* check for method availability,        return if used methods are unsupported        or id-ed elements used are not available */     if( !document.getElementById ||         !document.getElementsByTagName ||         !document.getElementById( 'switcher_form' ) ) return;     // assign the body     switcher.body = document.getElementsByTagName( 'body' )[0];     // assign the form     switcher.form = document.getElementById( 'switcher_form' );     // assign the select element to the controller     switcher.controller = switcher.form.getElementsByTagName(                             'select' )[0];     // add an event     switcher.addEvent( switcher.controller, // to the controller                        'change',            /* trigger with the                                                onchange event */                        function(  ){          // run this function                          /* set the body's class equal to                             the value of the controller */                          switcher.body.className = this.value;                        } );     // get the submit button     var input = switcher.form.getElementsByTagName( 'input' )[0];     // delete it as our onchange event has made it redundant     input.parentNode.removeChild( input );   },   addEvent:   function( obj, type, fn ){  // the add event function     if (obj.addEventListener)       obj.addEventListener( type, fn, false );     else if (obj.attachEvent) {       obj["e"+type+fn] = fn;       obj[type+fn] = function(  ) {         obj["e"+type+fn]( window.event );       };       obj.attachEvent( "on"+type, obj[type+fn] );     }   } }; /* using the object's built-in addEvent function,    trigger this object's init(  ) method on page load */ switcher.addEvent( window, 'load', switcher.init ); 

27.6.2. Example 2: Page Glossary

This script is pageGlossary from Easy Designs (easy-designs.net/code/pageGlossary/). It traverses a specified portion of the document (identified by an id), collecting all of the abbreviation, acronym, and definition elements, and writes them out to the designated portion of the page (also identified by an id) as a formal page glossary. The script also removes duplicate entries and sorts the contents alphabetically. Here it is:

 var pageGlossary = {   getFrom:  false, // where to collect terms from   buildIn:  false, // where to place the glossary   glossArr: [],    // the working glossary as an array   usedArr:  [],    // terms we've used ( to track duplicates )   init:     function( fromId, toId ){ /* init(  ) takes two arguments:                                          * id of the collection area                                          * id of the destination */     // make sure the required methods and elements are available     if( !document.getElementById ||         !document.getElementsByTagName ||         !document.getElementById( fromId ) ||         !document.getElementById( toId ) ) return;     // set the collection area     pageGlossary.getFrom = document.getElementById( fromId );     // set the destination area     pageGlossary.buildIn = document.getElementById( toId );     // run the collection method (below)     pageGlossary.collect(  );     // if the glossary array has no members, quit now     if( pageGlossary.usedArr.length < 1 ) return;     // resort the array in alphabetical order using ksort (below)     pageGlossary.glossArr = pageGlossary.ksort(                               pageGlossary.glossArr );     // run the build method (below)     pageGlossary.build(  );   },   collect:  function(  ){                 // the collection method     /* get all the abbr, acronym and dfn elements        inside the collection area */     var dfns  = pageGlossary.getFrom.getElementsByTagName('dfn');     var abbrs = pageGlossary.getFrom.getElementsByTagName('abbr');     var acros = pageGlossary.getFrom.getElementsByTagName('acronym');     var arr = [];            // a temp array to hold the collections     // populate the temp array     arr = arr.concat( dfns, abbrs, acros );     // quit if nothing was collected     if( ( arr[0].length == 0 ) &&         ( arr[1].length == 0 ) &&         ( arr[2].length == 0 ) ) return;     // save processing time by storing the length of the raw array     var arrLength = arr.length;     // interate through the raw array     for( var i=0; i < arrLength; i++ ){       // store the nested array length       var nestedLength = arr[i].length;       // skip this array if it has no members       if( nestedLength < 1 ) continue;       // iterate through the array       for( var j=0; j < nestedLength; j++ ){         // make sure the element has some children         if( !arr[i][j].hasChildNodes(  ) ) continue;         // collect the term         var trm = arr[i][j].firstChild.nodeValue;         // collect the definition         var dfn = arr[i][j].getAttribute( 'title' );         // if this term is not in the used array         if( !pageGlossary.inArray( trm, pageGlossary.usedArr ) ){           // push it to the used array           pageGlossary.usedArr.push( trm );           /* and store its definition in the glossary array,              using the term as its key value */           pageGlossary.glossArr[trm] = dfn;         }       }     }   },   build:    function(  ){                 // the builder method     // create a level heading     var h2 = document.createElement('h2');     // have it read "Page Glossary"     h2.appendChild( document.createTextNode( 'Page Glossary' ) );     // create the definition list     var dl = document.createElement('dl');     // give it a class of pageGlossary     dl.className = 'pageGlossary';     // iterate through the glossary array     for( key in pageGlossary.glossArr ){       // create a definition term element       var dt = document.createElement( 'dt' );       // make its text the term       dt.appendChild( document.createTextNode( key ) );       // append it to the list       dl.appendChild( dt );       // create the definition data element       var dd = document.createElement('dd');       // make its text the definition       dd.appendChild( document.createTextNode(                         pageGlossary.glossArr[key] ) );       // append it to the list       dl.appendChild( dd );     }     // append the h2 to the target element     pageGlossary.buildIn.appendChild( h2 );     // append the dl to the target element     pageGlossary.buildIn.appendChild( dl );   },   addEvent: function( obj, type, fn ){  // the add event function     if (obj.addEventListener) obj.addEventListener( type, fn, false );     else if (obj.attachEvent) {       obj["e"+type+fn] = fn;       obj[type+fn] = function(  ) {         obj["e"+type+fn]( window.event );       };       obj.attachEvent( "on"+type, obj[type+fn] );     }   },   ksort:    function( arr ){            // the key sorting function     var rArr = [], tArr = [], n=0, i=0, el;     for( el in arr ) tArr[n++] = el + '|' + arr[el];     tArr = tArr.sort(  );     var arrLength = tArr.length;     for( var i=0; i < arrLength; i++ ){       var x = tArr[i].split( '|' );       rArr[x[0]] = x[1];     }     return rArr;   },   inArray:  function( n, h ){           // the inArray test     var l = h.length;     for( var i=0; i < l; i++ ){       if( h[i] === n ) return true;     }     return false;   } }; // add pageGlossary.init(  ) method to the page's onload event pageGlossary.addEvent( window, 'load', function(  ){                                          pageGlossary.init( 'content',                                                             'extras' );                                        } ); 




Web Design in a Nutshell
Web Design in a Nutshell: A Desktop Quick Reference (In a Nutshell (OReilly))
ISBN: 0596009879
EAN: 2147483647
Year: 2006
Pages: 325

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net