<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2805388939215597768</id><updated>2012-02-15T23:23:37.413-08:00</updated><category term='Free Ebook XML'/><category term='Free Ebook c++'/><category term='Free Ebook Java'/><category term='CSS'/><category term='Free Ebook Database'/><category term='Tip And Trick Photo Shop'/><category term='Free ebook Download'/><category term='PHP With Ajax'/><category term='Ebook Networking'/><category term='User Guide Totorial'/><category term='Ajax And CSS'/><category term='Free Ebook Maya'/><category term='Free ebook XP Registry Guide'/><category term='Free ebook Hacker'/><category term='Ajax'/><category term='Ajax Http Request'/><category term='Free Ebook Ajax'/><title type='text'>Free ebooks Download</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>90</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-8096508367525006588</id><published>2009-04-15T12:27:00.000-07:00</published><updated>2009-04-15T12:28:44.870-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax'/><title type='text'>Securing Ajax Applications</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://free-dowload-ebook-programing.blogspot.com/"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 146px; height: 192px;" src="http://1.bp.blogspot.com/_gX-JntSisq4/SaLDGOB4GLI/AAAAAAAAAy0/iL6C-gm-C28/s320/scuring+ajax.JPG" alt="free ebook download" id="BLOGGER_PHOTO_ID_5306017822608464050" border="0" /&gt;&lt;/a&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;July    2007&lt;br /&gt;$49.99    US,    $59.99    CAN&lt;br /&gt;ISBN:    9780596529314&lt;br /&gt;250    pgs &lt;br /&gt;Shelving:    web    programming&lt;br /&gt;User    Level:        intermediate    to&lt;br /&gt;advanced    web    developers&lt;br /&gt;Will    Sell    Like: &lt;br /&gt;0596101805,    Ajax Design Patterns&lt;/span&gt;&lt;br /&gt;&lt;a href="http://free-dowload-ebook-programing.blogspot.com/2009/02/securing-ajax-applications.html"&gt;Securing Ajax Applications&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;By Christopher wells&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In addition to the responsiveness that makes Ajax so appealing, Ajax can also create&lt;br /&gt;security laws that need to be addressed at the development stage. S&lt;a href="http://free-dowload-ebook-programing.blogspot.com/2009/02/securing-ajax-applications.html"&gt;ecuring Ajax Applications&lt;/a&gt; examines the challenges created by the new generation of web development, exploring these structures and looking for dangerous gaps.&lt;br /&gt;Download&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-8096508367525006588?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/8096508367525006588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2009/04/securing-ajax-applications.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/8096508367525006588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/8096508367525006588'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2009/04/securing-ajax-applications.html' title='Securing Ajax Applications'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SaLDGOB4GLI/AAAAAAAAAy0/iL6C-gm-C28/s72-c/scuring+ajax.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-2052188206749844449</id><published>2008-12-28T21:16:00.000-08:00</published><updated>2009-02-01T15:33:41.248-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>MANAGING THE METADATA OVERLOAD</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/managing-metadata-overload.html" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhfiGBKjFI/AAAAAAAAAVg/otoduKOyEE4/s320/meta.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;The Metadata palette provides much more information than the  average person will ever need. If you don't need all this "metadata overload,"  you can set it up so it only displays the data you care about, giving you a more  orderly, easier-to-read Metadata palette. To do this, go to the Metadata tab,  click on the right-facing triangle button to the right of the tab, and from the  pop-down menu, choose Metadata Display Options. In the dialog that appears,  uncheck any fields you don't need displayed, turn on the Checkbox at the bottom  for Hide Empty Fields, and click OK.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-2052188206749844449?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/2052188206749844449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/managing-metadata-overload.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2052188206749844449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2052188206749844449'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/managing-metadata-overload.html' title='MANAGING THE METADATA OVERLOAD'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVhfiGBKjFI/AAAAAAAAAVg/otoduKOyEE4/s72-c/meta.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-4385263567503595530</id><published>2008-12-28T21:05:00.000-08:00</published><updated>2009-02-01T15:35:06.734-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>HAVE PHOTOSHOP SELECT THE SHADOWS AND HIGHLIGHTS</title><content type='html'>&lt;div class="docText"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://3.bp.blogspot.com/_gX-JntSisq4/SVhbEoH24CI/AAAAAAAAAVY/OoJ6Ggsvj-E/s320/have.JPG" border="0" /&gt;&lt;/a&gt;This is a trick we use for prepress and for photo retouching  because it instantly lets you select all the shadow areas (or highlight areas if  you wish) for a particular image, and it's so easy because Photoshop does all  the work. To have Photoshop select just the shadow areas in your image, go under  the Select menu and choose Color Range. When the dialog appears, in the Select  pop-up menu, choose Shadows, and click OK. The Shadow areas are instantly  selected. This is ideal for situations where your scanner has plugged up the  detail in the shadow areas (pretty common in most sub-$1,000 desktop scanners).  Once the shadows are selected, you can "open them up" by going to Levels and  moving the Midtone Input Levels slider to the left to bring back some of the  shadow detail lost in the scan.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-4385263567503595530?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/4385263567503595530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/have-photoshop-select-shadows-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4385263567503595530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4385263567503595530'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/have-photoshop-select-shadows-and.html' title='HAVE PHOTOSHOP SELECT THE SHADOWS AND HIGHLIGHTS'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_gX-JntSisq4/SVhbEoH24CI/AAAAAAAAAVY/OoJ6Ggsvj-E/s72-c/have.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1051065495007522440</id><published>2008-12-28T20:44:00.000-08:00</published><updated>2009-01-26T12:26:42.953-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>TROUBLESHOOTING ACTIONS? SLOW DOWN!</title><content type='html'>&lt;div class="docText"&gt;If you're an advanced user, chances are you're no stranger to  using actions, and in fact, you probably create your own (rather than using the  default actions that ship with Photoshop, many of which redefine the term  "useless"). If you do create your own actions, you've already found that you  spend more time troubleshooting your actions than you do creating them in the  first place. Well, this little tip makes the troubleshooting process a lot  easier, and saves you both time and frustration. The problem is (and this won't  sound like a problem) Photoshop runs actions so quickly that you don't see each  step, or each dialog, so tracking down a missing or wrong step is just about  impossible. Luckily, you can actually slow down your action, or even put a pause  between each step, by using Photoshop's Playback Options dialog found in the  Actions palette's pop-down menu. When it appears, you can choose to play your  action Step by Step, seeing everything as it happens, or you can choose to enter  the number of seconds you'd like it to pause. Then, when you replay the action,  you can see everything step by step and track down the culprit.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1051065495007522440?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1051065495007522440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/troubleshooting-actions-slow-down.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1051065495007522440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1051065495007522440'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/troubleshooting-actions-slow-down.html' title='TROUBLESHOOTING ACTIONS? SLOW DOWN!'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5759167451466712959</id><published>2008-12-28T20:40:00.000-08:00</published><updated>2009-02-01T15:48:47.449-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>ACCESSING GRAYED-OUT FILTERS IN CMYK</title><content type='html'>&lt;div class="docText"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/accessing-grayed-out-filters-in-cmyk.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhU9r40i9I/AAAAAAAAAVQ/vRKkyxML4js/s320/accesing.JPG" border="0" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;One of the bad things about converting from RGB mode to CMYK  mode is that many of Photoshop's coolest filters can only be applied in RGB  mode, and once you're in CMYK mode, many of them are "grayed out" in the Filter  menu, so they can't be accessed. So what do you do if you really want to use one  of those filters? (Whatever you do, don't convert back to RGB mode, then back to  CMYK. That's image suicide.) Instead, try this tip: In the Channels palette,  click on the Cyan channel. Go to the Filters menu and you'll notice that all  those grayed-out filters are now suddenly available. All you have to do now is  apply the filter you want to each channel individually (once each on Cyan,  Magenta, Yellow, and finally the Black channel), and the filter will appear as  though you applied it to the entire image (in reality, you didyou just did it  the more laborious way). One way to speed up this process is to create an action  that will do it all for you with one click of the mouse.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5759167451466712959?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5759167451466712959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/accessing-grayed-out-filters-in-cmyk.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5759167451466712959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5759167451466712959'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/accessing-grayed-out-filters-in-cmyk.html' title='ACCESSING GRAYED-OUT FILTERS IN CMYK'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVhU9r40i9I/AAAAAAAAAVQ/vRKkyxML4js/s72-c/accesing.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-66834923318232975</id><published>2008-12-28T20:35:00.000-08:00</published><updated>2009-02-01T15:49:57.660-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>MORE CONTROL OVER FILTERS</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/more-control-over-filters.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://3.bp.blogspot.com/_gX-JntSisq4/SVhUNgmmWQI/AAAAAAAAAVI/lxAdzqfCano/s320/more.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;We love Photoshop's Fade command (which acts like an "undo on a  slider"), and when it comes to applying filters, we use it all the time to gain  more control (including blending mode control) over filters we apply. The only  downside to the Fade command is you can only use it one timeyou get one  opportunity to Fade, or choose a Blend Mode, then you're stuck. Here's a tip to  keep the control of your filters for as long as you'd like: When you're about to  apply a filter, make a duplicate of the layer where you're applying the filter,  then apply it. This keeps the application of your filter fully editableyou can  change Blend Modes as often as you like, change Opacity, add a Layer Mask to  determine where the filter shows and where it doesn't, or even toss the layer in  the Trash and start all over.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-66834923318232975?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/66834923318232975/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/more-control-over-filters.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/66834923318232975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/66834923318232975'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/more-control-over-filters.html' title='MORE CONTROL OVER FILTERS'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_gX-JntSisq4/SVhUNgmmWQI/AAAAAAAAAVI/lxAdzqfCano/s72-c/more.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-2942661035730442148</id><published>2008-12-28T20:33:00.000-08:00</published><updated>2009-02-01T15:51:48.684-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>ASSIGNING METADATA TO MULTIPLE FILES</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/assigning-metadata-to-multiple-files.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://2.bp.blogspot.com/_gX-JntSisq4/SVhTQ03kPMI/AAAAAAAAAU0/6QipTN8xajA/s320/apply.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;Want to assign metadata to more than one photo at a time?  (Perhaps you want to embed your copyright info into 30 or more photos at once.)  Just Command-click (PC: Control-click) on all the photos you want to affect,  then enter the custom info you want (in one of the IPTC fields in the Metadata  palette) and that info will be added to every selected photo at once.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-2942661035730442148?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/2942661035730442148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/assigning-metadata-to-multiple-files.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2942661035730442148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2942661035730442148'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/assigning-metadata-to-multiple-files.html' title='ASSIGNING METADATA TO MULTIPLE FILES'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_gX-JntSisq4/SVhTQ03kPMI/AAAAAAAAAU0/6QipTN8xajA/s72-c/apply.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5709693025752874503</id><published>2008-12-28T20:30:00.000-08:00</published><updated>2009-02-01T15:52:57.407-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>APPLYING MULTIPLE FILTERS? NOT ON MY LAYER!</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/applying-multiple-filters-not-on-my.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://3.bp.blogspot.com/_gX-JntSisq4/SVhSmiSCe7I/AAAAAAAAAUc/0WHugWoueEE/s320/apply.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;Thinking of applying a number of different filters to a  particular layer? Don't do it. Instead, make a copy of your layer, then apply  the first filter. Make another copy of the layer and apply the second filter;  make another copy, apply the third filter, and so on. You can use Photoshop's  Layer Blend Modes to get the effect that one filter is applied on top of the  others, and now you've got full control over each individual filter applied. If  you don't like one of the filters, just drag that layer into the Trash. Better  yet, you've got Blend and Opacity control you wouldn't have by simply applying  filter over filter.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5709693025752874503?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5709693025752874503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/applying-multiple-filters-not-on-my.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5709693025752874503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5709693025752874503'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/applying-multiple-filters-not-on-my.html' title='APPLYING MULTIPLE FILTERS? NOT ON MY LAYER!'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_gX-JntSisq4/SVhSmiSCe7I/AAAAAAAAAUc/0WHugWoueEE/s72-c/apply.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5349258049821036593</id><published>2008-12-28T20:29:00.001-08:00</published><updated>2009-01-26T12:26:42.954-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>NEW SNAPSHOT, THE MISTAKE INSURANCE POLICY</title><content type='html'>&lt;div class="docText"&gt;The great thing about Photoshop's History feature is that you  can (by default) undo your last 20 steps. Perhaps even more important is that  you can always return to how the image looked when you opened it, so you never  really do any permanent damage (as long as the file is open). However, what if  you opened an image, worked on it for a while, and it was really looking great,  but about 10 minutes later, it took a turn for the worse (this happens to us  more often than we'd care to admit). If you undo the last 20 steps, it may not  take you back far enough to the point that you want to return to, and the only  other choice is to go all the way back to where you started. Here's a tip to  keep you from pulling your hair out: Any time your image is at a stage where you  think it looks pretty good, go to the History palette, and at the bottom of the  palette, click on the New Snapshot button. Think of it as an insurance policy so  that if things go bad, you can at least return to that spot and try again. It's  not a bad idea to create a new Snapshot about every five minutes when you're  working on a big project. To keep from loading up on snapshots, when you create  a new one, delete one or two snapshots before it.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5349258049821036593?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5349258049821036593/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/new-snapshot-mistake-insurance-policy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5349258049821036593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5349258049821036593'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/new-snapshot-mistake-insurance-policy.html' title='NEW SNAPSHOT, THE MISTAKE INSURANCE POLICY'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-643557104831011565</id><published>2008-12-28T20:12:00.000-08:00</published><updated>2009-02-01T15:55:44.587-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>3D PRINT EFFECTS (AND WHERE TO GET THOSE GOOFY GLASSES)</title><content type='html'>&lt;h3 class="docSection1Title"&gt;&lt;/h3&gt;&lt;div class="docText"&gt;For a brief time back in the 1950s, &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/3d-print-effects-and-where-to-get-those.html"&gt;3D movies&lt;/a&gt; were all the  rage, but it was short-lived, probably because you had to wear those  cheesy-&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/3d-print-effects-and-where-to-get-those.html"&gt;looking 3D glasse&lt;/a&gt;s to experience the effect. Although &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/3d-print-effects-and-where-to-get-those.html"&gt;3D &lt;/a&gt;has come a long  way since then, unfortunately you still have to wear the cheesy glasses. Be that  as it may, the &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/3d-print-effects-and-where-to-get-those.html"&gt;3D effect&lt;/a&gt; is starting to appear again in print ads in trendy  magazines, which generally include the paper 3D glasses in the magazine. This  effect can be created in Photoshop, no problem. The hardest part is finding a  supplier &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/3d-print-effects-and-where-to-get-those.html"&gt;for 3D glasses&lt;/a&gt; (okay, we'll help on that part too. &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/3d-print-effects-and-where-to-get-those.html"&gt;Try 3D Glasse&lt;/a&gt;s  Direct at &lt;a class="docLink" href="http://www.3dglasses.net/" target="_blank"&gt;www.3dglasses.net&lt;/a&gt;). Here's a tip on how to create the 3D  effect in Photoshop: Open an RGB image, then go to the Channels palette and  click on the Red channel. Go under the Filter menu, under Other, and choose  Offset. For Horizontal enter 5 and leave Vertical set to zero. For Undefined  Areas, choose Repeat Edge Pixels, then click OK. In the Channels palette, click  on the RGB channel to reveal the effect. Then, lastly, you have to determine  which part you want to appear as "coming out of the image" toward the person  viewing it. Switch to the History Brush and using a soft-edged brush, paint over  the area you want to "jump out" from the image. As you paint with the History  Brush, you'll see your original untouched image paint back in (don't sweat it;  that's what it's supposed to do). Now all you have to do is order the  glasses.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-643557104831011565?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/643557104831011565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/3d-print-effects-and-where-to-get-those.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/643557104831011565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/643557104831011565'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/3d-print-effects-and-where-to-get-those.html' title='3D PRINT EFFECTS (AND WHERE TO GET THOSE GOOFY GLASSES)'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7197799351418958330</id><published>2008-12-28T20:10:00.000-08:00</published><updated>2009-02-01T15:57:19.727-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>CREATING REUSABLE DIAGONAL GUIDES</title><content type='html'>&lt;div class="docText"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/creating-reusable-diagonal-guides.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhOCmYofgI/AAAAAAAAAT0/adETQBW3vKE/s320/creating.JPG" border="0" /&gt;&lt;/a&gt; &lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;If you've used Photoshop's rulers at all, you know that you  have your choice of either a vertical or horizontal guide. That's not a bad  thing, but there's one thing missinga diagonal guide. Since Photoshop doesn't  have one, here's a tip for making your own: Start by creating a new layer, then  set your Foreground to R=74, G=132, B=255 (the color Photoshop uses for its  built-in guides). Switch to the Line tool found in the Shapes tools, and on this  new layer draw a diagonal line where you want your guide to appear (make sure  you have Create Filled Region selected in the Options Bar). It's not a bad idea  to copy that layer into a separate document and save it on your driveso any time  you need a diagonal line, you can just open that document and drag it right  in.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7197799351418958330?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7197799351418958330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/creating-reusable-diagonal-guides.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7197799351418958330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7197799351418958330'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/creating-reusable-diagonal-guides.html' title='CREATING REUSABLE DIAGONAL GUIDES'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVhOCmYofgI/AAAAAAAAAT0/adETQBW3vKE/s72-c/creating.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-3599798454691319727</id><published>2008-12-28T20:07:00.000-08:00</published><updated>2009-02-01T15:58:13.023-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>LOCKING YOUR TABLET BRUSH SETTINGS</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/locking-your-tablet-brush-settings.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://2.bp.blogspot.com/_gX-JntSisq4/SVhNVZzOebI/AAAAAAAAATs/fjeSjVtdg3M/s320/lokking.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Since Photoshop 7, the one thing that drove Wacom tablet users insane was that  you couldn't lock in your pressure sensitivity settings without saving a special  custom brush. Luckily, that all changed in Photoshop CS, and you can now lock in  your pressure settings. Go to the Brushes palette and choose Expanded View in  its drop-down menu. Then, in the left column of brush options, you'll see a  little lock icon to the right of each category. Turn on Pen Pressure (or any of  the tablet settings from the pop-up menus) then click the lock icon, and as you  change and tweak brushes, your Pen Pressure stays locked in&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-3599798454691319727?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/3599798454691319727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/locking-your-tablet-brush-settings.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/3599798454691319727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/3599798454691319727'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/locking-your-tablet-brush-settings.html' title='LOCKING YOUR TABLET BRUSH SETTINGS'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_gX-JntSisq4/SVhNVZzOebI/AAAAAAAAATs/fjeSjVtdg3M/s72-c/lokking.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1841815894260046826</id><published>2008-12-28T20:05:00.000-08:00</published><updated>2009-02-01T16:00:16.640-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>THE SECRETS OF SEARCHING IN THE BROWSER</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/secrets-of-searching-in-browser.html" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://4.bp.blogspot.com/_gX-JntSisq4/SVhMyAW9R6I/AAAAAAAAATk/19yNUKnN7fo/s320/scrret.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;Don't get caught in the trap of thinking that you have to  assign keywords to your photos before you can start using the File Browser's  Search function (although keywords certainly make it easier). But to find out  just how much power the search function really has, just click on the binoculars  icon in the Toolbar at the top of the File Browser, then click-and-hold the  first Criteria pop-up menu. If you remember you shot the photo you're looking  for with a certain camera, you can search the EXIF data for that make and model.  You can also search by Rank, whether it was flagged or not, and a host of other  criteria.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1841815894260046826?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1841815894260046826/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/secrets-of-searching-in-browser.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1841815894260046826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1841815894260046826'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/secrets-of-searching-in-browser.html' title='THE SECRETS OF SEARCHING IN THE BROWSER'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_gX-JntSisq4/SVhMyAW9R6I/AAAAAAAAATk/19yNUKnN7fo/s72-c/scrret.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1803842885380941583</id><published>2008-12-28T20:01:00.000-08:00</published><updated>2009-02-01T16:00:53.122-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>DRAG-AND-DROP CURVES FOR QUICK CORRECTION</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/drag-and-drop-curves-for-quick.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhMDsgQm6I/AAAAAAAAATc/aA1aYbt546o/s320/drag.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;If you're color-correcting a number of images that are basically the same (for  example, catalog shots or high school yearbook shots, where the lighting and  composition are pretty much the same), you may want to apply the same Curve  setting to a number of images. Rather than saving the Curve setting and loading  it each time, try this tip: Use a Curves Adjustment layer, and then just  drag-and-drop that layer from your current image to your target image.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1803842885380941583?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1803842885380941583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/drag-and-drop-curves-for-quick.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1803842885380941583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1803842885380941583'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/drag-and-drop-curves-for-quick.html' title='DRAG-AND-DROP CURVES FOR QUICK CORRECTION'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVhMDsgQm6I/AAAAAAAAATc/aA1aYbt546o/s72-c/drag.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1955914972470680767</id><published>2008-12-28T19:59:00.000-08:00</published><updated>2009-02-01T16:01:37.347-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>ACTIONS POWER TIP: ADD AN ACTION TO YOUR ACTION</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/actions-power-tip-add-action-to-your.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhLVS755UI/AAAAAAAAATU/h3l7VZv2Pqc/s320/action.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;Here's an Actions power tip: Did you know that you can build an  action that will include an existing action? Here's how it's done: As you're  recording your action, just go to the Actions palette, click on the existing  action you want to include in your current action, and press the Play button at  the bottom of the Actions palette. The existing action will now be added as a  step in your current action (pretty scary stuff).&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1955914972470680767?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1955914972470680767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/actions-power-tip-add-action-to-your.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1955914972470680767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1955914972470680767'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/actions-power-tip-add-action-to-your.html' title='ACTIONS POWER TIP: ADD AN ACTION TO YOUR ACTION'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVhLVS755UI/AAAAAAAAATU/h3l7VZv2Pqc/s72-c/action.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5693950238400248315</id><published>2008-12-28T19:55:00.000-08:00</published><updated>2009-02-01T16:02:33.420-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>PREPRESS CLEANUPSIN A SNAP</title><content type='html'>&lt;h3 class="docSection1Title"&gt;&lt;/h3&gt;&lt;div class="docText"&gt;This is a great tip if you're zoomed in close to an image for  retouching, or checking it in prepress for spots or specs, because it lets you  check the entire image in a very methodical wayusing your keyboard to navigate  zone by zone. Here's how:&lt;/div&gt;&lt;ul&gt;&lt;li&gt; &lt;div class="docList"&gt;Press the &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/prepress-cleanupsin-snap.html"&gt;HOME&lt;/a&gt; key to jump to the upper left corner of your  image window.&lt;/div&gt;&lt;/li&gt;&lt;li&gt; &lt;div class="docList"&gt;Press the END key to jump to the lower right corner of your  image window.&lt;/div&gt;&lt;/li&gt;&lt;li&gt; &lt;div class="docList"&gt;Press the P&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/prepress-cleanupsin-snap.html"&gt;AGE UP&lt;/a&gt; key to scroll upward one full screen.&lt;/div&gt;&lt;/li&gt;&lt;li&gt; &lt;div class="docList"&gt;Press the&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/prepress-cleanupsin-snap.html"&gt; PAGE DOWN&lt;/a&gt; key to scroll downward one full screen.&lt;/div&gt;&lt;/li&gt;&lt;li&gt; &lt;div class="docList"&gt;Press Command-PAGE UP (PC: Control-PAGE UP) to scroll one full  screen to the left.&lt;/div&gt;&lt;/li&gt;&lt;li&gt; &lt;div class="docList"&gt;Press Command-PAGE DOWN (PC: Control-PAGE DOWN) to scroll one  full screen to the right.&lt;/div&gt;&lt;div class="docList"&gt;Once you've learned these shortcuts, you can start by pressing  the Home key (jumping you to the upper left-hand corner of your image). Clean  that area then press the Page Down key to move methodically down the left side  of your image until you reach the bottom of your window. Then press Command-Page  Up (PC: Control-Page Down) to move one screen to the right, clean that area,  then press the Page Up key to move methodically up the image until you reach the  top. Repeat these steps until you're finished. The advantage of doing it this  way, besides the sheer speed of using keyboard shortcuts, is that you'll see  every area of the image without missing a spot.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5693950238400248315?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5693950238400248315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/prepress-cleanupsin-snap.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5693950238400248315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5693950238400248315'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/prepress-cleanupsin-snap.html' title='PREPRESS CLEANUPSIN A SNAP'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-455293830443085047</id><published>2008-12-28T19:53:00.000-08:00</published><updated>2009-02-01T16:03:07.939-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>BLEND MODE POWER TIP</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/blend-mode-power-tip.html" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://2.bp.blogspot.com/_gX-JntSisq4/SVhJ8bU2LvI/AAAAAAAAATM/yUVYJ1Bd-Rc/s320/blend2.JPG" border="0" /&gt;&lt;/a&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/blend-mode-power-tip.html" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhJ4gUoMbI/AAAAAAAAATE/oO81skSP5KE/s320/blend.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;Once you understand layer Blend Modes, you wind up using them  all the time. Chances are by now you know which individual modes you want to use  (such as Overlay, Multiply, Soft Light, Hard Light, Screen) and which ones  you'll probably never use (such as Dissolve). If you know which ones you want to  use, you can use a keyboard shortcut to jump right to the Blend Mode you want.  For example, to jump to the Overlay mode for a layer, press Shift-Option (PC:  Shift-Alt) and the first letter of the mode you want, in this case, the letter  "O" (making the shortcut Shift-Option-O [PC: Shift-Alt-O]). For Screen mode,  you'd press Shift-Option-S (PC: Shift-Alt-S), and so on. (Note: If you have a  tool selected that has a Blend Mode in its Options Bar, the keyboard shortcut  will change that Blend Mode instead of the layer Blend Mode.)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-455293830443085047?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/455293830443085047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/blend-mode-power-tip.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/455293830443085047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/455293830443085047'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/blend-mode-power-tip.html' title='BLEND MODE POWER TIP'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_gX-JntSisq4/SVhJ8bU2LvI/AAAAAAAAATM/yUVYJ1Bd-Rc/s72-c/blend2.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-4416354128543766652</id><published>2008-12-28T19:49:00.000-08:00</published><updated>2009-02-01T16:03:39.053-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>MAKING CHANGES TO RAW PHOTOS WITHOUT OPENING THEM</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/making-changes-to-raw-photos-without.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://2.bp.blogspot.com/_gX-JntSisq4/SVhJBLxrGnI/AAAAAAAAAS8/LMUgUW0akCU/s320/making+changes.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;This is a pretty slick trickediting Raw photos without actually  opening them in Photoshop, well, technically. Here's how it's done: Open the Raw  digital camera image from within the File Browser, and it brings up the Camera  Raw dialog. Make the tonal processing changes you want within the Camera Raw  interface, but DON'T click OK. Instead, hold the Option key (PC: Alt key) and  you'll see the OK button change into an Update button. Click on it (when it says  Update) and Camera Raw will close, without the photo opening in Photoshop, but  the changes you made will be visibly applied to the thumbnail in the File  Browser. (Note: Like all changes in the Browser, they will not be applied until  you actually open the photo in Photoshop.)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-4416354128543766652?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/4416354128543766652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/making-changes-to-raw-photos-without.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4416354128543766652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4416354128543766652'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/making-changes-to-raw-photos-without.html' title='MAKING CHANGES TO RAW PHOTOS WITHOUT OPENING THEM'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_gX-JntSisq4/SVhJBLxrGnI/AAAAAAAAAS8/LMUgUW0akCU/s72-c/making+changes.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-626643674684830315</id><published>2008-12-28T19:48:00.000-08:00</published><updated>2009-02-01T16:04:16.060-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>NO MORE CREATING TYPE IN CHANNELS</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/no-more-creating-type-in-channels.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://2.bp.blogspot.com/_gX-JntSisq4/SVhIn79URdI/AAAAAAAAAS0/YIMEMsoFTtE/s320/nomore.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;If you've ever tried to create and format type in a Channel,  you know what a pain it can be. Especially because, when you're working in a  channel, it doesn't create an editable Type layer, so you're really limited as  to how you can format and of course, edit your type. So instead of creating type  in a channel (which many special channel-type effects call for), just create  your type on a layer as usual. In fact, don't go to the Channels palette at  alljust pretend you're not using channels. Once you've got your type formatted  and adjusted just the way you want it on your regular Type layer, Command-click  (PC: Control-click) on your Type layer's name in the Layers palette. This puts a  selection around your type. Now you can go under the Select menu and choose Save  Selection. When the dialog appears, click OK, and it saves your perfectly  formatted type as (you guessed it) a channel. Now you can delete your Type  layer, and you're left with an Alpha channel with perfectly formatted type.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-626643674684830315?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/626643674684830315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/no-more-creating-type-in-channels.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/626643674684830315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/626643674684830315'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/no-more-creating-type-in-channels.html' title='NO MORE CREATING TYPE IN CHANNELS'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_gX-JntSisq4/SVhIn79URdI/AAAAAAAAAS0/YIMEMsoFTtE/s72-c/nomore.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-4334893398495009313</id><published>2008-12-28T19:47:00.001-08:00</published><updated>2009-02-01T16:04:50.516-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>LET PHOTOSHOP TELL YOU THE HIGHLIGHT AND SHADOW</title><content type='html'>&lt;div class="docText"&gt;We use this tip to have Photoshop help us determine which are  the darkest (shadow) points and which are the lightest (highlight) points in an  image when we're color correcting. We start by choosing a Threshold Adjustment  layer from the bottom of the Layers palette. When the Threshold dialog appears,  we drag the slider all the way to the left and the image turns completely white.  We then slowly &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/let-photoshop-tell-you-highlight-and.html"&gt;drag the slider &lt;/a&gt;back to the right, and the first black pixels  that appear on screen are the shadow areas. We make a mental note of that area  as our shadow point. Then we drag the slider all the way to the far right (the  image turns black). As we drag slowly back toward the left, the first white  pixels that appear are the highlight points in the image. We note them as well.  &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/let-photoshop-tell-you-highlight-and.html"&gt;We &lt;/a&gt;now know where the shadow and highlight points are in the image, and we can  use them, along with the Eyedropper tools in the Curves dialog, to set the  proper shadow and highlight areas to remove any color casts. Note: When you've  determined where the shadow and highlight areas are, you can then delete the  Threshold Adjustment layer by dragging it into the Trash icon at the bottom of  the Layers palette.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-4334893398495009313?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/4334893398495009313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/let-photoshop-tell-you-highlight-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4334893398495009313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4334893398495009313'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/let-photoshop-tell-you-highlight-and.html' title='LET PHOTOSHOP TELL YOU THE HIGHLIGHT AND SHADOW'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-8971070472828239734</id><published>2008-12-28T19:45:00.000-08:00</published><updated>2009-02-01T16:05:34.549-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>USING THE LASSODON'T STOP TO NAVIGATE</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/using-lassodont-stop-to-navigate.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhIAdXZ9-I/AAAAAAAAASs/y9iCBxHADEg/s320/using.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;If you're using the Lasso tool, you have a surprising amount of navigation  control, even while you're dragging out your selection. For example, if you're  drawing a selection and you need to scroll over a bit, just press-and-hold the  Spacebar, and right where your cursor is, the Hand tool will appear and you can  move the image while you're still selecting (try it once and you'll see what we  mean). When you let go of the Spacebar, you're right where you left off, and you  can continue your selection. Here's &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/using-lassodont-stop-to-navigate.html"&gt;another&lt;/a&gt; Lasso tip: If you're drawing a  selection and reach the edge of your document window and need to scroll over,  hold the Option key (PC: Alt key), let go of the mouse button, move your mouse  to the edge of your image window, and you can nudge the screen over (again, this  is one you have to try once to understand it). It's like you're using the Lasso  tool to slide the image over. When you're done sliding, press the mouse button  and release Option/Alt to continue selecting. Incidentally, while selecting, you  can also use the Command- + (plus) and Command- (minus) zoom in/zoom out tricks  (PC: Control- + and Control- ).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-8971070472828239734?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/8971070472828239734/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/using-lassodont-stop-to-navigate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/8971070472828239734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/8971070472828239734'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/using-lassodont-stop-to-navigate.html' title='USING THE LASSODON&apos;T STOP TO NAVIGATE'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVhIAdXZ9-I/AAAAAAAAASs/y9iCBxHADEg/s72-c/using.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1447774926893660614</id><published>2008-12-28T19:38:00.000-08:00</published><updated>2009-02-01T16:06:08.081-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>LOAD ANY SAVED SELECTION WITHOUT THE CHANNELS PALETTE</title><content type='html'>&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/load-any-saved-selection-without.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://4.bp.blogspot.com/_gX-JntSisq4/SVhHlO4xi2I/AAAAAAAAASk/Ziy8Ydi3vBk/s320/load.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you're working on an RGB image and you've saved a selection (by drawing a  selection and choosing Save Selection from the Select menu), you can instantly  reload that selection at any time, without going to the Channels palette. If you  have only one saved selection, just press Option-Command-4 (PC: Alt-Control-4),  and the selection will instantly appear onscreen. If you have a second saved  selection, press Option-Command-5 (PC: Alt-Control-5), and so on. The key to  remember is that the RGB channels take up the first three spots, so always start  with 4 to load your first Alpha channel. Note: If you're working with CMYK  images, remember to always start with 5, because the CMYK channels take up the  first four spots.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1447774926893660614?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1447774926893660614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/load-any-saved-selection-without.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1447774926893660614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1447774926893660614'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/load-any-saved-selection-without.html' title='LOAD ANY SAVED SELECTION WITHOUT THE CHANNELS PALETTE'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_gX-JntSisq4/SVhHlO4xi2I/AAAAAAAAASk/Ziy8Ydi3vBk/s72-c/load.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7623851840702805809</id><published>2008-12-28T19:31:00.000-08:00</published><updated>2009-02-01T16:07:08.190-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>PLOT MULTIPLE CURVE POINTS IN JUST ONE CLICK</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/plot-multiple-curve-points-in-just-one.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhF5K3GweI/AAAAAAAAASc/bq3ilqMkIS4/s320/plot.JPG" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;Earlier in the book, we showed you how Photoshop will plot a  point on the curve for you if you Command-click (PC: Control-click) on a color  in your image you want plotted. However, there's a power tip that we waited  until now to shareif you add the Shift key, making it Shift-Command-click (PC:  Shift-Control-click), Photoshop will add a point for that spot on all the color  channels for you. This works in both RGB and&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/making-color-picker-show-cmyk.html"&gt; CMYK modes.&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7623851840702805809?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7623851840702805809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/plot-multiple-curve-points-in-just-one.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7623851840702805809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7623851840702805809'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/plot-multiple-curve-points-in-just-one.html' title='PLOT MULTIPLE CURVE POINTS IN JUST ONE CLICK'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVhF5K3GweI/AAAAAAAAASc/bq3ilqMkIS4/s72-c/plot.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-2660811699299801150</id><published>2008-12-28T19:29:00.000-08:00</published><updated>2009-01-26T12:26:42.956-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>TOUGH SELECTION TIP</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_gX-JntSisq4/SVhEKEFtWXI/AAAAAAAAASU/3RpA27lRmIg/s1600-h/selection1.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;/a&gt;&lt;a href="http://3.bp.blogspot.com/_gX-JntSisq4/SVhEHZxzD2I/AAAAAAAAASM/Q6iR2I7lo8k/s1600-h/selection.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_gX-JntSisq4/SVhEHZxzD2I/AAAAAAAAASM/Q6iR2I7lo8k/s320/selection.JPG" /&gt;&lt;/a&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_gX-JntSisq4/SVhEKEFtWXI/AAAAAAAAASU/3RpA27lRmIg/s320/selection1.JPG" /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;If you're struggling to make a selection of an image that's  against either a background of a similar color or a very busy background, here's  a masking tip to make the process easier: Add a Levels or Curves Adjustment  layer above your image layer, and use it to dramatically increase the contrast  in the image to help make the edges stand out. This will often help make the  difference between the object's edge and the background more obvious. The great  part is, you can totally damage the look of the image because you're using an  Adjustment layer. When your selection is in place, just drag the Adjustment  layer into the Trash icon to delete it, and your image is back to normal, but  you've got that "impossible" selection still in place.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-2660811699299801150?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/2660811699299801150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/tough-selection-tip.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2660811699299801150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2660811699299801150'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/tough-selection-tip.html' title='TOUGH SELECTION TIP'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_gX-JntSisq4/SVhEHZxzD2I/AAAAAAAAASM/Q6iR2I7lo8k/s72-c/selection.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7022374609634290488</id><published>2008-12-28T19:27:00.000-08:00</published><updated>2009-01-26T12:26:42.956-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>MAKING THE COLOR PICKER SHOW CMYK</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_gX-JntSisq4/SVhD25WHCrI/AAAAAAAAASE/ehplyWtX5Rg/s1600-h/making.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhD25WHCrI/AAAAAAAAASE/ehplyWtX5Rg/s320/making.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;If you're working in CMYK mode and you go to the Color Picker,  it still displays RGB colors. This is a bit of a problem, because you think  you're picking one color, but when you start to paint or fill with that color,  you get the CMYK desaturated version. Here's a tip to get around that. When  you're in CMYK mode and you go to the Color Picker, press Command-Y (PC:  Control-Y), which is the shortcut for Proof Colors (found under the View menu).  When you do this with the Color Picker open, it changes all the colors in the  Color Picker to CMYK colors. That way, when you pick a color in the Color  Picker, it looks the same when you paint or fill with it in your CMYK image.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7022374609634290488?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7022374609634290488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/making-color-picker-show-cmyk.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7022374609634290488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7022374609634290488'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/making-color-picker-show-cmyk.html' title='MAKING THE COLOR PICKER SHOW CMYK'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVhD25WHCrI/AAAAAAAAASE/ehplyWtX5Rg/s72-c/making.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-2161532353057088339</id><published>2008-12-28T19:20:00.000-08:00</published><updated>2009-01-26T12:26:42.956-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>MOVING MULTIPLE CURVE POINTS AT ONCE</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_gX-JntSisq4/SVhCVMuuhdI/AAAAAAAAARs/ITGE6kJ_cLY/s1600-h/moving.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhCVMuuhdI/AAAAAAAAARs/ITGE6kJ_cLY/s320/moving.JPG" /&gt;&lt;/a&gt;&lt;a href="http://1.bp.blogspot.com/_gX-JntSisq4/SVhDcd8Z5UI/AAAAAAAAAR0/5WZ5WTkSgAY/s1600-h/moving2.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhDcd8Z5UI/AAAAAAAAAR0/5WZ5WTkSgAY/s320/moving2.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;If you're working in the Curves dialog and you want to make  more than one point active at the same time, click on one point (to make it  active), then hold the Shift key and click on another. As long as the Shift key  is held down, you can click on as many points as you'd like to make them active  at the same time.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-2161532353057088339?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/2161532353057088339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/moving-multiple-curve-points-at-once.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2161532353057088339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2161532353057088339'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/moving-multiple-curve-points-at-once.html' title='MOVING MULTIPLE CURVE POINTS AT ONCE'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVhCVMuuhdI/AAAAAAAAARs/ITGE6kJ_cLY/s72-c/moving.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-543276175453285023</id><published>2008-12-28T18:50:00.000-08:00</published><updated>2009-01-26T12:28:38.920-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>ADD TO YOUR SELECTIONS THROUGH THE CHANNELS PALETTE</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_gX-JntSisq4/SVhBjpdU4MI/AAAAAAAAARk/joQgfanIuhw/s1600-h/add.GIF" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_gX-JntSisq4/SVhBjpdU4MI/AAAAAAAAARk/joQgfanIuhw/s320/add.GIF" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;If you've got the Channels palette open and you have multiple  saved Alpha channels, you can load any Alpha channel as a selection by holding  the Command key (PC: Control key) and clicking directly on the channel's name.  This instantly loads the selection. An even better tip: If you hold the Command  key (PC: Control key) then add the Shift key (making it  Shift-Command/Shift-Control) and click on another Alpha channel, it adds that to  your current selection. You can keep adding more selections to your original  selection until, well, until you run out of Alpha channels.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-543276175453285023?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/543276175453285023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/add-to-your-selections-through-channels.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/543276175453285023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/543276175453285023'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/add-to-your-selections-through-channels.html' title='ADD TO YOUR SELECTIONS THROUGH THE CHANNELS PALETTE'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVhBjpdU4MI/AAAAAAAAARk/joQgfanIuhw/s72-c/add.GIF' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-4728096552446090738</id><published>2008-12-28T18:48:00.000-08:00</published><updated>2009-01-26T12:28:38.920-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>EMBEDDING PATHS INTO ACTIONS</title><content type='html'>&lt;div class="docText"&gt;&lt;a href="http://1.bp.blogspot.com/_gX-JntSisq4/SVg6oqcYqOI/AAAAAAAAARU/MXGfDah_70g/s1600-h/embeding.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_gX-JntSisq4/SVg6oqcYqOI/AAAAAAAAARU/MXGfDah_70g/s320/embeding.JPG" /&gt;&lt;/a&gt;&lt;a href="http://1.bp.blogspot.com/_gX-JntSisq4/SVg6sXt5oVI/AAAAAAAAARc/7Z8GZOSo8mE/s1600-h/embeding1.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_gX-JntSisq4/SVg6sXt5oVI/AAAAAAAAARc/7Z8GZOSo8mE/s320/embeding1.JPG" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="docText"&gt;If you're creating actions and you want your action to include  a path that you've created, you can do that, but you have to draw your path  first, before you record your action. Once you've drawn your path, and it comes  to the part of your action that requires the path, go to the Action palette's  pop-down menu and choose Insert Path and that path will be stored along with the  action.&lt;/div&gt;&lt;a href="http://draft.blogger.com/25031535.html"&gt;&lt;img alt="" border="0" height="1" src="images/pixel.gif" width="1" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-4728096552446090738?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/4728096552446090738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/embedding-paths-into-actions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4728096552446090738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4728096552446090738'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/embedding-paths-into-actions.html' title='EMBEDDING PATHS INTO ACTIONS'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVg6oqcYqOI/AAAAAAAAARU/MXGfDah_70g/s72-c/embeding.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-4335843425723620767</id><published>2008-12-28T18:41:00.000-08:00</published><updated>2009-01-26T12:28:38.921-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>MEASURE TWICE, LOOK ONCE</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_gX-JntSisq4/SVg45L3gKkI/AAAAAAAAARE/tht5OjCqoxU/s1600-h/measure1.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_gX-JntSisq4/SVg45L3gKkI/AAAAAAAAARE/tht5OjCqoxU/s320/measure1.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/_gX-JntSisq4/SVg5-R7SOAI/AAAAAAAAARM/Xj56CEXIjmw/s1600-h/measure2.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_gX-JntSisq4/SVg5-R7SOAI/AAAAAAAAARM/Xj56CEXIjmw/s320/measure2.JPG" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;If you need to measure more than one side of an object (for  example, if you're measuring a box, and you need both the height and width), you  can measure both at the same time. First, open the Info palette (so you can see  the measurements that the Measure tool generates), then get the Measure tool  (under the Eyedropper) and click-and-drag it along the first edge. Release the  mouse when you reach the end of the edge. Then hold the Option key (PC: Alt  key), click on the end of the first line, and continue on in a different  direction. You'll notice that another measurement line appears. Now, look up in  the Info palette and you'll see your two measurements listed under D1 and  D2.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-4335843425723620767?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/4335843425723620767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/measure-twice-look-once.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4335843425723620767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4335843425723620767'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/measure-twice-look-once.html' title='MEASURE TWICE, LOOK ONCE'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_gX-JntSisq4/SVg45L3gKkI/AAAAAAAAARE/tht5OjCqoxU/s72-c/measure1.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5210172194398778058</id><published>2008-12-28T18:39:00.000-08:00</published><updated>2009-01-26T12:28:38.921-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>STROKING HALF A PATHHALF A PATH????</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_gX-JntSisq4/SVg4koDIFeI/AAAAAAAAAQ8/4Z-uoLXO3uA/s1600-h/stroking.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_gX-JntSisq4/SVg4koDIFeI/AAAAAAAAAQ8/4Z-uoLXO3uA/s320/stroking.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="docText"&gt;This is a mind-blowing advanced tip (not because it's hardit's  simplebut if you use the Pen tool, warningyour mind is about to spontaneously  combust). Here's the scoop: If you're an advanced user, you already know that  you can draw a path and then apply a stroke along that path (using the paint  tool of your choice) by choosing Stroke Path from the Paths palette's pop-down  menu. But dig this: If you draw your path, but only want to stroke a portion of  that path, all you have to do is make a selection (using the Lasso tool) of the  part of the path you want stroked. Then when you choose Stroke Path, it will  only stroke the area of your path that is contained within your selection. Boom!  That was the sound of our heads exploding.&lt;/div&gt;&lt;a href="http://draft.blogger.com/25031535.html"&gt;&lt;img alt="" border="0" height="1" src="images/pixel.gif" width="1" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5210172194398778058?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5210172194398778058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/stroking-half-pathhalf-path.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5210172194398778058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5210172194398778058'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/stroking-half-pathhalf-path.html' title='STROKING HALF A PATHHALF A PATH????'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVg4koDIFeI/AAAAAAAAAQ8/4Z-uoLXO3uA/s72-c/stroking.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5292532879590222241</id><published>2008-12-28T18:38:00.000-08:00</published><updated>2009-01-26T12:28:38.921-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>SPEEDING UP BATCH ACTIONS</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_gX-JntSisq4/SVg4R-XAQpI/AAAAAAAAAQ0/yUHLkucG4F8/s1600-h/spedding.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_gX-JntSisq4/SVg4R-XAQpI/AAAAAAAAAQ0/yUHLkucG4F8/s320/spedding.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;If you're running a Batch action on a folder full of images,  one of the things that can really slow the process down is the fact that the  History palette keeps creating History States (undos) for each image. To keep  your Batch actions running at full speed, there are two things you can do: In  the History palette's pop-down menu, under History Options, turn off the  checkbox for "Automatically Create First Snapshot." Secondly, go under the  Photoshop menu, under Preferences, and choose General (in Windows, Preferences  can be found under the Edit menu). In the History States field, lower the number  from 20 (the default) to 2 states and click OK. Then your batch will run like a  greased pig. Don't forget to increase your History States or change your History  Options back after you're done batching or you'll be down to two undos.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5292532879590222241?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5292532879590222241/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/speeding-up-batch-actions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5292532879590222241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5292532879590222241'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/speeding-up-batch-actions.html' title='SPEEDING UP BATCH ACTIONS'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_gX-JntSisq4/SVg4R-XAQpI/AAAAAAAAAQ0/yUHLkucG4F8/s72-c/spedding.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-3901532198200342104</id><published>2008-12-28T18:36:00.000-08:00</published><updated>2009-01-26T12:28:38.921-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>LOCKING A PDF PRESENTATION</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_gX-JntSisq4/SVg38Y05HiI/AAAAAAAAAQs/PaUdSeU8VSk/s1600-h/lokingpdf.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_gX-JntSisq4/SVg38Y05HiI/AAAAAAAAAQs/PaUdSeU8VSk/s320/lokingpdf.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;If you're using Photoshop to create a PDF Presentation slide  show (under the File Browser's Automate menu) so you can e-mail it to your  clients for proofing, one of your concerns may be that your client will just  print your photos out to a photo-quality printer, leaving you out in the cold  (so to speak). But you can pull the plug on their printing aspirations. When  saving your PDF Presentation, under Output Options, choose Presentation, then  hit Save. It'll ask you to name your PDF presentation (you're not done yet), so  name it and click Save. When you name it and click Save, a PDF Options dialog  will appear. Click on the PDF Security checkbox, then click on the Security  Settings button. In the PDF Security dialog, click on the checkbox for Password  Required to Change Permission and Passwords and enter (and memorize) a password.  Then, under Compatibility, turn on the checkboxes for No Printing, No Changing  the Document, and No Content Copying or Extraction, Disable Accessibility. Click  OK and it'll ask for your password one more time. Now, when you e-mail the PDF  Presentation, printing will be grayed out, and even if they have the full  version of Acrobat, they won't be able to copy and paste your photos into  something else for printing.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-3901532198200342104?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/3901532198200342104/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/locking-pdf-presentation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/3901532198200342104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/3901532198200342104'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/locking-pdf-presentation.html' title='LOCKING A PDF PRESENTATION'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVg38Y05HiI/AAAAAAAAAQs/PaUdSeU8VSk/s72-c/lokingpdf.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7004833576743314216</id><published>2008-12-28T18:35:00.000-08:00</published><updated>2009-01-26T12:28:38.921-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>SAVING TIME WHEN CORRECTING CAMERA RAW PHOTOS</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_gX-JntSisq4/SVg3hZ49RCI/AAAAAAAAAQk/5qKUJnAFyPI/s1600-h/savingtime.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_gX-JntSisq4/SVg3hZ49RCI/AAAAAAAAAQk/5qKUJnAFyPI/s320/savingtime.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="docText"&gt;If you're shooting and correcting Raw images from your digital  camera, there's a File Browser trick you can use to quickly correct photos taken  in similar lighting conditions. First, open the File Browser, then double-click  on your first Raw image. This opens Camera Raw. Make your adjustments, then  click OK in Camera Raw. This will open the image in Photoshop, but go back to  the File Browser for now. Command-click (PC: Control-click) on the other Raw  thumbnails in the File Browser that have similar lighting conditions. Once all  the photos are selected, go under the Automate menu and choose Apply Camera Raw  Settings. In the resulting dialog, the Apply Settings From pop-up menu should be  set to First Selected Image. Click Update and you'll see the thumbnail previews  update to reflect your correction (which will be applied automatically when you  open these images in Photoshop).&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7004833576743314216?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7004833576743314216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/saving-time-when-correcting-camera-raw.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7004833576743314216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7004833576743314216'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/saving-time-when-correcting-camera-raw.html' title='SAVING TIME WHEN CORRECTING CAMERA RAW PHOTOS'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_gX-JntSisq4/SVg3hZ49RCI/AAAAAAAAAQk/5qKUJnAFyPI/s72-c/savingtime.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7031076423929880022</id><published>2008-12-28T18:29:00.000-08:00</published><updated>2009-01-26T12:28:38.921-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip And Trick Photo Shop'/><title type='text'>PUTTING YOUR LENS FLARE ON THE SPOT</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_gX-JntSisq4/SVg3LHUJFsI/AAAAAAAAAQc/4T7zPclAmRg/s1600-h/info.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_gX-JntSisq4/SVg3LHUJFsI/AAAAAAAAAQc/4T7zPclAmRg/s320/info.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://1.bp.blogspot.com/_gX-JntSisq4/SVg25cvZQjI/AAAAAAAAAQU/iTUOCuNLh6w/s1600-h/putting.JPG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_gX-JntSisq4/SVg25cvZQjI/AAAAAAAAAQU/iTUOCuNLh6w/s320/putting.JPG" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;&lt;/div&gt;&lt;div class="docText"&gt;This tip lets you precisely position the center of the Lens  Flare filter by using the Info palette and a little-known feature of the Lens  Flare dialog. First, open the Info palette (found under the Window menu) then  put your cursor over the precise spot in your image where you'd like the center  of your Lens Flare to appear. Then look up in the Info palette, under the X and  Y coordinates, and write down those two coordinates (I knew one day I'd find a  use for the X and Y coordinate readings). Then go under the Filter menu, under  Render, and choose Lens Flare. There's a fairly large preview window in the  center of the dialog. Hold the Option key (PC: Alt key), click once on the  Preview window, and it brings up the Precise Flare Center dialog. Enter those X  and Y coordinates you wrote down earlier (you did write them down, right?),  click OK, and your Lens Flare is precisely positioned.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7031076423929880022?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7031076423929880022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/putting-your-lens-flare-on-spot.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7031076423929880022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7031076423929880022'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/putting-your-lens-flare-on-spot.html' title='PUTTING YOUR LENS FLARE ON THE SPOT'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_gX-JntSisq4/SVg3LHUJFsI/AAAAAAAAAQc/4T7zPclAmRg/s72-c/info.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-6255347689400284247</id><published>2008-12-13T13:00:00.000-08:00</published><updated>2009-01-26T12:29:52.719-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>Chapter 7. XMLHttpRequest</title><content type='html'>Several years ago, I worked for a company that had a reputation for conceiving incredible ideas. Unfortunately, the company also had a reputation for being unable to either recognize the value of those ideas or market a product using those ideas. Such was the case with the XMLHttpRequest object, originally created by Microsoft for use with one of the products in its Office Suite. It languished unused until outsiders discovered it in Internet Explorer.&lt;br /&gt;These unknown intrepid developers knew immediately that the XMLHttpRequest object was a solution in search of a problem. The only real question was in finding the problem. And although I can't speak for anyone else, the problem that I chose was a shopping cart application described in Chapter 2, "Introducing Ajax." Remember the "mockup" that wasn't a mockup and didn't "blink"? After that particular incident, I was considerably more careful in my selection of applicationsor, at least, in my selection of attendees at my demonstrations.&lt;br /&gt;In fact, at times I was so careful in selecting where to use the XMLHttpRequest object that it was necessary to examine the code to see exactly how it worked. I started by choosing applications in which it appeared that the information was cached on the client side: the dreaded HTML select whose contents are based upon another HTML select, which, in turn, is based upon another HTML select. As long as nobody ever looked at the code, which nobody ever did, the web page wouldn't appear any different from the hundreds of others in the system. That is, it wouldn't appear different unless you take into account speed. Without all the cached information, the initial load was considerably faster.&lt;br /&gt;In retrospect, looking back upon several of those "mad scientist" applications, I realize now that not all of them could be considered Ajax. This is because Ajax is shorthand for Asynchronous JavaScript and XML, and some of these applications were coded to be synchronous. And whoever heard of Sjax?&lt;br /&gt;Nevertheless, because the XMLHttpRequest object can be used both synchronously and asynchronously, both are covered. Moreover, we cover the following topics in this chapter:&lt;br /&gt;Synchronous&lt;br /&gt;Asynchronous&lt;br /&gt;Microsoft Internet Explorer&lt;br /&gt;XML Document Object Model&lt;br /&gt;RSS&lt;br /&gt;Web Services&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-6255347689400284247?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/6255347689400284247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-7-xmlhttprequest.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/6255347689400284247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/6255347689400284247'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-7-xmlhttprequest.html' title='Chapter 7. XMLHttpRequest'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7586764017121242577</id><published>2008-12-13T12:54:00.000-08:00</published><updated>2009-01-26T12:29:52.719-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>Synchronous</title><content type='html'>Although not nearly as cool as coding an asynchronous client-side application, a synchronous client-side application is nothing to look down at. In fact, it beats the pants off the average web applicationfiguratively speaking, of course, because web applications don't wear pants. Thinking about it, using the XMLHttpRequest object synchronously is actually a good way to expose yourself, also figuratively, to some of the basics.&lt;br /&gt;&lt;br /&gt;One of the interesting things about the basics of the XMLHttpRequest object is that these basics are actually basic. Only a few parameters and a few lines of code separate the synchronous from the asynchronous. When you understand that, not much is required to change a synchronous application into an asynchronous application. Don't believe me? Take a look at the XMLHttpRequest object's properties and methods shown in Table 7-1.&lt;br /&gt;&lt;br /&gt;Table 7-1. XMLHttpRequest Object Properties and Methods Method/Property&lt;br /&gt; Description&lt;br /&gt; &lt;br /&gt;abort()&lt;br /&gt; Terminates the previous outstanding request.&lt;br /&gt; &lt;br /&gt;getAllResponseHeaders()&lt;br /&gt; Returns all response headers, labels, and values, as a string.&lt;br /&gt; &lt;br /&gt;getresponseHeader("label")&lt;br /&gt; Returns the value for the provided label.&lt;br /&gt; &lt;br /&gt;open("method","url", asynchronous,"username","password")&lt;br /&gt; Opens/assigns a method: GET or POST and, optionally, an asynchronous indicator.&lt;br /&gt; &lt;br /&gt;send(content)&lt;br /&gt; Sends the request with optional content. This content can be either a string or DOM data.&lt;br /&gt; &lt;br /&gt;setRequestHeader ("label","value")&lt;br /&gt; Sets a request header label/value pair.&lt;br /&gt; &lt;br /&gt;onreadystatechange&lt;br /&gt; Event handler for asynchronous requests; fires on each change to the readyState property.&lt;br /&gt; &lt;br /&gt;readyState&lt;br /&gt; Status of the request as an integer.&lt;br /&gt;&lt;br /&gt;0 = uninitialize&lt;br /&gt;&lt;br /&gt;1 = loading&lt;br /&gt;&lt;br /&gt;2 = loaded&lt;br /&gt;&lt;br /&gt;3 = interactive&lt;br /&gt;&lt;br /&gt;4 = complete&lt;br /&gt; &lt;br /&gt;responseText&lt;br /&gt; String returned from the server.&lt;br /&gt; &lt;br /&gt;responseXML&lt;br /&gt; XML document returned from the server.&lt;br /&gt; &lt;br /&gt;status&lt;br /&gt; HTTP response code returned from the server.&lt;br /&gt;&lt;br /&gt;statusText&lt;br /&gt; String message associated with the HTTP a.&lt;br /&gt;Right now, the XMLHttpRequest object might seem like a pile of unrelated parts, but when the individual parts are assembled in the correct sequence, things are different. To prove my point, let's take a look at the JavaScript that uses XMLHTTP to synchronously get a file from the server in Gecko-based browsers such as Firefox, Mozilla, and Flock (see Listing 7-1).&lt;br /&gt;Listing 7-1. Getting a File Synchronously&lt;br /&gt;var objXMLHTTP = new XMLHttpRequest();&lt;br /&gt;objXMLHTTP.open('GET', 'books.xml', false);&lt;br /&gt;objXMLHTTP.send(null);&lt;br /&gt;var objXML = objXMLHTTP.responseXML;&lt;br /&gt;The first step is to create an instance of the XMLHttpRequest object using the JavaScript new operator. Next, the open method is invoked using the request method, GET, a destination URL, and a Boolean indicating that the request is not asynchronous. The third and final step is to invoke the send method and assign the responseXML, an XML document, to a variable. And if you're not interested in using XML, there is always the responseText property.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7586764017121242577?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7586764017121242577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/synchronous.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7586764017121242577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7586764017121242577'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/synchronous.html' title='Synchronous'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7269054474507326618</id><published>2008-12-13T12:49:00.000-08:00</published><updated>2009-01-26T12:29:52.720-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>Asynchronous</title><content type='html'>On the surface, what's required to change the request from synchronous to asynchronous appears to be simply changing the false parameter to TRue for the open method. Unfortunately, although that would make the request asynchronous, it would have some issues with the responseXML property. This is because the request is asynchronous; instead of waiting for a response from the send method, processing just continues on its merry way. This means that the responseXML property is undefined, which is not exactly what we're looking for or expecting.&lt;br /&gt;&lt;br /&gt;Fortunately, there is a way to correct this issue, but it requires creating an event handler to, er, handle changes to the readyState property. With the XMLHttpRequest object, the value of the readyState property changes every time something changes with the response to the request. This change fires the handler defined by the onreadystatechange property. Let's take a look at the example shown in Listing 7-2.&lt;br /&gt;&lt;br /&gt;Listing 7-2. Example of Creating an Event Handler to Correct the Problem&lt;br /&gt;var objXMLHTTP = new XMLHttpRequest();&lt;br /&gt;var objXML;&lt;br /&gt;&lt;br /&gt;objXMLHTTP.onreadystatechange = asyncHandler;&lt;br /&gt;objXMLHTTP.open('GET', 'books.xml', true);&lt;br /&gt;objXMLHTTP.send(null);&lt;br /&gt;&lt;br /&gt;function asyncHandler() {&lt;br /&gt;  if(objXMLHTTP.readyState == 4)&lt;br /&gt;    objXML = objXMLHTTP.responseXML;&lt;br /&gt;}&lt;br /&gt;In this example, the function asyncHandler is assigned as an event handler using the onreadystatechange property. This means that the asyncHandler function fires each time the readyState property changes. Because it fires every time the property changes, it is necessary to verify that the response is actually complete before doing anything with the response. The if statement in the asyncHandler function takes care of this issue; a readyState equal to 4 means that everything is fine and we're done. But what if everything isn't fine?&lt;br /&gt;&lt;br /&gt;Anyone who has ever played any of the Mech Assault campaigns knows that something always goes wrong. What fun would it be if everything worked all the time? Thinking about it, please disregard my last statement as the ramblings of a sick mind. Nevertheless, the universe is perverse, so bad things happen to good people, countries, cities, and web applications. Because of this, it is sometimes necessary to code defensively, to handle the unexpected. Note that I said defensively, not offensively. Don't go looking for problems; like a mad cat with charged PPCs, they'll find you soon enough.&lt;br /&gt;&lt;br /&gt;You can handle this potential problem in several ways. The first possible method involves hoping and wishing. Unfortunately, management has a tendency to frown upon this method of error handling. Possibly this is because mangers aren't a particularly hopeful group of people. Maybe because their heads are on the chopping block right next to our own.&lt;br /&gt;&lt;br /&gt;A better method of handling potential problems, at least from a job longevity point of view, is to consider what could go wrong. The way that I see it, things can go wrong in two possible ways. The first of these is getting basic bad information back from the server. During development, this can be handled by an alert and the responseText property. Beyond the development phase, however, this would probably scare away the nonmad scientists. At these times, you might want to inform the user that an error has taken place and use the XMLHttpRequest object to tell development about it. A more common, and much harder to handle, error is a timeout.&lt;br /&gt;&lt;br /&gt;A timeout, for those who have been watching Star Gate SG-1 instead of reading about web development, occurs when an application either doesn't respond at all or doesn't respond in a reasonable amount of time. Who defines "reasonable"? You do. Big believer in the 7-second rule? Then use 7 seconds. Like the Hitchhiker's Guide to the Galaxy? Then use 42 seconds. In short, use whatever time period seems appropriate. After you decide this, all that is necessary is to figure out how to handle it.&lt;br /&gt;&lt;br /&gt;Personally, I'm fond of using the setTimeout method with a variable set to the result from the method. If the response is received within the specified time limit, clearTimeout can be used to prevent the timeout function from executing. Otherwise, the function specified by the setTimeout method will execute and any problems can be dealt with then. All in all, using the setTimeout method is a rather elegant solution to a potentially fatal problem.&lt;br /&gt;&lt;br /&gt;This leaves really only one issue: What to do with those individuals who, for some reason, choose to use Microsoft Internet Explorer? Keep it clean! Yes, we have to accommodate those people in some way, beyond the Click Here to Download option.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7269054474507326618?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7269054474507326618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/asynchronous.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7269054474507326618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7269054474507326618'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/asynchronous.html' title='Asynchronous'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-756503290009825133</id><published>2008-12-13T12:40:00.000-08:00</published><updated>2009-01-26T12:29:52.720-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>7.5. RSS</title><content type='html'>&lt;p class="docText"&gt;Really Simple Syndication, or RSS, is a dialect of XML that is  commonly used for providing news-related content. Things such as news headlines  are the realm of RSS. The only issue is that because RSS is XML, it doesn't  appear as pretty as HTML does in a web browser. Consider the RSS shown in &lt;a class="docLink" href="#ch07list04"&gt;Listing 7-4&lt;/a&gt; as an example. &lt;/p&gt;&lt;h5 class="docExampleTitle" id="title-IDADPOEL"&gt;Listing 7-4. RSS Example&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;&lt;?xml version="1.0"?&gt;&lt;br /&gt;&lt;rss version="2.0"&gt;&lt;br /&gt; &lt;channel&gt;&lt;br /&gt;   &lt;titles&gt;NEWS!&lt;/titles&gt;&lt;br /&gt;   &lt;links&gt;http://overlord.gov/&lt;/links&gt;&lt;br /&gt;   &lt;description&gt;Latest news&lt;/description&gt;&lt;br /&gt;   &lt;language&gt;en-us&lt;/language&gt;&lt;br /&gt;   &lt;pubdate&gt;Tue, 29 Nov 2005 03:00:00 GMT&lt;/pubdate&gt;&lt;br /&gt;&lt;br /&gt;   &lt;lastbuilddate&gt;Tue, 29 Nov 2005 03:07:00 GMT&lt;/lastbuilddate&gt;&lt;br /&gt;   &lt;docs&gt;http://blogs.overlord.gov/rss&lt;/docs&gt;&lt;br /&gt;   &lt;generator&gt;My Generator&lt;/generator&gt;&lt;br /&gt;   &lt;managingeditor&gt;Bob@gol.com&lt;/managingeditor&gt;&lt;br /&gt;   &lt;webmaster&gt;webmaster@gol.com&lt;/webmaster&gt;&lt;br /&gt;&lt;br /&gt;   &lt;item&gt;&lt;br /&gt;     &lt;titles&gt;Galactic Overlord Resigns&lt;/titles&gt;&lt;br /&gt;     &lt;links&gt;http://overlord.gov/news/2005/news-resign.aspx&lt;/links&gt;&lt;br /&gt;     &lt;description&gt;&lt;br /&gt;      The much despised Galactic Overlord has announced&lt;br /&gt;      his resignation as the Blorf fleet entered&lt;br /&gt;       orbit.&lt;br /&gt;     &lt;/description&gt;&lt;br /&gt;    &lt;pubdate&gt;Tue, 29 Nov 2005 03:07:00 GMT&lt;/pubdate&gt;&lt;br /&gt;    &lt;guid&gt;http://overlord.gov/news/2005/11/28.html#item1&lt;/guid&gt;&lt;br /&gt;   &lt;/item&gt;&lt;br /&gt;   &lt;item&gt;&lt;br /&gt;     &lt;titles&gt;Earth's Moon Stolen&lt;/titles&gt;&lt;br /&gt;     &lt;links&gt;http://overlord.gov/news/2005/news-moon.aspx&lt;/links&gt;&lt;br /&gt;     &lt;description&gt;&lt;br /&gt;      Luna, the often photographed natural satellite of&lt;br /&gt;      Earth, has been reported stolen. According to a&lt;br /&gt;      UN spokesperson, at this moment, there are no&lt;br /&gt;       suspects.&lt;br /&gt;      &lt;/description&gt;&lt;br /&gt;     &lt;pubdate&gt;Tue, 29 Nov 2005 05:28:00 GMT&lt;/pubdate&gt;&lt;br /&gt;     &lt;guid&gt;http://overlord.gov/news/2005/11/28.html#item2&lt;/guid&gt;&lt;br /&gt;   &lt;/item&gt;&lt;br /&gt; &lt;/channel&gt;&lt;br /&gt;&lt;/rss&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt; &lt;p class="docText"&gt;Not very pretty, is it? There are, however, ways to prettify  it. (Wow, who would have thought that &lt;span class="docEmphasis"&gt;prettify&lt;/span&gt;  was a word? Oops, off the subject matter.) Using JavaScript and the DOM methods  and properties, it is possible to extract only the headlines from the RSS shown.  For example, the &lt;tt&gt;getElementsByTagname&lt;/tt&gt; or the &lt;tt&gt;getNamedItem&lt;/tt&gt;  properties could be used to obtain the title elements. The content of these  elements could then be displayed on the page as a hyperlink. Clicking on the  link could then fire a JavaScript handler that would display the description  element.&lt;/p&gt; &lt;p class="docText"&gt;The purpose of this side trip into the wonderful world of  Really Simple Syndication was to merely show some of the possibilities of XML.  When information is available as XML, it can at times be treated as something  like a database. In essence, XML is not only the data itself, but also the  source of subsets of that data.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-756503290009825133?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/756503290009825133/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/75-rss.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/756503290009825133'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/756503290009825133'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/75-rss.html' title='7.5. RSS'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7135882650045092519</id><published>2008-12-13T12:34:00.000-08:00</published><updated>2009-01-26T12:29:52.720-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>Web Services</title><content type='html'>Regardless of where you look, web services are a hot subject, and not just on resumés. Something of a mystique surrounds web services; like the latest hot video game, everybody wants one, even if nobody is quite sure what one is. Ah, to be a kid again, wanting something just because I want it. Who am I kidding? I'm still that way, obsessing over games such as Stargate: The Alliance for XBox, and books such as Practical Guide to Red Hat Linux: Fedora Core and Red Hat Enterprise Linux. However, unlike businesses, my pockets aren't full of much other than lint, which means that I have to wait, whereas businesses can just whip out the checkbook.&lt;br /&gt;7.6.1. What Is a Web Service?&lt;br /&gt;Alright, because everybody wants a web service, there are only two questions. The first question is, what is a web service? And the second question is, how does a web service work? Let's start by answering the first question: What is a web service?&lt;br /&gt;A web service is a piece of software designed to respond to requests across either the Internet or an intranet. In essence, it is a program that executes when a request is made of it, and it produces some kind of result that is returned to the caller. This might sound a lot like a web page, but there is a significant difference: With a web page, all the caller is required to know about the page is the URI. With a web service, the caller needs to know both the URI and at least one of the web service's public methods. Consider, for example, the C# web service shown in Listing 7-5. Knowing the URI, which, incidentally, is http://localhost/AJAX4/myService.asmx, isn't enough. It is also necessary to know that the public method is called monster.&lt;br /&gt;Listing 7-5. Web Service Example&lt;br /&gt;using System;&lt;br /&gt;using System.Collections;&lt;br /&gt;using System.ComponentModel;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Diagnostics;&lt;br /&gt;using System.Web;&lt;br /&gt;using System.Web.Services;&lt;br /&gt;namespace AJAX4&lt;br /&gt;{&lt;br /&gt;  public class myService : System.Web.Services.WebService&lt;br /&gt;  {&lt;br /&gt;    public myService()&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;      InitializeComponent();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #region Component Designer generated code&lt;br /&gt;&lt;br /&gt;    //Required by the Web Services Designer&lt;br /&gt;    private IContainer components = null;&lt;br /&gt;&lt;br /&gt;    /// &lt;summary&gt;&lt;br /&gt;    /// Required method for Designer support - do not modify&lt;br /&gt;    /// the contents of this method with the code editor.&lt;br /&gt;    /// &lt;/summary&gt;&lt;br /&gt;    private void InitializeComponent()&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /// &lt;summary&gt;&lt;br /&gt;    /// Clean up any resources being used.&lt;br /&gt;    /// &lt;/summary&gt;&lt;br /&gt;    protected override void Dispose( bool disposing )&lt;br /&gt;    {&lt;br /&gt;      if(disposing &amp;&amp; components != null)&lt;br /&gt;      {&lt;br /&gt;        components.Dispose();&lt;br /&gt;      }&lt;br /&gt;      base.Dispose(disposing);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    [WebMethod]&lt;br /&gt;    public string monster()&lt;br /&gt;    {&lt;br /&gt;      return "Grrr!";&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Great, now we have a web servicewhoopee, we're done, right? Wrong! Having a web service is only part of the battle; it falls into the same category as having a swimming pool and not knowing how to swim. Yeah, it is impressive, but deep down, there is a nagging feeling of feeling stupid for the unnecessary expense. What is needed is the knowledge of how to invoke the web service.&lt;br /&gt;&lt;br /&gt;Impressive word, invoke; it conjures up images of smoke, candles, pentagrams, and demons, the kind that could rip a soul from a body and torment it for eternityor, at least, during the annual performance evaluation. As with invoking a demon, invoking a web service is all a matter of how things are phrased, knowing both what to ask and how to ask. In both cases, mistakes can lead to, um, undesirable results.&lt;br /&gt;&lt;br /&gt;7.6.2. SOAP&lt;br /&gt;Unlike demonology, which requires the use of Latin (of the Roman variety, not the swine variety), invoking a web service requires the use of a dialect of XML called SOAP. And as with everything even remotely computer related, SOAP is an acronym standing for Simple Object Access Protocol. Fortunately, with SOAP, the little elves who name things didn't lie: It is actually simple, and who would have thought it?&lt;br /&gt;&lt;br /&gt;The basic structure of a SOAP request is an envelope, which is also a pretty good analogy of not only what it is, but also what it does. It serves as a wrapper around the request and any parameters being passed to the web service. Consider the example of SOAP shown in Listing 7-6, whose purpose is to invoke the web service from Listing 7-5.&lt;br /&gt;&lt;br /&gt;Listing 7-6. SOAP to Invoke the Web Service&lt;br /&gt;&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&lt;soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;br /&gt;xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;&lt;br /&gt;  &lt;soap:Body&gt;&lt;br /&gt;    &lt;monster xmlns="http://tempuri.org/" /&gt;&lt;br /&gt;  &lt;/soap:Body&gt;&lt;br /&gt;&lt;/soap:Envelope&gt;&lt;br /&gt;Doesn't look like much does it? All that the SOAP envelope does is specify the method, monster, along with a namespacewhich, in this case, is the default, basically a placeholder. If the method requires any parameters, they would be passed as children of that method. For example, let's add the method shown in Listing 7-7 to the web service from Listing 7-5.&lt;br /&gt;Listing 7-7. Method to Add to the Web Service&lt;br /&gt;[WebMethod]&lt;br /&gt;public string echo(string text)&lt;br /&gt;{&lt;br /&gt;  return text;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Beyond changing the method from monster to echo, there is the little problem of the parameter named text. Because of the parameter, it is necessary to change the body of the SOAP request to the one shown in Listing 7-8..&lt;br /&gt;&lt;br /&gt;Listing 7-8. The New SOAP Request&lt;br /&gt;&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&lt;soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;&lt;br /&gt;xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;br /&gt;xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;&lt;br /&gt;  &lt;soap:Body&gt;&lt;br /&gt;    &lt;echo xmlns="http://tempuri.org/"&gt;&lt;br /&gt;      &lt;text&gt;Dijon Ketchup&lt;/text&gt;&lt;br /&gt;    &lt;/echo&gt;&lt;br /&gt;  &lt;/soap:Body&gt;&lt;br /&gt;&lt;/soap:Envelope&gt;&lt;br /&gt;Now that we've got the basics down of the SOAP envelope (yes, there is more) let's consider how to deliver it to the web service. Unfortunately, FedEx and UPS are both out of the question, although it might be fun to call and ask the rates for delivering a SOAP envelope to a web serviceat least, until they got a restraining order. This leaves the XMLRequest object as the best available resource: neither rain, nor snow, and all that stuff.&lt;br /&gt;Everything necessary to deliver the SOAP envelope is already in there, so the only issue is how to send our SOAP envelopeafter all, there are no mailboxes with little red flags. Fortunately, we have a good chunk of the code down already, including the SOAP envelope itself. Instead of beating around the bush, Listing 7-9 shows the client-side JavaScript necessary to invoke the monster method of our web service.&lt;br /&gt;&lt;br /&gt;Listing 7-9. JavaScript to Invoke the monster Method&lt;br /&gt;try {&lt;br /&gt;  objXMLHTTP = new XMLHttpRequest();&lt;br /&gt;}&lt;br /&gt;catch(e) {&lt;br /&gt;  objXMLHTTP = new ActiveXObject('Microsoft.XMLHTTP');&lt;br /&gt;}&lt;br /&gt;objXMLHTTP.onreadystatechange = asyncHandler;&lt;br /&gt;objXMLHTTP.open('POST', 'http://localhost/AJAX4/myService.asmx', true);&lt;br /&gt;objXMLHTTP.setRequestHeader('SOAPAction','http://tempuri.org/monster');&lt;br /&gt;objXMLHTTP.setRequestHeader('Content-Type','text/xml');&lt;br /&gt;objXMLHTTP.send(soap);&lt;br /&gt;&lt;br /&gt;function asyncHandler() {&lt;br /&gt;  if(objXMLHTTP.readyState == 4)&lt;br /&gt;    alert(objXMLHTTP.responseText);&lt;br /&gt;}&lt;br /&gt;The first noticeable change from the earlier asynchronous request (refer to Listing 7-2) is that the method has been changed from GET to POST; this is because it is necessary to post the SOAP envelope to the web service. This leads to the second change; the URI in the open method is now the address of the web service instead of a filename.&lt;br /&gt;Perhaps the biggest changes are the addition of two setRequestHeader methods. The first one sets the SOAPAction to the web service's namespace and the method to be invoked. It is important to note that it is absolutely necessary for the SOAPAction header to be identical to the method in the SOAP envelope. If they aren't identical, it won't work. Personally, I spent a lot of time chasing my tail trying to figure out what was wrong whenever the methods were different, but, then, I was raised by wolves and have a strong tendency to chase my tail.&lt;br /&gt;The second setRequestHeader is the easy one; all that it does is set the Content-type to text/xml. As if we'd be doing anything else. But this raises the question of what the response from the web service will look like, beyond being XML.&lt;br /&gt;Well, there are essentially two possible responses; either it worked or it didn't. If it worked, it will look a lot like the response shown in Listing 7-10. However, there could be some differences. For instance, it could be an XML document instead of the "Grrr!", but this is only an example, so why strain ourselves?&lt;br /&gt;&lt;br /&gt;Listing 7-10. The Response&lt;br /&gt;&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&lt;soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;&lt;br /&gt;  &lt;soap:Body&gt;&lt;br /&gt;    &lt;monsterResponse xmlns="http://tempuri.org/"&gt;&lt;br /&gt;      &lt;monsterResult&gt;Grrr!&lt;/monsterResult&gt;&lt;br /&gt;    &lt;/monsterResponse&gt;&lt;br /&gt;  &lt;/soap:Body&gt;&lt;br /&gt;&lt;/soap:Envelope&gt;&lt;br /&gt;The second possible response is broken into two parts. The first part is called a SOAP fault. Basically, it means that something is wrong with the request, such as the methods not being identical. Listing 7-11 shows a SOAP fault that was created when I changed the SOAPAction in the request header to xxxx when it should have been monster.&lt;br /&gt;&lt;br /&gt;Listing 7-11. A SOAP Fault&lt;br /&gt;&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&lt;soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;&lt;br /&gt;xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;&lt;br /&gt; &lt;soap:Body&gt;&lt;br /&gt;   &lt;soap:Fault&gt;&lt;br /&gt;     &lt;faultcode&gt;soap:Client&lt;/faultcode&gt;&lt;br /&gt;     &lt;faultstring&gt;&lt;br /&gt;      System.Web.Services.Protocols.SoapException: Server&lt;br /&gt;      did not recognize the value of HTTP Header&lt;br /&gt;      SOAPAction: http://tempuri.org/xxxx.&lt;br /&gt;   at&lt;br /&gt;System.Web.Services.Protocols.Soap11ServerProtocolHelper.RouteRequest()&lt;br /&gt;   at System.Web.Services.Protocols.SoapServerProtocol.Initialize()&lt;br /&gt;   at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type,&lt;br /&gt;HttpContext context, HttpRequest request, HttpResponse response)&lt;br /&gt;   at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type&lt;br /&gt;type, HttpContext context, HttpRequest request, HttpResponse response,&lt;br /&gt;Boolean&amp;amp; abortProcessing)&lt;br /&gt;&lt;/faultstring&gt;&lt;br /&gt;      &lt;detail/&gt;&lt;br /&gt;    &lt;/soap:Fault&gt;&lt;br /&gt;  &lt;/soap:Body&gt;&lt;br /&gt;&lt;/soap:Envelope&gt;&lt;br /&gt;The final two possible responses also cover errors. For example, there could be errors that are not handled correctly in the web service. This could result in the web service returning text concerning the error instead of either a SOAP response or a SOAP fault. It is important to take this into consideration when creating a web service.&lt;br /&gt;&lt;br /&gt;Although the language C# was used here for writing the web services, it is important to remember that these techniques can be applied to a whole slew of languages. In the end, the choice of language is yours, or it belongs to the powers-that-be, or somewhere in the hierarchy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7135882650045092519?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7135882650045092519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/web-services.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7135882650045092519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7135882650045092519'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/web-services.html' title='Web Services'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-2466114726080687803</id><published>2008-12-13T12:30:00.000-08:00</published><updated>2009-01-26T12:29:52.720-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>Ajax Using XML and XMLHttpRequest</title><content type='html'>Unlike the previous chapter, which was sort of "mad scientist stuff" with training wheels, here the training wheels come off. We're free to either fly like the wind or remove large amounts of skin from various body parts. Based upon my personal experience as a web developer, we'll probably do some of both. From this chapter forward, nobody, regardless of their personal feelings, can deny that what we do in this chapter falls under the definition of Ajax.&lt;br /&gt;&lt;br /&gt;Up to this point, the only part of Ajax that we've really seen is the JavaScript. Feels like a rip-off, doesn't it?&lt;br /&gt;&lt;br /&gt;Don't worry, we're building up to it. It would not do to have the monster rise off the slab in the beginning of Chapter 1, would it? Alright, I, too have a tendency to fast-forward to the good parts. For example, I don't care how SG-1 got to Antarctica; I just want to see the ship-to-ship battle over the pole and the battle in space. Come to think of it, Stargate SG-1 should be required watching for mad scientists because two of the regular characters could be classified as mad scientists themselves.&lt;br /&gt;&lt;br /&gt;The mad scientist stuff covered in this chapter is the basic building block of Ajax applications, the XMLHttpRequest object and how to determine what's actually going on. Along with this object is XML, including how to deal with it on the client and some of the ways to deal with it, such as SOAP (basically, a way to package XML for transport to and from the server). The final item covered is what to do with the XML on the client, such as put it in an XML Data Island. To skip ahead a little, because mad scientists like to describe their diabolical plans, XML Data Islands are one of the methods that can be used to both embed and bind HTML controls and data. The best part is, if you change one, the other changes.&lt;br /&gt;Traditional Versus Ajax Websites&lt;br /&gt;Before we go any further, this is a good time to review how the average website works, if only to see the contrast between it and Ajax websites. With a traditional website, it isn't unusual for the same page to go through the unload/reload cycle several times before progressing to the next logical page. A number of valid reasons explain why these unload/reload cycles occur, ranging from HTML select objects whose contents are based on other select objects to simply bad input caught on the server side. In the end, the result looks quite a lot like Figure 8-1.&lt;br /&gt;Even in the early days, when the paint wasn't yet fully dry on the World Wide Web, the unload/reload cycle got old pretty quick, especially at dial-up speeds. Now with the improved bandwidth available, things are different; it is old right from the start. For example, several years ago, I worked as a consultant for a company that was trying to get a handle on the whole "web thing," as they referred to it. Their approach was to wave a magic wand, and, "Poof!"a CICS programmer was now a web developer. Although this approach worked, after a fashion, it led to some rather interesting web development standards.&lt;br /&gt;&lt;br /&gt;Their standard went pretty much along the lines of trying to make web pages as much like the mainframe CICS pages as possible. These standards were a combination of the weird and the scary. An example of the weird was that initially all scrolling, regardless of the direction, was forbidden because it was thought to be unprofessional. This meant that it was necessary to break up tabular web pages into single pagesized chunks and provide the user with some means of navigation.&lt;br /&gt;&lt;br /&gt;On the other hand, some of the scary things were really scary. For example, they believed that there was nothing wrong with giving scripts write permission to the web server. Let's say, for instance, that a shopping cart for the web application was needed. Following the local standards, it was perfectly acceptable for the "temporary" shopping cart to be written to the web server. The rationale was that it was easier to work with flat files than to store information either on the client side or in a database table. Time permitting, they also could write a "batch job" to clean up the web server of abandoned shopping carts.&lt;br /&gt;&lt;br /&gt;The shopping cart was actually coded in the manner that I described, but, thankfully, it was an absolute pig. It was both slow and temperamental, with items both appearing and disappearing seemingly at random in the shopping cart. In fact, my wife would probably say that it was like shopping with me: "Where did those Parmesan Goldfish and Double-Stuff Oreos come from?"&lt;br /&gt;&lt;br /&gt;I still shudder whenever I think that there was actually a chance of that page making it into a production environment and that management thought it was a perfectly acceptable design. Fortunately, the individual who developed that application was needed to fix a mainframe production problem, so I was assigned the task of making it work. I spent maybe a total of 10 minutes attempting to determine what was going wrong before deciding to try a somewhat more modern approach.&lt;br /&gt;&lt;br /&gt;The initial concept was to make the client work for a living and to pad my resumé with a whole bunch of things that I had only played with in the past, such as the XMLHttpRequest object. The result was a separation between the presentation layer and the web server; it was easily ten times faster than any of their existing web pages. It could have been faster yet, but, unfortunately, I was unable to bypass the draconian rules that were in place regarding stored procedures. Stored procedures were, in a word, forbidden, being considered as both too confusing to write and of no use. Argh! I was one step away from a three-tiered architecture.&lt;br /&gt;&lt;br /&gt;Regardless of the frustration that I felt at the time, I did achieve something wonderful by stumbling upon what was years later to be named Ajax. The shopping cart application was both similar to and different from the site's existing pages. The similarity to the existing applications was akin to the similarity between a soufflé and scrambled eggs. Many of the ingredients are the same; the real differences come from the technique used in putting the ingredients together. Probably the easiest way to illustrate this difference is to use a picture, such as the one shown in Figure 8-2.&lt;br /&gt;Very different from Figure 8-1, isn't it? Instead of a page seemingly unloading and reloading forever, the single page communicates directly with the web server. This greatly reduces the need for the unload/reload cycle, which has a lot of overhead. Think of it in terms of a trip to the moon. What if the Apollo astronauts needed to bring every necessity with them? Air, water, food, and anything else that was required had to be trucked along with them from the Earth to the moon. Now imagine for a moment that the moon had a breathable atmosphere and McDonald's. All of a sudden, a trip to the moon becomes almost as easy as a trip to Florida.&lt;br /&gt;&lt;br /&gt;Ajax does something similar by establishing an infrastructure on the client side. This infrastructure can be as simple or as complex as you want. In fact, now is a good time to see what goes into building our Ajax infrastructure. So queue the storm sound effects and put on the lab coat, and let's get our hands dirty.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-2466114726080687803?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/2466114726080687803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/ajax-using-xml-and-xmlhttprequest.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2466114726080687803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2466114726080687803'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/ajax-using-xml-and-xmlhttprequest.html' title='Ajax Using XML and XMLHttpRequest'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-982196096367665382</id><published>2008-12-13T12:26:00.000-08:00</published><updated>2009-01-26T12:29:52.720-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>XML</title><content type='html'>As you're aware, if only from the cameo appearance in Chapter 2, "Introducing Ajax," XML stands for eXtensible Markup Language, but other than the purpose of padding resumés, you're probably not aware of why XML is used so much. Basically, there are three main reasons for the popularity of XML, not including the air of mystery surrounding anything with an X in it. (Don't believe me about the air of mystery? What about The X-Files and X-Men?)&lt;br /&gt;Literally tons has been written about XMLwell, at least when hard copy is taken into account. As for electronic editions, I can't say because my notebook seems to weigh the same, regardless of the free space available. For this reason, I won't bore you with the history of XML and how it is the best thing since sliced bread, or how it cures baldness, because it would be either redundant or an outright lie. Anyone who has ever developed an application that uses XML knows that there is a good chance of pulling out one's own hair when attempting to explain XML to fellow developers who still haven't grasped the software equivalent of the concept of fire. However, I should at least hit the highlights and point out some of the more useful and obscure topics.&lt;br /&gt;8.2.1. Well Formed&lt;br /&gt;Alright, the concept that XML has to be well formed is not obscure, but it does fall well into the useful bucket. You'd be surprised at the number of times that I've had to explain the concept of "well formed" to a particular project leader with mainframe roots. Or, come to think of it, maybe you wouldn't. Let's just say that, like the Creature from the Black Lagoon, the XML challenged walk among us, and you don't even need to travel to the now-closed Marineland in Florida to find them. For this reason, it is time for XML 101.&lt;br /&gt;An XML document is well formed when the follow conditions have been met:&lt;br /&gt;All opening tags either have a closing tag or are self-closing.&lt;br /&gt;All attributes have values.&lt;br /&gt;All the values for the attribute are enclosed in either quotes or apostrophes. I should point out, however, that they need to be consistent. This means no mixing and matching; if a quotation mark is used on the left side of a value, a quotation mark must be used on the right side.&lt;br /&gt;Beware of entities! Wow, that sounds spooky, doesn't it? Entities are special characters that need to be handled with respect because, without special handling, they can be mistaken as something other than content.&lt;br /&gt;That was relatively easy, wasn't it? I recommend quoting it verbatim whenever it is necessary to explain the concept to a clueless project leader. But you need to remember to make your eyes big when saying "Beware of entities!" because they like that.&lt;br /&gt;Alright, now that you're (hopefully) open to XML, the big question is, where does it come from? Well, that depends on both your web server and database environments; some have built-in methods for producing XML directly from the result of SQL SELECT statements or stored procedures. If your environment doesn't support that, there is always the possibility of "rolling" your own XML. Because XML is human readableessentially, textwith a little work, it is possible to create XML, even where XML isn't supported.&lt;br /&gt;Take, for example, MySQL. Although both Oracle and SQL Server can produce XML directly from a stored procedure, a little more effort is required to produce XML from MySQL. First, a stored function is required to build the individual nodes by concatenating the node name and value, as in Listing 8-1. Next, a function is needed that uses a cursor to step through the results of a query and build the XML using the aforementioned stored function. Listing 8-2 contains a sample stored procedure to do just that.&lt;br /&gt;&lt;br /&gt;Listing 8-1. Concatenating a Stored Function&lt;br /&gt;DELIMITER $$&lt;br /&gt;&lt;br /&gt;DROP FUNCTION IF EXISTS `ajax`.`f_xmlNode`$$&lt;br /&gt;CREATE FUNCTION `ajax`.`f_xmlNode`(&lt;br /&gt;/*&lt;br /&gt;  To produce the text representation of an XML node.&lt;br /&gt;*/&lt;br /&gt;  nodeName VARCHAR(255),  /* XML node name                       */&lt;br /&gt;  nodeValue LONGTEXT,  /*  XML node value                    */&lt;br /&gt;  escape BOOLEAN  /*  Apply XML entity escaping         */&lt;br /&gt;) RETURNS longtext&lt;br /&gt;BEGIN&lt;br /&gt;  DECLARE xml LONGTEXT;  /* XML text node/value combination     */&lt;br /&gt;&lt;br /&gt;  IF nodeValue IS NULL OR LENGTH(nodeValue) = 0 THEN&lt;br /&gt;    SET xml = CONCAT('&lt;',nodeName,' /&gt;');&lt;br /&gt;  ELSE&lt;br /&gt;    IF escape THEN&lt;br /&gt;      SET xml =&lt;br /&gt;CONCAT('&lt;',nodeName,'&gt;',REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(nodeValue,&lt;br /&gt;'&amp;','&amp;amp;'),'&gt;','&amp;gt;'),'&lt;','&amp;lt;'),'''','&amp;apos;'),'"','&amp;quot;'),'&lt;/',nod&lt;br /&gt;eName,'&gt;');&lt;br /&gt;    ELSE&lt;br /&gt;      SET xml = CONCAT('&lt;',nodeName,'&gt;',nodeValue,'&lt;/',nodeName,'&gt;');&lt;br /&gt;    END IF;&lt;br /&gt;  END IF;&lt;br /&gt;&lt;br /&gt;  RETURN xml;&lt;br /&gt;END$$&lt;br /&gt;&lt;br /&gt;DELIMITER ;&lt;br /&gt;Listing 8-2. XML Producing a Stored Procedure&lt;br /&gt;DELIMITER $$&lt;br /&gt;&lt;br /&gt;DROP PROCEDURE IF EXISTS `ajax`.`itemSelectXML`$$&lt;br /&gt;CREATE PROCEDURE `ajax`.`itemSelectXML`(&lt;br /&gt;guildItemId INTEGER,&lt;br /&gt;guildId INTEGER&lt;br /&gt;)BEGIN&lt;br /&gt;  DECLARE done BOOLEAN DEFAULT FALSE;&lt;br /&gt;  DECLARE xml LONGTEXT DEFAULT '&lt;items&gt;';&lt;br /&gt;  DECLARE cGuildItemId INTEGER(6);&lt;br /&gt;  DECLARE cGuildId INTEGER(6);&lt;br /&gt;  DECLARE cGuildName VARCHAR(255);&lt;br /&gt;  DECLARE cItemName VARCHAR(255);&lt;br /&gt;  DECLARE cItemDescription VARCHAR(255);&lt;br /&gt;  DECLARE cItemPrice DECIMAL(10,2);&lt;br /&gt;  DECLARE itemCursor CURSOR FOR SELECT     b.guild_item_id,&lt;br /&gt;                                           b.guild_id,&lt;br /&gt;                                           g.guild_name,&lt;br /&gt;                                           i.item_name,&lt;br /&gt;                                           i.item_description,&lt;br /&gt;                                           i.item_price&lt;br /&gt;                                FROM       guild_item_bridge b&lt;br /&gt;                                INNER JOIN guild g&lt;br /&gt;                                ON         b.guild_id =&lt;br /&gt;                                           g.guild_id&lt;br /&gt;                                INNER JOIN item i&lt;br /&gt;                                ON         b.item_id = i.item_id&lt;br /&gt;                                WHERE      (guildItemId IS NULL&lt;br /&gt;                                           OR guildItemId =&lt;br /&gt;                                           b.guild_item_id)&lt;br /&gt;                                AND        (guildId IS NULL&lt;br /&gt;                                           OR guildId =&lt;br /&gt;                                           b.guild_id);&lt;br /&gt;  DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = TRUE;&lt;br /&gt;&lt;br /&gt;  OPEN itemCursor;&lt;br /&gt;&lt;br /&gt;  FETCH itemCursor INTO cGuildItemId,&lt;br /&gt;                        cGuildId,&lt;br /&gt;                        cGuildName,&lt;br /&gt;                        cItemName,&lt;br /&gt;                        cItemDescription,&lt;br /&gt;                        cItemPrice;&lt;br /&gt;&lt;br /&gt;  REPEAT&lt;br /&gt;    SET xml =&lt;br /&gt;CONCAT(xml,'&lt;item&gt;&lt;guild_item_id&gt;',cGuildItemId,'&lt;/guild_item_id&gt;');&lt;br /&gt;    SET xml = CONCAT(xml,'&lt;guild_id&gt;',cGuildId,'&lt;/guild_id&gt;');&lt;br /&gt;    SET xml =&lt;br /&gt;CONCAT(xml,'&lt;guild_item_name&gt;',REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(cGu&lt;br /&gt;ildName,'&amp;','&amp;amp;'),'&gt;','&amp;gt;'),'&lt;','&amp;lt;'),'''','&amp;apos;'),'"','&amp;quot;'),&lt;br /&gt;'&lt;/guild_item_name&gt;');&lt;br /&gt;    SET xml = CONCAT(xml,f_xmlString('item_name',cItemName));&lt;br /&gt;    SET xml =&lt;br /&gt;CONCAT(xml,'&lt;item_description&gt;',REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(cI&lt;br /&gt;temDescription,'&amp;','&amp;amp;'),'&gt;','&amp;gt;'),'&lt;','&amp;lt;'),'''','&amp;apos;'),'"','&amp;q&lt;br /&gt;uot;'),'&lt;/item_description&gt;');&lt;br /&gt;&lt;br /&gt;    SET xml =&lt;br /&gt;CONCAT(xml,'&lt;item_price&gt;',cItemPrice,'&lt;/item_price&gt;&lt;/item&gt;');&lt;br /&gt;&lt;br /&gt;    FETCH itemCursor INTO cGuildItemId,&lt;br /&gt;                          cGuildId,&lt;br /&gt;                          cGuildName,&lt;br /&gt;                          cItemName,&lt;br /&gt;                          cItemDescription,&lt;br /&gt;                          cItemPrice;&lt;br /&gt;  UNTIL done END REPEAT;&lt;br /&gt;&lt;br /&gt;  SET xml = CONCAT(xml,'&lt;/items&gt;');&lt;br /&gt;&lt;br /&gt;  SELECT xml;&lt;br /&gt;&lt;br /&gt;  CLOSE itemCursor;&lt;br /&gt;END$$&lt;br /&gt;DELIMITER ;&lt;br /&gt;Here's how it works: The stored procedure shown in listing 8-2 retrieves the result of a query, builds an XML string containing the opening root element, and then performs the following steps for each row retrieved:&lt;br /&gt;1.  If the item is numeric, concatenate it, wrapped in the appropriate XML tags, to the XML string.&lt;br /&gt;2.  If the item is alpha or alphanumeric, the stored function shown in Listing 8-1 is invoked to handle any entities and wrap the information in appropriate XML tags. The result of this stored function is then concatenated to the XML string&lt;br /&gt;After all the rows have been processed, the closing root element is appended to the XML string and the process is complete. Now that we have a reliable source of XML, let's examine how we can use it in a web browser.&lt;br /&gt;8.2.2. Data Islands for Internet Explorer&lt;br /&gt;The official party line about XML Data Islands is that they are a "Microsoft-only" technology and, therefore, will not work with any other browser. Yeah, right. However, before altering the fabric of reality as only a mad scientist can, let's take a closer look at what XML data islands are and how they work.&lt;br /&gt;&lt;br /&gt;As foreboding as the term XML Data Island is, according to the official definition, it is nothing more than XML embedded somewhere in an HTML document. Not too badsounds about as scary as a bowl of goldfish. In fact, Listing 8-3 is a basic HTML page with XML embedded smack in the middle of it, with Figure 8-3 showing what it looks like in Microsoft Internet Explorer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-982196096367665382?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/982196096367665382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/xml.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/982196096367665382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/982196096367665382'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/xml.html' title='XML'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7185888557737734065</id><published>2008-12-13T12:14:00.002-08:00</published><updated>2009-01-26T12:29:52.720-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>The XMLHttpRequest Object</title><content type='html'>As interesting as the previous section may have been, remember that it was only an appetizer. Now the time has come for the entrée: the XMLHttpRequest object. If you've never used the XMLHttpRequest object, it is, as described previously, an object that gives web browsers the capability to communicate directly with the server, without the unload/reload cycleor "blink," as the peasants call it.&lt;br /&gt;&lt;br /&gt;8.3.1. Avoiding the Unload/Reload Cycle&lt;br /&gt;The best analogy that I can think of to the XMLHttpRequest object is the transporter from any of the various incarnations of Star Trek. With the transporter, only the personnel essential to a particular mission need go down to the planet's surface. The alternative would be to either land the Starship, if it were capable of planetary landings, or send a shuttlecraft. In either case, there would be a lot of unnecessary equipment and personnel being moved about at great expense, as opposed to the "move only what you need" philosophy of the transporter.&lt;br /&gt;&lt;br /&gt;The XMLHttpRequest object is the web equivalent of the transporter. Why transmit an entire web page when all that is really needed is the data itself?&lt;br /&gt;&lt;br /&gt;The HTML and JavaScript for presentation are already there, so just change the data and we're good to go. I should point out that although the data being beamed from the server to the client doesn't necessarily have to be XML, in all these examples, it is XML.&lt;br /&gt;&lt;br /&gt;8.3.2. Browser Differences&lt;br /&gt;Before describing the actual syntax necessary to use XMLHTTP, I recommend that you sit down because I don't want to shock you or anything. Sitting down? Good. The syntax used for the XMLHttpRequest object is different in Microsoft Internet Explorer than from every other browser that supports it. In fact, from Microsoft's perspective, somewhere on the surface of Charon, not even the World Wide Web Consortium got it right. As a matter of fact, they made exactly the same mistake as Firefox. Fortunately, because the error is consistent among all nonInternet Explorer browsers all that is necessary is to code for IE and everybody else. Mmm, I wonder if maybe...nah!&lt;br /&gt;&lt;br /&gt;The first thing is to create an instance of the XMLHttpRequest object in the following manner:&lt;br /&gt;&lt;br /&gt;try {&lt;br /&gt;&lt;br /&gt;  var x = new DOMParser();&lt;br /&gt;  var _IE = false;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;catch(e) { var _IE = true; };&lt;br /&gt;var _XMLHTTP;&lt;br /&gt;&lt;br /&gt;if(_IE)&lt;br /&gt;   _XMLHTTP = new ActiveXObject('Microsoft.XMLHTTP');&lt;br /&gt;else&lt;br /&gt;   _XMLHTTP = new XMLHttpRequest();&lt;br /&gt;Before proceeding any further, a couple of decisions must be made that involve just how we'd like the page to work.&lt;br /&gt;Synchronous or asynchronous?&lt;br /&gt;GET or POST?&lt;br /&gt;The choice of synchronous or asynchronous is a relatively big one, but it boils down to waiting for a response or being notified when there is a response. As long as you remember to specify a state change handler for responses to asynchronous requests, things should work. The GET or POST question is also an important decision. Fortunately, it is the same decision that has been around ever since the introduction of HTML forms, so as long as we follow the same rules, everything will be alright.&lt;br /&gt;Let's say, for instance, that we want to retrieve the XML file of states and provinces shown in Listing 8-8 from the server. The first thing that is needed is to determine the browserbasically, Microsoft Internet Explorer and everyone else. The next task is to create an instance of the XMLHttpRequest object, followed by setting the event handler, for asynchronous requests. Finally, the XMLHttpRequest object is opened with three parameters:&lt;br /&gt;GET or POST&lt;br /&gt;The URL for the request&lt;br /&gt;Either TRue for asynchronous or false for synchronous&lt;br /&gt;However, you must remember one thing about coding a state change handler. It is a state change handler, not an "I'm finished" handler. There are other states than "complete"; we're interested in 4, which indicates that the request is complete. Listing 8-9 shows a page that retrieves the XML from Listing 8-8, storing it in an XML Data Island and binding it for display purposes.&lt;br /&gt;&lt;br /&gt;Listing 8-8. Sample XML Document&lt;br /&gt;&lt;states&gt;&lt;br /&gt;      &lt;state&gt;&lt;br /&gt;            &lt;state_abbreviation&gt;AB&lt;/state_abbreviation&gt;&lt;br /&gt;            &lt;state_name&gt;Alberta&lt;/state_name&gt;&lt;br /&gt;            &lt;country_id&gt;3&lt;/country_id&gt;&lt;br /&gt;      &lt;/state&gt;&lt;br /&gt;      &lt;state&gt;&lt;br /&gt;            &lt;state_abbreviation&gt;AK&lt;/state_abbreviation&gt;&lt;br /&gt;            &lt;state_name&gt;Alaska&lt;/state_name&gt;&lt;br /&gt;            &lt;country_id&gt;1&lt;/country_id&gt;&lt;br /&gt;      &lt;/state&gt;&lt;br /&gt;      &lt;state&gt;&lt;br /&gt;            &lt;state_abbreviation&gt;AL&lt;/state_abbreviation&gt;&lt;br /&gt;            &lt;state_name&gt;Alabama&lt;/state_name&gt;&lt;br /&gt;            &lt;country_id&gt;1&lt;/country_id&gt;&lt;br /&gt;      &lt;/state&gt;&lt;br /&gt;      &lt;state&gt;&lt;br /&gt;            &lt;state_abbreviation&gt;AR&lt;/state_abbreviation&gt;&lt;br /&gt;            &lt;state_name&gt;Arkansas&lt;/state_name&gt;&lt;br /&gt;            &lt;country_id&gt;1&lt;/country_id&gt;&lt;br /&gt;      &lt;/state&gt;&lt;br /&gt;      &lt;state&gt;&lt;br /&gt;            &lt;state_abbreviation&gt;AS&lt;/state_abbreviation&gt;&lt;br /&gt;            &lt;state_name&gt;American Samoa&lt;/state_name&gt;&lt;br /&gt;            &lt;country_id&gt;1&lt;/country_id&gt;&lt;br /&gt;      &lt;/state&gt;&lt;br /&gt;      &lt;state&gt;&lt;br /&gt;            &lt;state_abbreviation&gt;AZ&lt;/state_abbreviation&gt;&lt;br /&gt;            &lt;state_name&gt;Arizona&lt;/state_name&gt;&lt;br /&gt;            &lt;country_id&gt;1&lt;/country_id&gt;&lt;br /&gt;      &lt;/state&gt;&lt;br /&gt;&lt;/states&gt;&lt;br /&gt;Listing 8-9. HTML Document Using an XML Data Island xml&lt;br /&gt;      display: none;&lt;br /&gt;      font-size: 0px&lt;br /&gt;}&lt;br /&gt;            &lt;/style&gt;&lt;br /&gt;            &lt;script language="JavaScript"&gt;&lt;br /&gt;try {&lt;br /&gt;  var x = new DOMParser();&lt;br /&gt;  var _IE = false;&lt;br /&gt;}&lt;br /&gt;catch(e) { var _IE = true; };&lt;br /&gt;var _URL = 'http://localhost/chapter4/states.xml';&lt;br /&gt;var _XMLHTTP;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;   Perform page initialization.&lt;br /&gt;*/&lt;br /&gt;function initialize() {&lt;br /&gt;    if(_IE)&lt;br /&gt;        _XMLHTTP = new ActiveXObject('Microsoft.XMLHTTP');&lt;br /&gt;    else&lt;br /&gt;        _XMLHTTP = new XMLHttpRequest();&lt;br /&gt;&lt;br /&gt;    _XMLHTTP.onreadystatechange = stateChangeHandler;&lt;br /&gt;&lt;br /&gt;    _XMLHTTP.open('GET',_URL,true);     // Asynchronous (true)&lt;br /&gt;    _XMLHTTP.send(null);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;   Handle the asynchronous response to a XMLHttpRequest,&lt;br /&gt;   including the loading of the XML Data Island.&lt;br /&gt;*/&lt;br /&gt;function stateChangeHandler() {&lt;br /&gt;  if(_XMLHTTP.readyState == 4) {&lt;br /&gt;    var strHTML = '';&lt;br /&gt;    var nodeCount;&lt;br /&gt;&lt;br /&gt;    if(_IE) {&lt;br /&gt;&lt;br /&gt;document.getElementById('xmlDI').XMLDocument.load(_XMLHTTP.responseXML);&lt;br /&gt;      nodeCount =&lt;br /&gt;document.getElementById('xmlDI').XMLDocument.getElementsByTagName('state_n&lt;br /&gt;ame').length;&lt;br /&gt;    } else {&lt;br /&gt;      document.getElementById('xmlDI').innerHTML = _XMLHTTP.responseText;&lt;br /&gt;      nodeCount = document.body.getElementsByTagName('state_name').length;&lt;br /&gt;    }&lt;br /&gt;      try {&lt;br /&gt;          _XMLHTTP.close();            //  Close XMLHttpRequest&lt;br /&gt;      }&lt;br /&gt;      catch(e) {}&lt;br /&gt;&lt;br /&gt;      for(var i=0;i &lt; nodeCount;i++)&lt;br /&gt;        strHTML += '&lt;div xmldi="xmlDI" xmlnode="state_name"&gt;&lt;/div&gt;';&lt;br /&gt;&lt;br /&gt;      document.getElementById('show').innerHTML = strHTML;&lt;br /&gt;&lt;br /&gt;      _bind();                              //  Bind XML and HTML&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;   Handle the logic necessary to bind HTML elements to XML&lt;br /&gt;   nodes. Note that in some instances this binding is a two-way&lt;br /&gt;   street. For example, if the value in a text box should&lt;br /&gt;   change the corresponding value in the XML data island will&lt;br /&gt;   also change.&lt;br /&gt;*/&lt;br /&gt;function _bind() {&lt;br /&gt;  if(arguments.length == 0) {&lt;br /&gt;    doBind(document.body.getElementsByTagName('div'));&lt;br /&gt;    doBind(document.body.getElementsByTagName('input'));&lt;br /&gt;    doBind(document.body.getElementsByTagName('select'));&lt;br /&gt;    doBind(document.body.getElementsByTagName('span'));&lt;br /&gt;    doBind(document.body.getElementsByTagName('textarea'));&lt;br /&gt;  } else {&lt;br /&gt;    applyChange(arguments[0],arguments[1]);&lt;br /&gt;    _bind();                                 // Re-bind&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;     To handle data-binds for specific nodes based upon HTML&lt;br /&gt;     element type and browser type.&lt;br /&gt;  */&lt;br /&gt;  function doBind(objects) {&lt;br /&gt;    var strTag;                         //  HTML tag&lt;br /&gt;    var strDI;                          //  XML data island id&lt;br /&gt;    var strNode;                        //  XML node name&lt;br /&gt;    var strValue;                       //  XML node value&lt;br /&gt;&lt;br /&gt;    for(var i=0;i &lt; objects.length;i++) {&lt;br /&gt;      strTag = objects[i].tagName;&lt;br /&gt;      strDI = objects[i].getAttribute('xmldi');&lt;br /&gt;      strNode = objects[i].getAttribute('xmlnode');&lt;br /&gt;      if(strDI != null &amp;&amp; strNode != null) {&lt;br /&gt;        if(_IE)&lt;br /&gt;            strValue =&lt;br /&gt;document.getElementById(strDI).XMLDocument.selectNodes('//' +&lt;br /&gt;strNode).item(i).text;&lt;br /&gt;        else&lt;br /&gt;            strValue =&lt;br /&gt;document.getElementById(strDI).getElementsByTagName(strNode)[i].innerHTML;&lt;br /&gt;&lt;br /&gt;        switch(strTag) {&lt;br /&gt;            case('DIV'):&lt;br /&gt;            case('SPAN'):&lt;br /&gt;                objects[i].innerHTML = strValue;&lt;br /&gt;&lt;br /&gt;                break;&lt;br /&gt;            case('INPUT'):&lt;br /&gt;                switch(objects[i].type) {&lt;br /&gt;                    case('text'):&lt;br /&gt;                    case('hidden'):&lt;br /&gt;                    case('password'):&lt;br /&gt;                        objects[i].value = strValue;&lt;br /&gt;                        objects[i].onchange = new Function("_bind(this," +&lt;br /&gt;i.toString() + ")");&lt;br /&gt;                        break;&lt;br /&gt;                    case('checkbox'):&lt;br /&gt;                        if(objects[i].value == strValue)&lt;br /&gt;                            objects[i].checked = true;&lt;br /&gt;                        else&lt;br /&gt;                            objects[i].checked = false;&lt;br /&gt;                        objects[i].onclick = new Function("_bind(this," +&lt;br /&gt;i.toString() + ")");&lt;br /&gt;                        break;&lt;br /&gt;                    case('radio'):&lt;br /&gt;                        if(_IE)&lt;br /&gt;                            strValue =&lt;br /&gt;document.getElementById(strDI).XMLDocument.selectNodes('//' +&lt;br /&gt;strNode).item(0).text;&lt;br /&gt;                        else&lt;br /&gt;                            strValue =&lt;br /&gt;document.getElementById(strDI).getElementsByTagName(strNode)[0].innerHTML;&lt;br /&gt;&lt;br /&gt;                        if(objects[i].value == strValue)&lt;br /&gt;                            objects[i].checked = true;&lt;br /&gt;                        else&lt;br /&gt;                            objects[i].checked = false;&lt;br /&gt;&lt;br /&gt;                        objects[i].onclick = new&lt;br /&gt;Function("_bind(this,0)");&lt;br /&gt;                        break;&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                break;&lt;br /&gt;            case('SELECT'):&lt;br /&gt;            case('TEXTAREA'):&lt;br /&gt;                objects[i].value = strValue;&lt;br /&gt;                objects[i].onchange = new Function("_bind(this," +&lt;br /&gt;i.toString() + ")");&lt;br /&gt;&lt;br /&gt;                break;&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;     To handle changes to the bound HTML elements and apply&lt;br /&gt;     those changes to the appropriate XML node.&lt;br /&gt;  */&lt;br /&gt;  function applyChange(obj,index) {&lt;br /&gt;    var strDI = obj.getAttribute('xmldi');&lt;br /&gt;    var strNode = obj.getAttribute('xmlnode');&lt;br /&gt;    var strValue = obj.value;&lt;br /&gt;&lt;br /&gt;    if(obj.type == 'checkbox')&lt;br /&gt;        if(obj.checked)&lt;br /&gt;            strValue = obj.value;&lt;br /&gt;        else&lt;br /&gt;            strValue = '';&lt;br /&gt;    if(_IE)&lt;br /&gt;        document.getElementById(strDI).XMLDocument.selectNodes('//' +&lt;br /&gt;strNode).item(index).text = strValue;&lt;br /&gt;    else&lt;br /&gt;&lt;br /&gt;document.getElementById(strDI).getElementsByTagName(strNode)[index].&lt;br /&gt;innerHTML = strValue;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;            &lt;/script&gt;&lt;br /&gt;     &lt;br /&gt;      &lt;body onload="initialize()"&gt;&lt;br /&gt;            &lt;xml id="xmlDI"&gt;&lt;br /&gt;            &lt;/xml&gt;&lt;br /&gt;            &lt;b&gt;XML Data Island Test&lt;/b&gt;&lt;br /&gt;            &lt;br /&gt;&lt;br /&gt;            &lt;div id="show"&gt;&lt;/div&gt;&lt;br /&gt;      &lt;/body&gt;&lt;br /&gt;&lt;br /&gt;Essentially, the JavaScript in Listing 8-9 makes an asynchronous XMLHTTP request. This entails, beyond the usual "which browser is it?" stuff, creating an instance of the XMLHttpRequest object, setting an event handler for the response, and making the request using the request type, the URL, and TRue for asynchronous. The state change handler, er, handles the response from the server. If you look closely, you'll see a condition testing the readyState property to see if it is equal to 4, which is complete. The reason for testing the readyState property is that this handler fires multiple times for different reasons, ranging from the equivalent of "I'm sitting here" to "Hey, I'm getting a response."&lt;br /&gt;The previous example illustrated how to use the XMLHttpRequest object to asynchronously obtain an XML document from a file located on the server. Think of it as something along the lines of a proof of concept because the odds are against the XML document needed sitting in a folder on the web server. Instead, there will probably be some script version of Igor sitting around watching Oprah, waiting for some real work to do.&lt;br /&gt;Several different methods exist for getting data to and from our virtual Igor, ranging from a simple custom approach to slightly more complex XML-based standards. One of the standards that can be used to get the virtual Igor moving is called XML Remote Procedure Calling, or XML-RPC, for short. In a nutshell, XML-RPC is a World Wide Web Consortium Recommendation that describes a request/response protocol. A request is posted to the web server, and the web server acts upon the request and returns a response. This entire process might sound rather complex, but it really isn't any more difficult than what we've already accomplished. The only differences are that instead of a GET, we'll be doing a POST, and the request needs to be in XML, as shown in Listing 8-10 and the response in Listing 8-11.&lt;br /&gt;Listing 8-10. XML-RPC Request&lt;br /&gt;&lt;?xml version="1.0"?&gt;&lt;br /&gt;&lt;methodCall&gt;&lt;br /&gt;      &lt;methodName&gt;igor.getGuildName&lt;/methodName&gt;&lt;br /&gt;      &lt;params&gt;&lt;br /&gt;            &lt;param&gt;&lt;br /&gt;                  &lt;value&gt;&lt;br /&gt;                        &lt;int&gt;1&lt;/int&gt;&lt;br /&gt;                  &lt;/value&gt;&lt;br /&gt;            &lt;/param&gt;&lt;br /&gt;      &lt;/params&gt;&lt;br /&gt;&lt;/methodCall&gt;&lt;br /&gt;Listing 8-11. XML-RPC Response&lt;br /&gt;&lt;?xml version="1.0"?&gt;&lt;br /&gt;&lt;methodResponse&gt;&lt;br /&gt;      &lt;params&gt;&lt;br /&gt;            &lt;param&gt;&lt;br /&gt;                  &lt;value&gt;&lt;br /&gt;                        &lt;string&gt;Mad Scientist&lt;/string&gt;&lt;br /&gt;                  &lt;/value&gt;&lt;br /&gt;            &lt;/param&gt;&lt;br /&gt;      &lt;/params&gt;&lt;br /&gt;&lt;/methodResponse&gt;&lt;br /&gt;As you've probably deduced from this, the structure of the XML document goes along the lines of methodCall, params, param, value, and, finally, data type (integer, in this instance). The rule for the structure goes along the lines of one methodResponse, one params, and at least one param. In addition, each param can have only one valueno more, no less. Values, in turn, have a single node that both describes and holds the data. Table 8-1 shows the valid data types for XML-RPC.&lt;br /&gt;Table 8-1. XML-RPC Data Types Type&lt;br /&gt; Description&lt;br /&gt; int 4-byte signed integer i4 4-byte signed integer&lt;br /&gt; boolean  True = 1 and false = 0&lt;br /&gt; sting Character string&lt;br /&gt; double Double-precision floating point&lt;br /&gt; dateTime.iso8601 Date/time&lt;br /&gt; &lt;br /&gt;base64&lt;br /&gt; Base 64 binary&lt;br /&gt; Of course, communicating a single item of information as shown is pretty rare. More common are more complex data structures, such as arrays or the record-line structs. Both arrays and structs work pretty much along the same lines as the simpler example earlier. Listing 8-12 shows an example of an array, and Listing 8-13 shows an example of a struct.&lt;br /&gt;&lt;br /&gt;Listing 8-12. XML-RPC Array&lt;br /&gt;&lt;?xml version="1.0"?&gt;&lt;br /&gt;&lt;array&gt;&lt;br /&gt;      &lt;data&gt;&lt;br /&gt;            &lt;value&gt;&lt;br /&gt;                  &lt;int&gt;5&lt;/i4&gt;&lt;br /&gt;            &lt;/value&gt;&lt;br /&gt;            &lt;value&gt;&lt;br /&gt;                  &lt;string&gt;Lab Coat&lt;/string&gt;&lt;br /&gt;            &lt;/value&gt;&lt;br /&gt;            &lt;value&gt;&lt;br /&gt;                  &lt;double&gt;29.95&lt;/double&gt;&lt;br /&gt;            &lt;/value&gt;&lt;br /&gt;      &lt;/data&gt;&lt;br /&gt;&lt;/array&gt;&lt;br /&gt;Listing 8-13. XML-RPC Struct&lt;br /&gt;&lt;?xml version="1.0"?&gt;&lt;br /&gt;&lt;struct&gt;&lt;br /&gt;      &lt;member&gt;&lt;br /&gt;            &lt;name&gt;name_last&lt;/name&gt;&lt;br /&gt;            &lt;value&gt;&lt;br /&gt;                  &lt;string&gt;Woychowsky&lt;/&gt;&lt;br /&gt;            &lt;/value&gt;&lt;br /&gt;      &lt;/member&gt;&lt;br /&gt;      &lt;member&gt;&lt;br /&gt;            &lt;name&gt;name_first&lt;/name&gt;&lt;br /&gt;            &lt;value&gt;&lt;br /&gt;                  &lt;string&gt;Edmond&lt;/string&gt;&lt;br /&gt;            &lt;/value&gt;&lt;br /&gt;      &lt;/member&gt;&lt;br /&gt;      &lt;member&gt;&lt;br /&gt;            &lt;name&gt;purpose&lt;/name&gt;&lt;br /&gt;            &lt;value&gt;&lt;br /&gt;                  &lt;int&gt;42&lt;/int&gt;&lt;br /&gt;            &lt;/value&gt;&lt;br /&gt;      &lt;/member&gt;&lt;br /&gt;&lt;/struct&gt;&lt;br /&gt;The array example shown is merely an elaboration of the earlier simple XML document, but the struct example is more complex. Along with specifying the parameter type and value, it specifies the name of the parameter. This might not seem like much, but it is useful in applications with so many parameters that it becomes difficult to keep their relative positions straight.&lt;br /&gt;This leads us to the question, what does the response look like when the relative positions aren't kept straight? That's simple enough; a fault like the one in Listing 8-14 is returned.&lt;br /&gt;Listing 8-14. XML-RPC Fault&lt;br /&gt;&lt;?xml version="1.0"?&gt;&lt;br /&gt;&lt;methodResponse&gt;&lt;br /&gt;      &lt;fault&gt;&lt;br /&gt;            &lt;value&gt;&lt;br /&gt;                  &lt;struct&gt;&lt;br /&gt;                        &lt;member&gt;&lt;br /&gt;                              &lt;name&gt;faultCode&lt;/name&gt;&lt;br /&gt;                              &lt;value&gt;&lt;br /&gt;                                    &lt;int&gt;86&lt;/int&gt;&lt;br /&gt;                              &lt;/value&gt;&lt;br /&gt;                        &lt;/member&gt;&lt;br /&gt;                        &lt;member&gt;&lt;br /&gt;                              &lt;name&gt;faultString&lt;/name&gt;&lt;br /&gt;                              &lt;value&gt;&lt;br /&gt;                                    &lt;string&gt;&lt;br /&gt;                                          Invalid data type.&lt;br /&gt;                                    &lt;/string&gt;&lt;br /&gt;                              &lt;/value&gt;&lt;br /&gt;                        &lt;/member&gt;&lt;br /&gt;                  &lt;/struct&gt;&lt;br /&gt;            &lt;/value&gt;&lt;br /&gt;      &lt;/fault&gt;&lt;br /&gt;&lt;/methodResponse&gt;&lt;br /&gt;&lt;br /&gt;Now that we know what the request looks like ordinarily, the next step is to modify the previous example, in which the XSLT was retrieved through the XMLHttpRequest object and a GET to use XML-RPC. This time, however, we skip the examples and progress directly to what is considered by some the protocol of choice when creating web services: SOAP.&lt;br /&gt;&lt;br /&gt;8.3.3. Cleaning Up with SOAP&lt;br /&gt;Other than being something for cleaning, SOAP is an acronym for Simple Object Access Protocol, a protocol used to communicate between web browsers and web servers. SOAP is probably one of the more difficult subjects to research on the web, if for no other reason than the multiple websites that deal with the original SOAP. Nevertheless, when searching, you eventually will obtain the desired results and discover that SOAP is nothing more than a wrapper for XML.&lt;br /&gt;&lt;br /&gt;XML-RPC was designed to provide a standard structure. However, with SOAP, a slightly different approach was used. Instead of the strict params-param-value used by XML-RPC, which rigidly ties the information with the wrapper, SOAP uses a more flexible envelope method. As with a physical envelope, a SOAP envelope both identifies the recipient and contains the message within. The only real difference between a SOAP envelope and a physical envelope is that the message contained by a SOAP envelope must be well formed, like the one shown in Listing 8-15.&lt;br /&gt;&lt;br /&gt;Listing 8-15. SOAP Request&lt;br /&gt;&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&lt;soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;br /&gt;xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;&lt;br /&gt;  &lt;soap:Body&gt;&lt;br /&gt;    &lt;getItems xmlns="http://tempuri.org/"&gt;&lt;br /&gt;      &lt;guild_item_id&gt;string&lt;/guild_item_id&gt;&lt;br /&gt;      &lt;guild_id&gt;string&lt;/guild_id&gt;&lt;br /&gt;    &lt;/getItems&gt;&lt;br /&gt;  &lt;/soap:Body&gt;&lt;br /&gt;&lt;/soap:Envelope&gt;&lt;br /&gt;As with the XML-RPC example, there are two possible responses to a SOAP request. Either the web service worked and returned a SOAP response, as shown in Listing 8-16, or some kind of error occurred, and the request failed and a SOAP fault was returned. Listing 8-17 contains an example of a SOAP fault.&lt;br /&gt;Listing 8-16. SOAP Response&lt;br /&gt;&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;br /&gt;&lt;soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;br /&gt;xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;&lt;br /&gt;  &lt;soap:Body&gt;&lt;br /&gt;    &lt;getItemsResponse xmlns="http://tempuri.org/"&gt;&lt;br /&gt;      &lt;getItemsResult&gt;xml&lt;/getItemsResult&gt;&lt;br /&gt;    &lt;/getItemsResponse&gt;&lt;br /&gt;  &lt;/soap:Body&gt;&lt;br /&gt;&lt;/soap:Envelope&gt;&lt;br /&gt;Listing 8-17. SOAP Fault&lt;br /&gt;&lt;soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-&lt;br /&gt;instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:soap="http://sc&lt;br /&gt;hemas.xmlsoap.org/soap/envelope/"&gt;&lt;br /&gt;  &lt;soap:Body&gt;&lt;br /&gt;    &lt;soap:Fault&gt;&lt;br /&gt;      &lt;faultcode&gt;soap:MustUnderstand&lt;/faultcode&gt;&lt;br /&gt;      &lt;faultstring&gt;Mandatory Header error.&lt;/faultstring&gt;&lt;br /&gt;      &lt;faultactor&gt;http://localhost/AJAX4/chapter4.asmx&lt;/faultactor&gt;&lt;br /&gt;      &lt;detail&gt;Web Service coffee break.&lt;/detail&gt;&lt;br /&gt;    &lt;/soap:Fault&gt;&lt;br /&gt;  &lt;/soap:Body&gt;&lt;br /&gt;&lt;/soap:Envelope&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7185888557737734065?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7185888557737734065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/xmlhttprequest-object.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7185888557737734065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7185888557737734065'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/xmlhttprequest-object.html' title='The XMLHttpRequest Object'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1738129524918724474</id><published>2008-12-13T12:06:00.000-08:00</published><updated>2009-01-26T12:29:52.720-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>A Problem Revisited</title><content type='html'>Now that we have covered some of the necessary background material for using XML, SOAP, and XMLHTTP, let's apply it to the e-commerce site. As you might recall, the objective of the site is to provide materials for the often-overlooked market of mad scientists, alchemists, and sorcerers. In Chapter 5, we created pages using a primitive ancestor of Ajax; now let's give it a shot using the real thing. This doesn't mean that it is entirely necessary to completely abandon hidden frames. If you decide that you need them, then by all means, use them; we abandon hidden frames from here on, however.&lt;br /&gt;&lt;br /&gt;In addition, we change server-side languages from PHP to C#. The reason for this change isn't that PHP can't be used to develop web services; it is actually the fact that I'm more comfortable using C# for developing web services. To those of you who question the presence of C# in an open source book, I have one word for you: Mono.&lt;br /&gt;&lt;br /&gt;No, not the Mono that everybody came down with in high school, college, or, in my case, Bell Labsthe Mono that is the open source implementation of the .NET Framework. You haven't lived until you've seen a C# application running under Linux. It doesn't feel wrong; it feels more like when Lieutenant Commander Worf said: "Assimilate this!" in Star Trek First Contact.&lt;br /&gt;&lt;br /&gt;Listing 8-18 contains the web service that will handle the server-side requirements for the remainder of this chapter.&lt;br /&gt;&lt;br /&gt;Listing 8-18. A Web Service&lt;br /&gt;using System;&lt;br /&gt;using System.Collections;&lt;br /&gt;using System.ComponentModel;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Diagnostics;&lt;br /&gt;using System.IO;&lt;br /&gt;using System.Web;&lt;br /&gt;using System.Web.Services;&lt;br /&gt;using System.Web.Services.Protocols;&lt;br /&gt;using System.Xml;&lt;br /&gt;using MySql.Data.MySqlClient;&lt;br /&gt;using MySql.Data.Types;&lt;br /&gt;namespace AJAX&lt;br /&gt;{&lt;br /&gt;  /// &lt;summary&gt;&lt;br /&gt;  /// Summary description for msas.&lt;br /&gt;  /// &lt;/summary&gt;&lt;br /&gt;  public class msas : System.Web.Services.WebService&lt;br /&gt;  {&lt;br /&gt;    const string CONNECTION_STRING =&lt;br /&gt;      "Persist Security&lt;br /&gt;Info=False;database=ajax;server=localhost;username=root;password=wyvern";&lt;br /&gt;&lt;br /&gt;    public msas()&lt;br /&gt;    {&lt;br /&gt;      InitializeComponent();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #region Component Designer generated code&lt;br /&gt;&lt;br /&gt;    //Required by the Web Services Designer&lt;br /&gt;    private IContainer components = null;&lt;br /&gt;&lt;br /&gt;    /// &lt;summary&gt;&lt;br /&gt;    /// Required method for Designer support - do not modify&lt;br /&gt;    /// the contents of this method with the code editor.&lt;br /&gt;    /// &lt;/summary&gt;&lt;br /&gt;    private void InitializeComponent()&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /// &lt;summary&gt;&lt;br /&gt;    /// Clean up any resources being used.&lt;br /&gt;    /// &lt;/summary&gt;&lt;br /&gt;    protected override void Dispose( bool disposing )&lt;br /&gt;    {&lt;br /&gt;      if(disposing &amp;&amp; components != null)&lt;br /&gt;      {&lt;br /&gt;        components.Dispose();&lt;br /&gt;      }&lt;br /&gt;      base.Dispose(disposing);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    [WebMethod]&lt;br /&gt;    public XmlDocument getState(string state_abbreviation)&lt;br /&gt;    {&lt;br /&gt;      MySqlConnection connection =&lt;br /&gt;      new MySqlConnection(CONNECTION_STRING);&lt;br /&gt;      MySqlDataAdapter adapter = new MySqlDataAdapter();&lt;br /&gt;      DataSet dataSet = new DataSet();&lt;br /&gt;      XmlDocument xml = new XmlDocument();&lt;br /&gt;      string query = "CALL stateSelect(NULL)";&lt;br /&gt;      if(state_abbreviation.Length != 0)&lt;br /&gt;        query = "CALL stateSelect('" + state_abbreviation + "')";&lt;br /&gt;&lt;br /&gt;      adapter.SelectCommand =&lt;br /&gt;      new MySqlCommand(query, connection);&lt;br /&gt;      adapter.Fill(dataSet);&lt;br /&gt;      xml.LoadXml(dataSet.GetXml());&lt;br /&gt;&lt;br /&gt;      connection.Close();&lt;br /&gt;&lt;br /&gt;      return(xml);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [WebMethod]&lt;br /&gt;    public XmlDocument getXML(string name)&lt;br /&gt;    {&lt;br /&gt;      XmlDocument xml = new XmlDocument();&lt;br /&gt;&lt;br /&gt;      try&lt;br /&gt;      {&lt;br /&gt;        xml.Load(Server.MapPath(name));&lt;br /&gt;      }&lt;br /&gt;      catch(Exception e)&lt;br /&gt;      {&lt;br /&gt;        StringWriter writer = new StringWriter();&lt;br /&gt;        Server.UrlEncode(name, writer);&lt;br /&gt;        String encodedName = writer.ToString();&lt;br /&gt;        XmlNode node =&lt;br /&gt;        xml.CreateNode(XmlNodeType.CDATA,"detail","");&lt;br /&gt;&lt;br /&gt;        node.Value = encodedName;&lt;br /&gt;&lt;br /&gt;        throw(new&lt;br /&gt;SoapException(e.Message,SoapException.ClientFaultCode,"",node));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      return(xml);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [WebMethod]&lt;br /&gt;    public XmlDocument getItems(string guild_item_id,string guild_id)&lt;br /&gt;    {&lt;br /&gt;      MySqlConnection connection =&lt;br /&gt;      new MySqlConnection(CONNECTION_STRING);&lt;br /&gt;      MySqlDataAdapter adapter = new MySqlDataAdapter();&lt;br /&gt;      DataSet dataSet = new DataSet();&lt;br /&gt;      XmlDocument xml = new XmlDocument();&lt;br /&gt;      string query;&lt;br /&gt;&lt;br /&gt;      if(guild_item_id.Length == 0)&lt;br /&gt;        if(guild_id.Length == 0)&lt;br /&gt;          query = "CALL itemSelect(NULL,NULL)";&lt;br /&gt;        else&lt;br /&gt;          query = "CALL itemSelect(NULL," + guild_id + ")";&lt;br /&gt;      else&lt;br /&gt;        if(guild_id.Length == 0)&lt;br /&gt;          query = "CALL itemSelect(" + guild_item_id + ",NULL)";&lt;br /&gt;        else&lt;br /&gt;          query = "CALL itemSelect(" + guild_item_id + "," + guild_id +&lt;br /&gt;")";&lt;br /&gt;      adapter.SelectCommand =&lt;br /&gt;      new MySqlCommand(query, connection);&lt;br /&gt;      adapter.Fill(dataSet);&lt;br /&gt;      xml.LoadXml(dataSet.GetXml());&lt;br /&gt;&lt;br /&gt;      connection.Close();&lt;br /&gt;&lt;br /&gt;      return(xml);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;I'd like to point out that the web service shown handles several different jobs. First, if necessary, it performs database queries against a MySQL database. Immediately following the queries, it builds the XHTML required to display the page; finally, it creates a node that contains a line of JavaScript. All this is then incorporated into a single XML document, which is then sent to the client. Although this might seem a wee bit strange, there is a method to my madness. As with the hidden frames example, there will be a single HTML document that also has several different jobs to perform.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1738129524918724474?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1738129524918724474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/problem-revisited.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1738129524918724474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1738129524918724474'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/problem-revisited.html' title='A Problem Revisited'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-238675279082751481</id><published>2008-12-13T12:00:00.000-08:00</published><updated>2008-12-13T12:03:53.080-08:00</updated><title type='text'>Tabular Information and Forms</title><content type='html'>With the server side taken care of, there are three ways to proceed with developing on the client side. The first is to continue developing the way that we've been developing, hand-coding every function. Although this would give us a really good understanding of how the application works, it would take forever to develop anything useful.&lt;br /&gt;The second approach is to get online and find a suitable Ajax library, download it, and proceed with developing. Currently, quite a number of them are out there, such as Sarissa and JSON (pronounced "Jason"). (However, if memory serves, Jason was the leader or the Argonauts, whereas Ajax was a hero of the Trojan War.)&lt;br /&gt;The third possibility is to write our own Ajax libraryor, rather, use one that I've already written. This approach is useful for several reasons, the first being that I'll (hopefully) know exactly how the library works. The second reason is that I can dissect them in a later chapter so that we'll know exactly how they work. The final reason is that it will help to pad the page counteh, I mean, to increase the depth of these examples. Table 8-2 briefly describes the classes in the library, along with their associated methods and properties.&lt;br /&gt;Table 8-2. Ajax Library Classes Name&lt;br /&gt; Parent Class&lt;br /&gt; Type&lt;br /&gt; Description&lt;br /&gt; XMLHttpRequest&lt;br /&gt;  Class&lt;br /&gt; Constructor&lt;br /&gt; action&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Property&lt;br /&gt; GET, POST, or HEAD&lt;br /&gt; asynchronous&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Property&lt;br /&gt; true or false&lt;br /&gt; envelope&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Property&lt;br /&gt; SOAP envelope&lt;br /&gt; readyState&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Method&lt;br /&gt; Returns the document readyState&lt;br /&gt; getresponseHeader&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Method&lt;br /&gt; Returns a single HTTP response header&lt;br /&gt; getAllResponseHeaders&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Method&lt;br /&gt; Returns all HTTP response headers&lt;br /&gt; responseText&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Method&lt;br /&gt; Returns the SOAP response as text&lt;br /&gt; responseXML&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Method&lt;br /&gt; Returns the SOAP response as an XML document&lt;br /&gt; stateChangeHandler&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Method&lt;br /&gt; Dummy state change handler&lt;br /&gt; setRequestHeader&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Method&lt;br /&gt; Sets an HTTP response header&lt;br /&gt; removeRequestHeader&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Method&lt;br /&gt; Removes a previously set HTTP response header&lt;br /&gt; Send&lt;br /&gt; XMLHttpRequest&lt;br /&gt; Method&lt;br /&gt; Sends the XMLHttpRequest&lt;br /&gt; Cache&lt;br /&gt;  Class&lt;br /&gt; Constructor&lt;br /&gt; insert&lt;br /&gt; Cache&lt;br /&gt; Method&lt;br /&gt; Inserts a name/value pair&lt;br /&gt; retrieve&lt;br /&gt; Cache&lt;br /&gt; Method&lt;br /&gt; Retrieves a value&lt;br /&gt; purge&lt;br /&gt; Cache&lt;br /&gt; Method&lt;br /&gt; Purges one or more name/value pairs&lt;br /&gt; names&lt;br /&gt; Cache&lt;br /&gt; Method&lt;br /&gt; Returns an array of names&lt;br /&gt; XMLDocument&lt;br /&gt;  Class&lt;br /&gt; Constructor&lt;br /&gt; Load&lt;br /&gt; XMLDocument&lt;br /&gt; Method&lt;br /&gt; Loads an\ XML document&lt;br /&gt; serialize&lt;br /&gt; XMLDocument&lt;br /&gt; Method&lt;br /&gt; Serializes an XML document to text&lt;br /&gt; DOMDocument&lt;br /&gt; XMLDocument&lt;br /&gt; Method&lt;br /&gt; Returns an XML document&lt;br /&gt; readyState&lt;br /&gt; XMLDocument&lt;br /&gt; Method&lt;br /&gt; Returns the document readyState&lt;br /&gt; setRequestHeader&lt;br /&gt; XMLDocument&lt;br /&gt; Method&lt;br /&gt; Sets an HTTP response header&lt;br /&gt; getresponseHeader&lt;br /&gt; XMLDocument&lt;br /&gt; Method&lt;br /&gt; Returns a single HTTP response header&lt;br /&gt; getAllResponseHeaders&lt;br /&gt; XMLDocument&lt;br /&gt; Method&lt;br /&gt; Returns all HTTP response headers&lt;br /&gt; setEnvelope&lt;br /&gt; XMLDocument&lt;br /&gt; Method&lt;br /&gt; Sets the envelope for an XMLHttpRequest&lt;br /&gt; selectNodes&lt;br /&gt; XMLDocument&lt;br /&gt; Method&lt;br /&gt; Returns an array of XML nodes&lt;br /&gt; SOAPEnvelope&lt;br /&gt;  Class&lt;br /&gt; Constructor&lt;br /&gt; envelope&lt;br /&gt; SOAPEnvelope&lt;br /&gt; Method&lt;br /&gt; SOAP envelope&lt;br /&gt; Now that the foundations of the application architecture have been covered, albeit lightly, this is a good time to see what the HTML page built upon that architecture looks like. Figure 8-6 shows what it looks like in a browser, and Listing 8-19 shows the HTML and JavaScript.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-238675279082751481?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/238675279082751481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/tabular-information-and-forms.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/238675279082751481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/238675279082751481'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/tabular-information-and-forms.html' title='Tabular Information and Forms'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-952282184177594119</id><published>2008-12-13T11:57:00.000-08:00</published><updated>2009-01-26T12:29:52.721-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>Chapter 9. XPath</title><content type='html'>Just what is XPath? Briefly stated, XPath is to XML what an SQL SELECT is to a relational database. This might at first sound like an oversimplification, but it is essentially true. XPath can be used to locate and navigate the various parts of an XML document. Unfortunately, as with every other language under the sun, a number of unique terms should be defined before you can start understanding it. These concepts and terms might at first seem overwhelming, but they are essential to both querying XML and keeping us employed.&lt;br /&gt;&lt;br /&gt;Although you can choose to fluff over these terms, I actually don't recommend it, if only for the purpose of job security. Several years ago, I used my understanding of terms to extend a contract when the client, who is widely known for being frugal, wanted to save money by having their employee mainframe programmers support a web application. During the turnover process, I described how the site worked using the precise web and XML terms. To make a long story short, the contract was extended for another two years.&lt;br /&gt;&lt;br /&gt;The first concept is that, even with all the hoopla surrounding all things XML, it is essentially nothing more than data represented in a tree data structure. Looking at XML from an XPath perspective, XML consists of only seven types of nodes:&lt;br /&gt;&lt;br /&gt;The root nodeonly one per XML document. All other nodes are child nodes of the root node.&lt;br /&gt;&lt;br /&gt;Element nodes.&lt;br /&gt;&lt;br /&gt;Text nodes.&lt;br /&gt;&lt;br /&gt;Attribute nodes.&lt;br /&gt;&lt;br /&gt;Comment nodes.&lt;br /&gt;&lt;br /&gt;Processing instruction nodes.&lt;br /&gt;&lt;br /&gt;Namespace nodes.&lt;br /&gt;&lt;br /&gt;Note that DTDs (Data Type Definitions), CDATA sections, and entity references are not included in this list of node types, each for different reasons. Because a DTD is not an XML document, XPath is incapable of addressing it. CDATA, on the other hand, is a part of XML but, by design, is ignored by XPath, as are entity references.&lt;br /&gt;&lt;br /&gt;In addition, it is important to note that the root element and the root node are not different terms for the same thing. Using the XML document shown in Listing 9-1, an XML document's root node contains both the processing instruction, &lt;?xml version="1.0" encoding="UTF-8"?&gt;, and the root element, &lt;library&gt;.&lt;br /&gt;&lt;br /&gt;Listing 9-1. Example XML Document&lt;br /&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;br /&gt;&lt;library&gt;&lt;br /&gt;      &lt;book publisher="Del Rey"&gt;&lt;br /&gt;            &lt;series/&gt;&lt;br /&gt;            &lt;titles&gt;Way Station&lt;/titles&gt;&lt;br /&gt;            &lt;author&gt;Clifford D. Simak&lt;/author&gt;&lt;br /&gt;      &lt;/book&gt;&lt;br /&gt;      &lt;book publisher="Del Rey"&gt;&lt;br /&gt;            &lt;series&gt;The Lord of the Rings&lt;/series&gt;&lt;br /&gt;            &lt;titles&gt;The Fellowship of the Ring&lt;/titles&gt;&lt;br /&gt;            &lt;author&gt;J.R.R. Tolkien&lt;/author&gt;&lt;br /&gt;      &lt;/book&gt;&lt;br /&gt;      &lt;book publisher="Del Rey"&gt;&lt;br /&gt;            &lt;series&gt;The Lord of the Rings&lt;/series&gt;&lt;br /&gt;            &lt;titles&gt;The Two Towers&lt;/titles&gt;&lt;br /&gt;            &lt;author&gt;J.R.R. Tolkien&lt;/author&gt;&lt;br /&gt;      &lt;/book&gt;&lt;br /&gt;      &lt;book publisher="Del Rey"&gt;&lt;br /&gt;            &lt;series&gt;The Lord of the Rings&lt;/series&gt;&lt;br /&gt;            &lt;titles&gt;The Return of the King&lt;/titles&gt;&lt;br /&gt;            &lt;author&gt;J.R.R. Tolkien&lt;/author&gt;&lt;br /&gt;      &lt;/book&gt;&lt;br /&gt;      &lt;book publisher="Ace"&gt;&lt;br /&gt;            &lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;            &lt;titles&gt;Too Many Magicians&lt;/titles&gt;&lt;br /&gt;            &lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;      &lt;/book&gt;&lt;br /&gt;      &lt;book publisher="Ace"&gt;&lt;br /&gt;            &lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;            &lt;titles&gt;Murder and Magic&lt;/titles&gt;&lt;br /&gt;            &lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;      &lt;/book&gt;&lt;br /&gt;      &lt;book publisher="Ace"&gt;&lt;br /&gt;            &lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;            &lt;titles&gt;The Napoli Express&lt;/titles&gt;&lt;br /&gt;            &lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;      &lt;/book&gt;&lt;br /&gt;      &lt;book publisher="Ace"&gt;&lt;br /&gt;            &lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;            &lt;titles&gt;Lord Darcy Investigates&lt;/titles&lt;br /&gt;            &lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;      &lt;/book&gt;&lt;br /&gt;&lt;/library&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-952282184177594119?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/952282184177594119/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-9-xpath.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/952282184177594119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/952282184177594119'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-9-xpath.html' title='Chapter 9. XPath'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-544703706009166211</id><published>2008-12-13T11:55:00.001-08:00</published><updated>2009-01-26T12:29:52.721-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax Http Request'/><title type='text'>Listing 10-1. Simple Style Sheet to Copy the Source XML Document to the Result XML Document </title><content type='html'>Chapter 10. XSLT&lt;br /&gt;The movie Star Trek: The Wrath of Khan introduced a device called the Genesis Torpedo that rearranged matter on a subatomic level to produce life-bearing planets. Talk about your mad scientist stuff! eXtensible Stylesheet Language for Transformations (XSLT) is the XML equivalent to Star Trek's Genesis; it rearranges XML at the element level to produce the desired results. However, unlike Genesis, the desired results are not limited to a single type, but rather can be any conceivable XML or text-based format. In addition, instead of the original document being modified, a new document is created in the desired format, which could be identical to the original document or vastly different.&lt;br /&gt;&lt;br /&gt;An XSLT document, sometimes referred to as a style sheet, is a well-formed XML document that uses the XSLT namespace (xmlns:xsl=http://www.w3.org/1999/XSL/Transform) to describe the rules for transforming the source XML document into the result XML document. XSLT is always used in conjunction with XPath, which specifies the location of various elements within the source document. XSLT, on the other hand, describes the structure of the result document.&lt;br /&gt;&lt;br /&gt;Listing 10-1 contains a simple style sheet whose purpose is to simply copy the source XML document to the result XML document. Because no specific node names are used, this style sheet works equally well with all XML documents.&lt;br /&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0"&lt;br /&gt;      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;        &lt;xsl:output method="xml" version="1.0" encoding="UTF-8"/&gt;&lt;br /&gt;        &lt;xsl:template match="/"&gt;&lt;br /&gt;&lt;br /&gt;            &lt;xsl:copy-of select="."/&gt;&lt;br /&gt;&lt;br /&gt;      &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;The XSL style sheet shown in Listing 10-1 works like this. First, the XML declaration describes the version of XML and the character set encoding. The xsl:stylesheet element describes the document as a style sheet, and the attributes specify the version of XSLT and the namespace. The xsl:output element defines the result document's XML declaration. The xsl:template defines a relationship between the source XML document and the result document. For example, the match attribute with the / specifies the source document's root node; all child elements of this element will be applied to the root element. Finally, the xsl:copy-of specifies to perform a deep copy of the context node; in other words, copy the context node and all descendants recursively.&lt;br /&gt;This chapter covers the following topics:&lt;br /&gt;Recursive versus iterative style sheets&lt;br /&gt;XPath in the style sheet&lt;br /&gt;Elements&lt;br /&gt;XSLT functions&lt;br /&gt;XSLT concepts&lt;br /&gt;Client-side transformations&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-544703706009166211?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/544703706009166211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/listing-10-1-simple-style-sheet-to-copy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/544703706009166211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/544703706009166211'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/listing-10-1-simple-style-sheet-to-copy.html' title='Listing 10-1. Simple Style Sheet to Copy the Source XML Document to the Result XML Document '/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-6049841485579782894</id><published>2008-12-13T11:30:00.003-08:00</published><updated>2009-01-26T12:30:48.953-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><title type='text'>10.1. Recursive Versus Iterative Style Sheets</title><content type='html'>One of the things about XSLT is that although the capability exists for iteration (looping), it is strongly frowned upon by the development community. Instead, recursive templates are considered the acceptable standard. Although this philosophy requires some changes in the way developers think, it also means that recursive style sheets are often far more compact and not nested nearly as deep as their iterative counterparts. At the very least, recursive style sheets are always far more structured, which can be a major advantage in larger style sheets.&lt;br /&gt;Let's say that our goal is to create an XSLT table and the source XML document shown in Listing 10-2. As a starting point, there are two distinct courses of action: an iterative style sheet (see Listing 10-3) and a recursive style sheet (see Listing 10-4). Each of these two approaches to coding style sheets has its own strengths and weaknesses. For example, the iterative style sheet is about the same length, but it is also nested much deeper than the recursive style sheet.&lt;br /&gt;Listing 10-2. Source XML Document&lt;br /&gt;&lt;library&gt;&lt;br /&gt;&lt;book publisher="Del Rey"&gt;&lt;br /&gt;&lt;series&gt;&lt;titles&gt;tation&lt;/titles&gt;&lt;br /&gt;&lt;author&gt;Clifford D. Simak&lt;/author&gt;&lt;br /&gt;    &lt;/series&gt;&lt;book publisher="Del Rey"&gt;&lt;br /&gt;          &lt;series&gt;The Lord of the Rings&lt;/series&gt;&lt;br /&gt;          &lt;titles&gt;The Fellowship of the Ring&lt;/titles&gt;&lt;author&gt;J.R.R. Tolkien&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Del Rey"&gt;&lt;br /&gt;          &lt;series&gt;The Lord of the Rings&lt;/series&gt;&lt;br /&gt;          &lt;titles&gt;The Two Towers&lt;/titles&gt;&lt;br /&gt;          &lt;author&gt;J.R.R. Tolkien&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Del Rey"&gt;&lt;br /&gt;          &lt;series&gt;The Lord of the Rings&lt;/series&gt;&lt;br /&gt;          &lt;titles&gt;The Return of the King&lt;/titles&gt;&lt;br /&gt;          &lt;author&gt;J.R.R. Tolkien&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Ace"&gt;&lt;br /&gt;          &lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;          &lt;titles&gt;Too Many Magicians&lt;/titles&gt;&lt;br /&gt;          &lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Ace"&gt;&lt;br /&gt;          &lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;          &lt;titles&gt;Murder and Magic&lt;/titles&gt;&lt;br /&gt;          &lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Ace"&gt;&lt;br /&gt;          &lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;          &lt;titles&gt;The Napoli Express&lt;/titles&gt;&lt;br /&gt;          &lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Ace"&gt;&lt;br /&gt;          &lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;          &lt;titles&gt;Lord Darcy Investigates&lt;/titles&gt;&lt;br /&gt;          &lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;/book&gt;Listing &lt;br /&gt;10-3. Iterative Style Sheet&lt;br /&gt;&lt;xsl:stylesheet version="1.0" xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;&lt;xsl:output method="xml" version="1.0" encoding="UTF-8"&gt;&lt;xsl:template match="/"&gt;&lt;xsl:element name="table"&gt;&lt;xsl:for-each select="//book"&gt;&lt;xsl:element name="tr"&gt;&lt;xsl:for-each select="child::*"&gt;&lt;xsl:element name="td"&gt;&lt;xsl:value-of select="."&gt;&lt;/xsl:value-of&gt;&lt;/xsl:element&gt;&lt;/xsl:for-each&gt;&lt;/xsl:element&gt;&lt;br /&gt;&lt;/xsl:for-each&gt;&lt;/xsl:element&gt;&lt;/xsl:template&gt;&lt;br /&gt;lsting 10-4. Recursive Style Sheet&lt;br /&gt;&lt;xsl:stylesheet version="1.0" xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;&lt;xsl:output method="xml" version="1.0" encoding="UTF-8"&gt;&lt;xsl:template match="/"&gt;&lt;xsl:element name="table"&gt;&lt;xsl:apply-templates select="//book"&gt;&lt;/xsl:apply-templates&gt;&lt;/xsl:element&gt;&lt;xsl:template match="*"&gt;&lt;br /&gt;&lt;xsl:if test="count(ancestor::*) = 1"&gt;&lt;xsl:element name="tr"&gt;&lt;br /&gt;&lt;xsl:apply-templates select="child::*"&gt;&lt;/xsl:apply-templates&gt;&lt;br /&gt;&lt;/xsl:element&gt;&lt;xsl:if test="count(ancestor::*) != 1"&gt;&lt;xsl:element name="td"&gt;&lt;xsl:value-of select="."&gt;&lt;/xsl:value-of&gt;&lt;/xsl:element&gt;&lt;/xsl:if&gt;&lt;/xsl:if&gt;&lt;br /&gt;&lt;br /&gt;The decision to use an iterative design or a recursive design is more a matter of personal taste and comfort than any rule imposed from on high. For example, many developers new to XSLT start by writing iterative style sheets and move to recursive methods only when they become more confident in their abilities. But in the end, the result of the two style sheets is the same as shown in Listing 10-5.&lt;br /&gt;Listing 10-5. Result from Applying Either Style Sheet to the XML in Listing 10-2&lt;br /&gt;&lt;library&gt;&lt;book publisher="Del Rey"&gt;&lt;series&gt;&lt;title&gt;tation&lt;/title&gt;&lt;author&gt;Clifford D. Simak&lt;/author&gt;&lt;br /&gt;    &lt;/series&gt;&lt;book publisher="Del Rey"&gt;&lt;series&gt;The Lord of the Rings&lt;/series&gt;&lt;br /&gt;      &lt;title&gt;The Fellowship of the Ring&lt;/title&gt;&lt;author&gt;J.R.R. Tolkien&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Del Rey"&gt;&lt;series&gt;The Lord of the Rings&lt;/series&gt;&lt;br /&gt;      &lt;title&gt;The Two Towers&lt;/title&gt;&lt;author&gt;J.R.R. Tolkien&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Del Rey"&gt;&lt;series&gt;The Lord of the Rings&lt;/series&gt;&lt;br /&gt;      &lt;title&gt;The Return of the King&lt;/title&gt;&lt;author&gt;J.R.R. Tolkien&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Ace"&gt;&lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;      &lt;title&gt;Too Many Magicians&lt;/title&gt;&lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Ace"&gt;&lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;      &lt;title&gt;Murder and Magic&lt;/title&gt;&lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Ace"&gt;&lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;      &lt;title&gt;The Napoli Express&lt;/title&gt;&lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;book publisher="Ace"&gt;&lt;series&gt;Lord Darcy&lt;/series&gt;&lt;br /&gt;      &lt;title&gt;Lord Darcy Investigates&lt;/title&gt;&lt;author&gt;Randall Garrett&lt;/author&gt;&lt;br /&gt;    &lt;/book&gt;&lt;/book&gt;10.1.1. Scope&lt;br /&gt;If you're in a cubical right now, take a moment and look around; you're the absolute ruler of all that you survey. The desk and its contents all fall under your benevolent influence, as do the coffee cup and its contents. However, all that is beyond the imaginary line that separates your cubical from the corridor is beyond the scope of your influence and belongs to another. This simplistic description of office life is essentially the same as how the concept of scope works in XSLT. In XSLT, scope is applied to both the context node, the current position in the XML document, and the variables.&lt;br /&gt;It is best to think of scope along the same lines as local and global variables in other programming languages. For example, if a variable is defined within an if statement, it is accessible only inside that if statement. Or if a variable is defined within a function (template in XSLT), it can be used only within that function, not in any subsequent function, unless it is passed as a parameter. Variables defined on the root level are considered global to the entire XSLT document. Also, while we're on the subject of variables, I should describe the toughest issue that new developers have with learning XSLT.&lt;br /&gt;10.1.2. Nonvariable Variables&lt;br /&gt;As with other programming languages, XSLT provides the capability to create variables, which can be a major stumbling block to newcomers. You see, because of the functional nature of XSLT, variables aren't variable, and after they're created, they cannot be assigned a new value within the same scope. This might seem at first to be a problem, but it was intentional because XSLT is not a procedural language, like JavaScript. XSLT variables function more like variables in mathematical functions; you can create them, you can use them, but you can never change them.&lt;br /&gt;This, probably more than any other aspect of XSLT, has caused more developers to run screaming into the night, although I'm not sure, having never conducted any research into the subject. After all, how long can you develop without Jonesing for a fixer, make that needing a way to alter a variable or something along those lines?&lt;br /&gt;There is, however, a way around this issue; remember what I said about scope? That scope can be both local and global? Imagine, if you will, a recursive template. Yes, the headaches are starting already, but bear with me on this. There is absolutely no reason why a template cannot call itself. Okay, that's really useful information. A template can get around this issue, and it would be even more useful if I were to explain what a template is.&lt;br /&gt;In XSLT, a template is the equivalent to a function in another language, such as PHP or JavaScript. In fact, it isn't all that unusual for a template to have a name and be invoked using that name, just like a function. In addition, templates can accept parameters, just as functions do in other languages. However, there is a major difference between XSLT functions and, say, JavaScript functions.&lt;br /&gt;In JavaScript, functions are required to have names, whereas, in XSLT, templates aren't required to have names. This raises the question, if a template doesn't have a name, then how do you call it? The simple answer is that you don't call it; only named templates can be called. Instead, you apply it. The XSLT apply-templates element has an attribute named select, which uses XPath to specify which nodes in the source document the template is to be applied to.&lt;br /&gt;&lt;/library&gt;&lt;/xsl:template&gt;&lt;/xsl:template&gt;&lt;/xsl:output&gt;&lt;/xsl:stylesheet&gt;&lt;/xsl:output&gt;&lt;/xsl:stylesheet&gt;&lt;/library&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-6049841485579782894?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/6049841485579782894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/101-recursive-versus-iterative-style.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/6049841485579782894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/6049841485579782894'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/101-recursive-versus-iterative-style.html' title='10.1. Recursive Versus Iterative Style Sheets'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-753107742055382275</id><published>2008-12-13T11:30:00.001-08:00</published><updated>2009-01-26T12:33:17.865-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>10.2. XPath in the Style Sheet&lt;br /&gt;Even though the XSLT elements in the three style sheets shown earlier are unfamiliar, they illustrate that XPath is an indispensable part of the style sheet. The recursive style sheet particularly shows this dependence upon XPath because of the heavy use of template and apply-templates elements for pattern matching, and the if elements for flow control. But because you read the previous chapter on XPath, all this XPath stuff is already old hat. You did read it, didn't you? Skipping ahead to the good parts, eh? For shame, no soup for you!&lt;br /&gt;&lt;br /&gt;Before continuing, I'd like to take a moment to explain something to one of my former co-workers who might be reading this (Yeah, right! Like that would ever happenthe last technical book he read was Curious George Builds a Web Page) before continuing. First, there is no difference in XPath, regardless of where it is being used. The XPath in Europe is the same as the XPath in Asia, which is the same as the XPath in North America, and if something on the Mars Rovers use XPath, then that is also the same. It is called a standard, which means that it is standard throughout the solar system. Sorry to those of you who understand the concept of standards; I just needed to exercise (exorcise) that particular demon for personal reasons. Besides, it was getting a little pudgy, and who wants a pudgy demon anyway?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-753107742055382275?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/753107742055382275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/10_9629.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/753107742055382275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/753107742055382275'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/10_9629.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-6897258132269043646</id><published>2008-12-13T11:28:00.000-08:00</published><updated>2009-01-26T12:33:17.865-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>10.3. Elements&lt;br /&gt;Regardless of whether you consider XSLT to be a markup language, a scripting language, or just a pain in the fanny, it is, first and foremost, a dialect of XML and, therefore, must adhere to all of XML's rules. And I mean all of XML's rules because if it isn't well formed, then end of game. Fortunately, we've been there and done that already, which gives us the opportunity to look at the various XSLT elements available to us. Table 10-1 provides a high-level overview of these elementsnot quite an orbital overview, but close. Don't worry; we cover some of these elements in much greater detail shortly.&lt;br /&gt;&lt;br /&gt;Table 10-1. XSLT Elements Element&lt;br /&gt; Attributes&lt;br /&gt; Description&lt;br /&gt; &lt;br /&gt;apply-imports&lt;br /&gt;   Applies external templates that have been imported using the import element.&lt;br /&gt; &lt;br /&gt;apply-templates&lt;br /&gt; select optional &lt;br /&gt;mode optional&lt;br /&gt; Applies templates that were defined locally.&lt;br /&gt; &lt;br /&gt;attribute&lt;br /&gt; name &lt;br /&gt;namespace optional&lt;br /&gt; Specifies an attribute for the preceding element.&lt;br /&gt; &lt;br /&gt;attribute-set&lt;br /&gt; name &lt;br /&gt;use-attribute-sets &lt;br /&gt;optional&lt;br /&gt; Defines a named set of attributes that can be used to specify a list of attributes en mass instead of individually.&lt;br /&gt; &lt;br /&gt;call-template&lt;br /&gt; name&lt;br /&gt; Used to invoke a named template.&lt;br /&gt; &lt;br /&gt;choose&lt;br /&gt;   Indicates the beginning of a case structure.&lt;br /&gt; &lt;br /&gt;comment&lt;br /&gt;   Used to create comments in the output document.&lt;br /&gt; &lt;br /&gt;copy&lt;br /&gt; use-attribute-sets &lt;br /&gt;optional&lt;br /&gt; Copies the current node and namespaces to the output document. However, it does not copy the children of the current node.&lt;br /&gt; &lt;br /&gt;copy-of&lt;br /&gt; select&lt;br /&gt; Copies the node or nodes specified by the select attribute to the output document.&lt;br /&gt; &lt;br /&gt;decimal-format&lt;br /&gt; decimal-separator &lt;br /&gt;optional &lt;br /&gt;digit optional &lt;br /&gt;grouping-separator &lt;br /&gt;optional &lt;br /&gt;infinity optional &lt;br /&gt;minus-sign optional &lt;br /&gt;name optional &lt;br /&gt;NaN optional &lt;br /&gt;pattern-separator &lt;br /&gt;optional &lt;br /&gt;per-mille optional &lt;br /&gt;percent optional &lt;br /&gt;zero-digit optional&lt;br /&gt; Defines the appearance of numbers formatted using the format-number() function.&lt;br /&gt; &lt;br /&gt;element&lt;br /&gt; name &lt;br /&gt;namespace &lt;br /&gt;use-attribute-sets &lt;br /&gt;optional&lt;br /&gt; Used to create an element in the output document.&lt;br /&gt; &lt;br /&gt;fallback&lt;br /&gt;   Specifies to the XSL processor alternative code to run in case an XSL element is not supported.&lt;br /&gt; &lt;br /&gt;for-each&lt;br /&gt; select&lt;br /&gt; Loops through the node set specified by the select attribute.&lt;br /&gt; &lt;br /&gt;if&lt;br /&gt; test&lt;br /&gt; Executes the enclosed XSL when the result of the test is TRue. It is important to remember that no else clause exists for the if element. In these instances, the choose, when, and otherwise elements should be used.&lt;br /&gt; &lt;br /&gt;import&lt;br /&gt; href&lt;br /&gt; Imports an external style sheet, which is the same as including a style sheet.&lt;br /&gt; &lt;br /&gt;include&lt;br /&gt; href&lt;br /&gt; Includes an external style sheet, which is the same as importing a style sheet.&lt;br /&gt; &lt;br /&gt;key&lt;br /&gt; name &lt;br /&gt;match &lt;br /&gt;use&lt;br /&gt; Defines a search key that is used to locate specific nodes based upon their value or the value of another node.&lt;br /&gt; &lt;br /&gt;message&lt;br /&gt; terminate optional&lt;br /&gt; Writes a programmer-defined message to the output document.&lt;br /&gt; &lt;br /&gt;namespace-alias&lt;br /&gt; stylesheet-prefix &lt;br /&gt;result-prefix&lt;br /&gt; Replaces the namespace specified with the stylesheet-prefix attribute on the input stylesheet with the namespace specified with the result-prefix attribute on the output document.&lt;br /&gt; &lt;br /&gt;number&lt;br /&gt; level optional &lt;br /&gt;count optional &lt;br /&gt;from optional &lt;br /&gt;value optional &lt;br /&gt;format optional &lt;br /&gt;lang optional &lt;br /&gt;letter-value optional &lt;br /&gt;group-separator optional &lt;br /&gt;grouping-size optional&lt;br /&gt; Used to write a formatted number to the output document.&lt;br /&gt; &lt;br /&gt;otherwise&lt;br /&gt;   Defines the default action for a case structure (choose).&lt;br /&gt; &lt;br /&gt;output&lt;br /&gt; method optional &lt;br /&gt;version optional &lt;br /&gt;encoding optional &lt;br /&gt;omit-xml-declaration &lt;br /&gt;optional &lt;br /&gt;standalone optional &lt;br /&gt;doctype-public optional &lt;br /&gt;doctype-system optional &lt;br /&gt;cdata-section-elements &lt;br /&gt;optional &lt;br /&gt;indent optional &lt;br /&gt;media-type optional&lt;br /&gt; Defines the format of the output document.&lt;br /&gt; &lt;br /&gt;param&lt;br /&gt; name &lt;br /&gt;select optional&lt;br /&gt; Used to specify template, stylesheet, and transform input parameters.&lt;br /&gt; &lt;br /&gt;preserve-space&lt;br /&gt; elements&lt;br /&gt; Defines the elements for which whitespace is to be preserved on the output document.&lt;br /&gt; &lt;br /&gt;processing-instruction&lt;br /&gt; name&lt;br /&gt; Writes an XML processing instruction to the output document.&lt;br /&gt; &lt;br /&gt;sort&lt;br /&gt; select optional &lt;br /&gt;lang optional &lt;br /&gt;data-type optional &lt;br /&gt;order optional &lt;br /&gt;case-order optional&lt;br /&gt; Sorts a node set.&lt;br /&gt; &lt;br /&gt;strip-space&lt;br /&gt; elements&lt;br /&gt; Defines the elements for which whitespace is not to be preserved on the output document.&lt;br /&gt; &lt;br /&gt;stylesheet&lt;br /&gt; id optional &lt;br /&gt;extension-element-prefixes optional &lt;br /&gt;exclude-result-prefixes optional &lt;br /&gt;version&lt;br /&gt; Defines the XSL document as a style sheet to the XSLT processor.&lt;br /&gt; &lt;br /&gt;template&lt;br /&gt; match optional &lt;br /&gt;name optional &lt;br /&gt;priority optional &lt;br /&gt;mode optional&lt;br /&gt; Defines a template, which is essentially an XSL function.&lt;br /&gt; &lt;br /&gt;text&lt;br /&gt; disable-output-escaping optional&lt;br /&gt; Indicates that the enclosed is text.&lt;br /&gt; &lt;br /&gt;transform&lt;br /&gt; id optional &lt;br /&gt;extension-element-prefixes optional &lt;br /&gt;exclude-result-prefixes optional &lt;br /&gt;version&lt;br /&gt; Defines the XSL document as a style sheet to the XSLT processor, identical to the stylesheet element.&lt;br /&gt; &lt;br /&gt;value-of&lt;br /&gt; select &lt;br /&gt;disable-output-escaping optional&lt;br /&gt; Writes the information specified by the select attribute to the output document.&lt;br /&gt; &lt;br /&gt;variable&lt;br /&gt; name select optional&lt;br /&gt; Defines either a local or global variable to the XSLT processor.&lt;br /&gt; &lt;br /&gt;when&lt;br /&gt; test&lt;br /&gt; Defines the individual cases of a case structure (choose).&lt;br /&gt; &lt;br /&gt;with-param&lt;br /&gt; name select optional&lt;br /&gt; Defines the parameters to a template.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;10.3.1. In the Beginning&lt;br /&gt;In the beginning, all your data was painted on the wall of a cave somewhere, and it was good. Depending on the available light, it was human readable, self-describing, colorful, and even pretty. Unfortunately, civilization has advanced to the point that cave paintings just can't express the sheer volume of information available to us today. Enter XML, which, like its distant ancestor, is also human readable, self-describing, and, if you're using an XML editor such as Stylus Studio, both colorful and pretty.&lt;br /&gt;&lt;br /&gt;Although it might seem to some people that we've come full circle in our data storage, from cave paintings to XML, there is a distinct advantage to XML. Unlike a cave painting, which pretty much just sits there on the wall looking about the same as it did 40,000 years ago, XML is a bit more portable. With the addition of XSLT, XML is also elastic and flexible. I'm sold on the concept, how about you? Good. The only issue remaining is how to start developing an XSL style sheet.&lt;br /&gt;&lt;br /&gt;All XSL style sheets begin with one of two elements, either the stylesheet element or the TRansform element. They are interchangeable because both do exactly the same thing, although I recommend not using the transform element during months with r's. Wait, maybe that was oystersI have a tendency to confuse the two.&lt;br /&gt;&lt;br /&gt;The next part of the style sheet is the output element, which essentially describes the format of the output. This is where you make the commitment of whether the output document will be XML, HTML, text, or, gasp, even XSLT. Not big on commitment? Not a problem. Just leave out the output element, and the output defaults to XML. Of course, come to think of it, that, too, is a form of commitment.&lt;br /&gt;&lt;br /&gt;The next "standard" part of an XSL style sheet is the first template, the one that starts the whole ball rolling. However, before we get there, I should point out that between the first element and the first template is where some really useful elements go. Parameters from the outside world and global variables are just two examples. In fact, let's take a look at Table 10-2, which indicates where elements can be defined in a style sheet and what effect location can have on their behavior.&lt;br /&gt;&lt;br /&gt;Table 10-2. XSL Style Sheet Elements and Where They Can Be Defined Element&lt;br /&gt; Defined Where&lt;br /&gt; &lt;br /&gt;apply-imports&lt;br /&gt; Either root or element level&lt;br /&gt; &lt;br /&gt;apply-templates&lt;br /&gt; Either root or element level&lt;br /&gt; &lt;br /&gt;attribute&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;attribute-set&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;call-template&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;choose&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;comment&lt;br /&gt; Either root or element level&lt;br /&gt; &lt;br /&gt;copy&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;copy-of&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;decimal-format&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;element&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;fallback&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;if&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;import&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;include&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;key&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;message&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;namespace-alias&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;number&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;otherwise&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;output&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;preserve-space&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;processing-instruction&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;sort&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;strip-space&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;stylesheet&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;template&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;text&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;TRansform&lt;br /&gt; Root level&lt;br /&gt; &lt;br /&gt;value-of&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;variable&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;when&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;with-param&lt;br /&gt; Element level&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;At last we've come to the first template of the style sheet. Unfortunately, it is kind of anticlimatic because 99 percent of all style sheets start with a template element that looks just like this:&lt;br /&gt;&lt;br /&gt;&lt;xsl:template match="/"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Boring, isn't it? Yes, you can make it more specific and have it look for a particular element that should be in the input document. I don't recommend it, though, because it will only cause problems someday when, for some reason, that specific element is not in the input document. Then comes the inevitable yelling, the finger pointing, and the peasants with pitchforks and torches again. Not a pretty picture.&lt;br /&gt;&lt;br /&gt;10.3.2. Templates and How to Use Them&lt;br /&gt;After the initial template, the one that establishes the current location as the root, what are some of the other ways to use templates?&lt;br /&gt;&lt;br /&gt;Earlier I stated that templates could have names, although it wasn't required. In XSLT, these named templates fill pretty much the same niche that functions do in a language such as JavaScript or PHP. They can accept parameters and return results. In my opinion, if it looks like a duck and walks like a duck, the odds are, it is a duck. Unless it is a goose, but that is kind of like duckzilla, so it isn't a problem.&lt;br /&gt;&lt;br /&gt;Let's take a look at what a typical, although useless, named function looks like. Shown in Listing 10-6, its purpose is to accept two numbers, add them, and return the result.&lt;br /&gt;&lt;br /&gt;Listing 10-6. Named Template&lt;br /&gt;&lt;xsl:template name="add"&gt;&lt;br /&gt;      &lt;xsl:param name="a" /&gt;&lt;br /&gt;      &lt;xsl:param name="b" /&gt;&lt;br /&gt;&lt;br /&gt;      &lt;xsl:value-of select="number($a) + number($b)" /&gt;&lt;br /&gt;&lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Thankfully, this is one of those times when something both seems simple and actually is simple, as long as you remember that dollar signs aren't required at definition but are required when used. However, the same thing can't always be said for templates invoked using XPathbut before we go there, perhaps it would be better to take a look at two more mundane templates. Using the XML shown way back in Listing 10-4, the style sheets shown in Listings 10-7 and 10-8 do exactly the same thing in a slightly different manner.&lt;br /&gt;&lt;br /&gt;Listing 10-7. A Pure XSLT Example&lt;br /&gt;&lt;?xml version="1.0"?&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0"&lt;br /&gt;xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;      &lt;xsl:preserve-space elements="text"/&gt;&lt;br /&gt;&lt;br /&gt;      &lt;xsl:template match="/"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;xsl:element name="div"&gt;&lt;br /&gt;          &lt;xsl:apply-templates select="//library"/&gt;&lt;br /&gt;        &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;      &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;      &lt;xsl:template match="library"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;xsl:element name="table"&gt;&lt;br /&gt;          &lt;xsl:attribute name="width"&gt;100%&lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;          &lt;xsl:for-each select="book"&gt;&lt;br /&gt;            &lt;xsl:element name="tr"&gt;&lt;br /&gt;&lt;br /&gt;              &lt;xsl:for-each select="*"&gt;&lt;br /&gt;              &lt;xsl:element name="td"&gt;&lt;br /&gt;                &lt;xsl:attribute name="width"&gt;33%&lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;                &lt;xsl:value-of select="."/&gt;&lt;br /&gt;&lt;br /&gt;             &lt;xsl:if test="string-length(.) = 0"&gt;&lt;br /&gt;                  &lt;xsl:text&gt; &lt;/xsl:text&gt;&lt;br /&gt;                &lt;/xsl:if&gt;&lt;br /&gt;              &lt;/xsl:element&gt;&lt;br /&gt;            &lt;/xsl:for-each&gt;&lt;br /&gt;       &lt;/xsl:element&gt;&lt;br /&gt;        &lt;/xsl:for-each&gt;&lt;br /&gt;       &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;     &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Listing 10-8. An XSLT/XHTML Hybrid Example&lt;br /&gt;&lt;?xml version="1.0"?&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0"&lt;br /&gt;xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;      &lt;xsl:preserve-space elements="text"/&gt;&lt;br /&gt;&lt;br /&gt;      &lt;xsl:template match="/"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;xsl:element name="div"&gt;&lt;br /&gt;          &lt;xsl:apply-templates select="//library"/&gt;&lt;br /&gt;        &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;      &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;      &lt;xsl:template match="library"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;xsl:element name="table"&gt;&lt;br /&gt;          &lt;xsl:attribute name="width"&gt;100%&lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;          &lt;xsl:for-each select="book"&gt;&lt;br /&gt;            &lt;tr&gt;&lt;br /&gt;              &lt;xsl:for-each select="*"&gt;&lt;br /&gt;                &lt;td width="33%"&gt;&lt;br /&gt;                  &lt;xsl:value-of select="."/&gt;&lt;br /&gt;&lt;br /&gt;                  &lt;xsl:if test="string-length(.) = 0"&gt;&lt;br /&gt;                    &lt;xsl:text&gt; &lt;/xsl:text&gt;&lt;br /&gt;                  &lt;/xsl:if&gt;&lt;br /&gt;                &lt;/td&gt;&lt;br /&gt;              &lt;/xsl:for-each&gt;&lt;br /&gt;           &lt;/tr&gt;&lt;br /&gt;         &lt;/xsl:for-each&gt;&lt;br /&gt;         &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;       &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Confused? Don't be. Because XSLT and XHTML are both dialects of XML, there is absolutely nothing wrong with mixing the two. At first glance, the style sheet shown in Listing 10-8 might seem to be a little like a mutt, part this and part that. But as weird as it seems, it is much more common than the purebred solution from Listing 10-7.&lt;br /&gt;&lt;br /&gt;Earlier I stated that templates invoked using XPath aren't always simple because, at times, more than one template matches. If you don't expect this, it could, at the very least, be an embarrassment. However, there is a way to specify which template to use when more than one matches the criteria.&lt;br /&gt;&lt;br /&gt;The mode attribute, which is on both the template and apply-templates elements, is used to specify which template to use when a particular select could result in more than one match. Listing 10-9, a merging of Listings 10-7 and 10-8, has an example of this. The only difference, other than the merging, is the addition of a mode attribute for the mutt template and a new applytemplates element, also with a mode attribute.&lt;br /&gt;&lt;br /&gt;Listing 10-9. Distinguishing Template Matches Using Mode&lt;br /&gt;&lt;?xml version="1.0"?&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0"&lt;br /&gt;xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;  &lt;xsl:preserve-space elements="text"/&gt;&lt;br /&gt;&lt;br /&gt;  &lt;xsl:template match="/"&gt;&lt;br /&gt;&lt;br /&gt;    &lt;xsl:element name="div"&gt;&lt;br /&gt;      &lt;xsl:apply-templates select="//library" /&gt;&lt;br /&gt;      &lt;xsl:apply-templates select="//library" mode="mutt" /&gt;&lt;br /&gt;    &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;     &lt;xsl:template match="library"&gt;&lt;br /&gt;&lt;br /&gt;       &lt;xsl:element name="table"&gt;&lt;br /&gt;         &lt;xsl:attribute name="width"&gt;100%&lt;/xsl:attribute&gt;&lt;br /&gt;         &lt;xsl:for-each select="book"&gt;&lt;br /&gt;           &lt;xsl:element name="tr"&gt;&lt;br /&gt;&lt;br /&gt;              &lt;xsl:for-each select="*"&gt;&lt;br /&gt;                &lt;xsl:element name="td"&gt;&lt;br /&gt;                  &lt;xsl:attribute name="width"&gt;33%&lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;                  &lt;xsl:value-of select="." /&gt;&lt;br /&gt;&lt;br /&gt;              &lt;xsl:if test="string-length(.) = 0"&gt;&lt;br /&gt;                   &lt;xsl:text&gt; &lt;/xsl:text&gt;&lt;br /&gt;                 &lt;/xsl:if&gt;&lt;br /&gt;               &lt;/xsl:element&gt;&lt;br /&gt;             &lt;/xsl:for-each&gt;&lt;br /&gt;           &lt;/xsl:element&gt;&lt;br /&gt;         &lt;/xsl:for-each&gt;&lt;br /&gt;      &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;    &lt;xsl:template match="library" mode="mutt"&gt;&lt;br /&gt;&lt;br /&gt;      &lt;xsl:element name="table"&gt;&lt;br /&gt;        &lt;xsl:attribute name="width"&gt;100%&lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;        &lt;xsl:for-each select="book"&gt;&lt;br /&gt;          &lt;tr&gt;&lt;br /&gt;            &lt;xsl:for-each select="*"&gt;&lt;br /&gt;              &lt;td width="33%"&gt;&lt;br /&gt;                &lt;xsl:value-of select="." /&gt;&lt;br /&gt;&lt;br /&gt;                &lt;xsl:if test="string-length(.) = 0"&gt;&lt;br /&gt;                     &lt;xsl:text&gt; &lt;/xsl:text&gt;&lt;br /&gt;                   &lt;/xsl:if&gt;&lt;br /&gt;                 &lt;/td&gt;&lt;br /&gt;               &lt;/xsl:for-each&gt;&lt;br /&gt;          &lt;/tr&gt;&lt;br /&gt;        &lt;/xsl:for-each&gt;&lt;br /&gt;      &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The mode attribute provides additional criteria for the match. Instead of the XPath being the only criteria, the mode is also used. So a simple XPath match alone is not enough; there also has to be a match to the mode. This leads to some interesting possibilities, such as when the mode name is unknown. Just use an asterisk as the mode name and use the mode to indicate the depth, or something along those lines.&lt;br /&gt;&lt;br /&gt;10.3.3. Decisions, Decisions&lt;br /&gt;As in the majority of programming languages, XSLT provides flow control in the way of decision structures. Excluding apply-templates, which can be used for some similar functionality, there is the if element and a case structure, called choose. Basically, it is all easy stuff, but two issues with XSLT decisions can cause many developers problems.&lt;br /&gt;&lt;br /&gt;The first of these issues is how to test for greater than and less than, and still keep the document well formed. Fortunately, the previous chapter covered this problem when discussing XPath. The only remaining issue is one that causes quite a number of headaches: a lack of an else for the if element.&lt;br /&gt;&lt;br /&gt;Lack of an else might seem like, if not an insurmountable problem, at least an annoying problem. Because of this lack, the choose element is used more often in languages with an else. Listing 10-10 is an example of a workaround for this lack of an else statement.&lt;br /&gt;&lt;br /&gt;Listing 10-10. A Workaround&lt;br /&gt;&lt;?xml version='1.0'?&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0"&lt;br /&gt;xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;&lt;br /&gt;  &lt;xsl:template match="/"&gt;&lt;br /&gt;    &lt;xsl:variable name="value" select="7" /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;xsl:element name="div"&gt;&lt;br /&gt;      &lt;xsl:choose&gt;&lt;br /&gt;        &lt;xsl:when test="($value mod 2) = 0"&gt;Even&lt;/xsl:when&gt;&lt;br /&gt;        &lt;xsl:otherwise&gt;Not even&lt;/xsl:otherwise&gt;&lt;br /&gt;      &lt;/xsl:choose&gt;&lt;br /&gt;    &lt;/xsl:element&gt;&lt;br /&gt;  &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;10.3.4. Sorting Out Looping&lt;br /&gt;XSL style sheets have a built-in mechanism for sorting node sets, which can be rather useful when information needs to be arranged in a specific sequence. As with everything in XSL, sorting is accomplished through the use of an element, which, appropriately, is called sort. Interesting how these things work out, isn't it?&lt;br /&gt;&lt;br /&gt;Listings 10-11 and 10-12 both show examples of the use of the sort element, with a couple minor differences. For example, Listing 10-11 uses a for-each element to navigate through the node set, which is sorted into ascending sequence. In Listing 10-12, an apply-templates is used, and the node set is sorted into descending sequence.&lt;br /&gt;&lt;br /&gt;Listing 10-11. A for-each Sort Example&lt;br /&gt;&lt;?xml version='1.0'?&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0"&lt;br /&gt;xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;&lt;br /&gt;  &lt;xsl:template match="/"&gt;&lt;br /&gt;    &lt;xsl:element name="table"&gt;&lt;br /&gt;      &lt;xsl:attribute name="width"&gt;100%&lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;      &lt;xsl:for-each select="//book"&gt;&lt;br /&gt;           &lt;xsl:sort select="title" order="ascending" /&gt;&lt;br /&gt;&lt;br /&gt;           &lt;xsl:element name="tr"&gt;&lt;br /&gt;             &lt;xsl:for-each select="*"&gt;&lt;br /&gt;               &lt;xsl:element name="td"&gt;&lt;br /&gt;                 &lt;xsl:value-of select="." /&gt;&lt;br /&gt;               &lt;/xsl:element&gt;&lt;br /&gt;             &lt;/xsl:for-each&gt;&lt;br /&gt;           &lt;/xsl:element&gt;&lt;br /&gt;         &lt;/xsl:for-each&gt;&lt;br /&gt;    &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Listing 10-12. A template sort Example&lt;br /&gt;&lt;?xml version='1.0'?&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0"&lt;br /&gt;xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;&lt;br /&gt;  &lt;xsl:template match="/"&gt;&lt;br /&gt;    &lt;xsl:element name="table"&gt;&lt;br /&gt;      &lt;xsl:attribute name="width"&gt;100%&lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;      &lt;xsl:apply-templates select="//book"&gt;&lt;br /&gt;       &lt;xsl:sort select="title" order="descending" /&gt;&lt;br /&gt;        &lt;/xsl:apply-templates&gt;&lt;br /&gt;      &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;  &lt;xsl:template match="*"&gt;&lt;br /&gt;&lt;br /&gt;    &lt;xsl:element name="tr"&gt;&lt;br /&gt;      &lt;xsl:for-each select="*"&gt;&lt;br /&gt;        &lt;xsl:element name="td"&gt;&lt;br /&gt;        &lt;xsl:value-of select="." /&gt;&lt;br /&gt;      &lt;/xsl:element&gt;&lt;br /&gt;       &lt;/xsl:for-each&gt;&lt;br /&gt;     &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;  &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;10.4. XSLT Functions&lt;br /&gt;Unlike XPath, which has a plethora of functions, the number of XSL functions is significantly lower. Mostly, the reason for this is that the XPath functions are fully available to supplement the few functions shown in Table 10-3.&lt;br /&gt;&lt;br /&gt;Table 10-3. XSL Functions Function&lt;br /&gt; Description&lt;br /&gt; &lt;br /&gt;Current() Returns only the current node in a node set&lt;br /&gt; &lt;br /&gt;document() Used to access an XML document other than the source document&lt;br /&gt; &lt;br /&gt;element-available() Returns a TRue condition if the passed string is a supported XSL element&lt;br /&gt; &lt;br /&gt;Format-number() Returns a formatted numeric string using a number and a pattern as input&lt;br /&gt; &lt;br /&gt;function-available() Returns a true condition if the passed string is a supported XSL or XPath function&lt;br /&gt; &lt;br /&gt;generate-id(node) Returns an ID that is unique to the node passed, regardless of how the node was obtained&lt;br /&gt; &lt;br /&gt;key() Returns a node set that was previously indexed using the key element&lt;br /&gt; &lt;br /&gt;System-property() Returns a value for a specific system property&lt;br /&gt; &lt;br /&gt;unparsed-entity-uri() Returns the URI of an unparsed entity&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-6897258132269043646?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/6897258132269043646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/10_13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/6897258132269043646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/6897258132269043646'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/10_13.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5149233489190075869</id><published>2008-12-13T11:25:00.000-08:00</published><updated>2009-01-26T12:33:17.865-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>10.5. XSLT Concepts&lt;br /&gt;When developing an XSL style sheet, I usually find myself using only two of the XSL functions shown earlier: the key() function and the generate-id() function, both of which are indispensable when doing something unique to XSL style sheets. I am referring to something called Muenchian grouping.&lt;br /&gt;&lt;br /&gt;Muenchian grouping, invented by Steve Muench, the XML Evangelist of the Oracle Corporation, is a method of grouping nodes based upon their values. Although I can describe how it works, it is probably a better idea to take a look at the example of Muenchian grouping shown in Listing 10-13. After that, we take it apart to see how it works.&lt;br /&gt;&lt;br /&gt;Listing 10-13. A Muenchian Grouping Example&lt;br /&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0"&lt;br /&gt;xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;  &lt;xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes" /&gt;&lt;br /&gt;  &lt;xsl:key name="keyBook" match="book" use="series" /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;xsl:template match="/"&gt;&lt;br /&gt;&lt;br /&gt;    &lt;xsl:element name="table"&gt;&lt;br /&gt;       &lt;xsl:attribute name="width"&gt;100%&lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;       &lt;xsl:apply-templates select="//book[1]" mode="header" /&gt;&lt;br /&gt;    &lt;xsl:apply-templates select="//book[generate-id(.) = generate-&lt;br /&gt;id(key('keyBook',series)[1])]" /&gt;&lt;br /&gt;       &lt;xsl:apply-templates select="//book[string-length(series) =&lt;br /&gt;0]/series" /&gt;&lt;br /&gt;  &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;   &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;xsl:template match="book"&gt;&lt;br /&gt;&lt;br /&gt;     &lt;xsl:variable name="key"&gt;&lt;br /&gt;       &lt;xsl:value-of select="series" /&gt;&lt;br /&gt;     &lt;/xsl:variable&gt;&lt;br /&gt;&lt;br /&gt;     &lt;xsl:apply-templates select="//series[node() = $key]" /&gt;&lt;br /&gt;&lt;br /&gt;   &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;   &lt;xsl:template match="series"&gt;&lt;br /&gt;&lt;br /&gt;   &lt;xsl:element name="tr"&gt;&lt;br /&gt;     &lt;xsl:apply-templates select="parent::node()/*" mode="cell" /&gt;&lt;br /&gt;   &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;&lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;xsl:template match="*" mode="cell"&gt;&lt;br /&gt;&lt;br /&gt;  &lt;xsl:element name="td"&gt;&lt;br /&gt;      &lt;xsl:attribute name="align"&gt;left&lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;    &lt;xsl:value-of select="." /&gt;&lt;br /&gt;  &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;   &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;   &lt;xsl:template match="book" mode="header"&gt;&lt;br /&gt;&lt;br /&gt;  &lt;xsl:element name="tr"&gt;&lt;br /&gt;   &lt;xsl:apply-templates select="./*" mode="columnHeader" /&gt;&lt;br /&gt;  &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;   &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;   &lt;xsl:template match="*" mode="columnHeader"&gt;&lt;br /&gt;&lt;br /&gt;     &lt;xsl:variable&lt;br /&gt;name="lowerCase"&gt;qwertyuiopasdfghjklzxcvbnm&lt;/xsl:variable&gt;&lt;br /&gt;     &lt;xsl:variable&lt;br /&gt;name="upperCase"&gt;QWERTYUIOPASDFGHJKLZXCVBNM&lt;/xsl:variable&gt;&lt;br /&gt;&lt;br /&gt;     &lt;xsl:element name="th"&gt;&lt;br /&gt;       &lt;xsl:attribute name="width"&gt;33%&lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;       &lt;xsl:value-of select="translate(name(.),$lowerCase,$upperCase)" /&gt;&lt;br /&gt;     &lt;/xsl:element&gt;&lt;br /&gt;&lt;br /&gt;   &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The element that starts the whole ball rolling is the key element, which creates a cross-reference based upon the node specified by the use attribute. Using the series element as the key results in an index consisting of The Lord of the Rings and Lord Darcy, with the book The Way Station left out because its series element is null. This cross-reference is accessed using the key function, which accepts two parameters: the name from the key element and the node.&lt;br /&gt;&lt;br /&gt;Another function that plays an integral part in Muenchian grouping is the generate-id function. This function, well, generates a unique ID for every node in an XML document every time that the document is processed. So the XPath statement //book[generate-id(.) = generate-id(key('keyBook',series)[1])] locates the first element with each unique key from the cross-reference and applies the matching template. The matching template then uses the unique series to select the matching elements.&lt;br /&gt;&lt;br /&gt;It is all pretty basic XSLT and XPath stuff, although it does have a tendency to make grown men whimper like little scared puppies. If it doesn't, here is one that will put someone over the edge: Imagine trying to group based upon multiple criteria, such as author and series. Although it isn't done very often, and you'll probably never have to do it, I'll give you a hint: Concatenate the elements using the concat function.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5149233489190075869?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5149233489190075869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/10.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5149233489190075869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5149233489190075869'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/10.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1256749879512151332</id><published>2008-12-13T11:21:00.000-08:00</published><updated>2008-12-13T11:24:21.482-08:00</updated><title type='text'>Chapter 11. Ajax Using XSLT</title><content type='html'>"But wait, there's more ...."&lt;br /&gt;&lt;br /&gt;I do so feel like someone hawking my wares on a late-night infomercial, but hey, it's true. There is actually more to Ajax than what we've already covered. In fact, we're about to get to one of my favorite parts. I've jokingly referred to the material covered up to this point as "mad scientist stuff," but the material that we're about to cover transcends everything that we've covered up till now. It is called eXtensible Stylesheet Language for Transformations, or XSLT, and I like to think of it as magic. Think of XSLT as the part of a spell that says what to do. The second part of the spell is XPath, which acts as the targeting device for the spell. Tightly intertwined, XSLT and XPath work together to modify or, if you prefer, transform XML.&lt;br /&gt;&lt;br /&gt;11.1. XSLT&lt;br /&gt;Transformations are an idea as old as human thought. Primitive societies had werewolves, werebears, and weretigers. The Greeks had warnings against seeing goddesses bathe, unless one was interested in going to parties stag, literally. During the renaissance, there was Shakespeare's A Midsummer's Night Dream, in which Bottom was made an Ass of. Today we have Jack Chalker's Midnight at the Well of Souls and the Borg from Star Trek. And although the transformations in each of these stories dealt with the physical world and XSLT can affect only XML, they all share many of the same characteristics: Without change, the story can progress no further.&lt;br /&gt;&lt;br /&gt;As one who has been working in the programming field for a number of years, I can attest to one thing: About 40 percent of the time, the data is in the wrong format. In ancient times, when great beasts with names such as System major problem. Programs had to be changed or written from scratch to massage the data to make it usable. Changing programs and creating programs has always been a costly undertaking in any day and age.&lt;br /&gt;&lt;br /&gt;Now things are different, as time seems to be speeding up. The great beasts are all either dead or behind glass in museums, where people can stare in awe, never realizing that the old 486 machine that they gave to their kids had more power.&lt;br /&gt;&lt;br /&gt;Today much of the information that we deal with is in the form of XML, which, interestingly enough, can be transformed by XSLT in much the same manner as Lon Chaney was by the full moon. Thankfully, however, the XML doesn't get hairyunless, of course, we want it to.&lt;br /&gt;&lt;br /&gt;11.1.1. XML Magic&lt;br /&gt;Here's the quandary: On the client side, we have XML and we want HTML. It's a real pain in the gluteus, isn't it?&lt;br /&gt;&lt;br /&gt;Yes, we can write a script to perform the conversion, but it is a time-consuming task accomplished with ill-suited tools. Face it: The majority of scripting languages aren't really built to handle XML. Although it works just fine, when messing around with individual nodes, JavaScript's XML support comes across like a Bose sound system in a Ford Pinto. I'm not saying that it doesn't workit works just fine, but, unfortunately, six months later it has a tendency to cause questions like, "I wrote this?"&lt;br /&gt;&lt;br /&gt;XSLT, as opposed to JavaScript, was designed from the ground up to handle XML. Come to think of it, XSLT is itself a dialect of XML. This has a tendency to lead to some really interesting style sheets when working with XSLT, but that is a topic for another day. Another interesting thing is that although the input has to be XML, nothing says that the output needs to be XML. This means that if you want to transform XML into HTML as opposed to XHTML, by all means do it, but just remember that if you're using SOAP, the package must be well formed.&lt;br /&gt;&lt;br /&gt;11.1.2. How Microsoft Shot Itself in the Foot&lt;br /&gt;Back in the old days, during the first browser wars, Microsoft released Internet Explorer version 5.0, the first web browser with XSLT support. It would have been a major victory for Microsoft, if it had not been for one little detail. In their haste, they forgot one little thing about the World Wide Web Consortium's recommendations. You see, recommendations are often vastly different from drafts. In an effort to produce the first browser with XSLT support, Microsoft used a draft as a guide.&lt;br /&gt;&lt;br /&gt;For this reason, you sometimes see references to the namespace http://www.w3.org/TR/WD-xsl instead of http://www.w3.org/1999/XSL/Transform.&lt;br /&gt;&lt;br /&gt;It was only with the advent of Microsoft Internet Explorer 6 that Internet Explorer started following the recommendation instead of the draft. Personally, I believe that it is a good idea to ignore the old namespace entirely; I think that Microsoft would like to. And although they're currently considered the third most popular browser, at most, individuals using versions 5.0, 5.01, and 5.5 of Internet Explorer comprise only a fraction of the general population. It is a pretty safe bet that you can ignore these web browsers entirely without alienating anyone but technophobes, the White House, and project leaders who use the term blink.&lt;br /&gt;&lt;br /&gt;11.1.3. XPath, or I Left It Around Here Someplace&lt;br /&gt;Earlier I stated that XPath was the targeting device for XSLT, which is essentially true. XPath is used to describe the XML node or nodes that we're looking for. As the name suggests, XPath describes the path to the node that we're looking for. For example, let's say that we want the state_name node in the XML document shown in Listing 11-1. A number of different ways exist for locating it, some of which are shown in Listing 11-2.&lt;br /&gt;&lt;br /&gt;Listing 11-1. A Sample XML Document&lt;br /&gt;&lt;states&gt;&lt;br /&gt;      &lt;state&gt;&lt;br /&gt;            &lt;state_abbreviation&gt;AB&lt;/state_abbreviation&gt;&lt;br /&gt;            &lt;state_name&gt;Alberta&lt;/state_name&gt;&lt;br /&gt;      &lt;/state&gt;&lt;br /&gt;      &lt;state&gt;&lt;br /&gt;            &lt;state_abbreviation&gt;AK&lt;/state_abbreviation&gt;&lt;br /&gt;            &lt;state_name&gt;Alaska&lt;/state_name&gt;&lt;br /&gt;      &lt;/state&gt;&lt;br /&gt;      &lt;state&gt;&lt;br /&gt;            &lt;state_abbreviation&gt;AL&lt;/state_abbreviation&gt;&lt;br /&gt;            &lt;state_name&gt;Alabama&lt;/state_name&gt;&lt;br /&gt;      &lt;/state&gt;&lt;br /&gt;      &lt;state&gt;&lt;br /&gt;            &lt;state_abbreviation&gt;AR&lt;/state_abbreviation&gt;&lt;br /&gt;            &lt;state_name&gt;Arkansas&lt;/state_name&gt;&lt;br /&gt;      &lt;/state&gt;&lt;br /&gt;&lt;/states&gt;&lt;br /&gt;Listing 11-2. Sample XPath&lt;br /&gt;/states/state/state_name&lt;br /&gt;/*/*/state_name&lt;br /&gt;/*/*/*[name(.) = 'state_name']&lt;br /&gt;/states/state/*[2]&lt;br /&gt;//state_name&lt;br /&gt;Why so many? With XPath, it is possible to describe complete paths, paths with wildcards, and paths based upon its location, or to describe only the node itself. From a high level, such as an orbital view, it works as shown in Table 11-1.&lt;br /&gt;&lt;br /&gt;Table 11-1. High-Level View of XPath XPath Notation&lt;br /&gt; Description&lt;br /&gt; &lt;br /&gt;/&lt;br /&gt; Either the root node, in the case of the first slash, or a separator between nodes&lt;br /&gt; &lt;br /&gt;//&lt;br /&gt; Anywhere in the document that meets the criteria&lt;br /&gt; &lt;br /&gt;*&lt;br /&gt; Wildcard (I know that there is a node here, but I don't know its name)&lt;br /&gt; &lt;br /&gt;.&lt;br /&gt; The context node (where we are at this point)&lt;br /&gt; &lt;br /&gt;[2]&lt;br /&gt; A predicate stating that the second node is the one we want&lt;br /&gt; &lt;br /&gt;states&lt;br /&gt; Qualified node name&lt;br /&gt; &lt;br /&gt;state&lt;br /&gt; Qualified node name&lt;br /&gt; &lt;br /&gt;state_name&lt;br /&gt; Qualified node name&lt;br /&gt; &lt;br /&gt;name()&lt;br /&gt; A function that returns the name of passed node&lt;br /&gt; &lt;br /&gt;[name(.) = 'state_name']&lt;br /&gt; A predicate stating that the desired node name is state_name&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Alright, that should be enough XPath to get started. Now let's take a gander at the XSLT shown in Listing 11-3, whose purpose is to build an HTML select object using the XML from Listing 11-1.&lt;br /&gt;&lt;br /&gt;Listing 11-3. Sample XSL Style Sheet&lt;br /&gt;&lt;?xml version='1.0'?&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0"&lt;br /&gt;xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;      &lt;xsl:output method="html" indent="yes" media-type="text/html"/&gt;&lt;br /&gt;&lt;br /&gt;      &lt;xsl:template match="/"&gt;&lt;br /&gt;&lt;br /&gt;            &lt;select id="myselect" name="myselect"&gt;&lt;br /&gt;                  &lt;xsl:for-each select="/states/state"&gt;&lt;br /&gt;                        &lt;xsl:element name="option"&gt;&lt;br /&gt;                              &lt;xsl:attribute name="value"&gt;&lt;br /&gt;                                    &lt;xsl:value-of&lt;br /&gt;select="state_abbreviation" /&gt;&lt;br /&gt;                              &lt;/xsl:attribute&gt;&lt;br /&gt;                              &lt;xsl:value-of select="state_name" /&gt;&lt;br /&gt;                        &lt;/xsl:element&gt;&lt;br /&gt;                  &lt;/xsl:for-each&gt;&lt;br /&gt;            &lt;/select&gt;&lt;br /&gt;&lt;br /&gt;      &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;&lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Pretty cool, isn't it? At first glance, not only is it nicely indented, but it also has the advantage of being one of the most obscure things that you've ever laid your eyes upon. A second glance reveals some details that you might have missed the first time; for example, the select statement looks remarkably like HTML. There is a very good reason for the resemblance: It is HTML. In fact, the xsl:output statement even says that it is HTML, and you can take it from me, xsl:output statements don't lie.&lt;br /&gt;&lt;br /&gt;Upon closer examination, some other details might pop out, such as the xsl:template with match="/". From what we covered earlier, the slash means that we're looking for the root node. And while we're examining XPath, you'll find xsl:for-each with select="/states/state". Just in case you're wondering, for-each means exactly what you think it does: Iterate once for every node that matches the predicate.&lt;br /&gt;&lt;br /&gt;Another thing that might jump out is the xsl:element node with name="option". This is an alternate method of specifying an output element. The xsl:attribute also does exactly what you'd expect from its name; it defines an attribute of the previous xsl:element. Finally, the xsl:value-of simply copies the node's content from the source document to the output document. In a nutshell, that's pretty much the basics of XSLT and XPath. The next question, of course, is, "So, what does the output HTML look like?" For the answer, check out Listing 11-4.&lt;br /&gt;&lt;br /&gt;Listing 11-4. HTML Output&lt;br /&gt;&lt;select id="myselect" name="myselect"&gt;&lt;br /&gt;  &lt;option value="AB"&gt;Alberta&lt;/option&gt;&lt;br /&gt;  &lt;option value="AK"&gt;Alaska&lt;/option&gt;&lt;br /&gt;  &lt;option value="AL"&gt;Alabama&lt;/option&gt;&lt;br /&gt;  &lt;option value="AR"&gt;Arkansas&lt;/option&gt;&lt;br /&gt;&lt;/select&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Later, both in this chapter and in others, you'll find more detailed examples of client-side XSLT.&lt;br /&gt;&lt;br /&gt;11.1.4. What I Learned from the Gecko&lt;br /&gt;Back when I was first learning XSLT, I was developing with the bare minimum, a text editor and a copy of Microsoft Internet Explorer version 5.01and I was happy! Well, at least for about 20 minutes or so, right up to the point I read the World Wide Web Consortium's XSLT recommendation. But we've already covered that, and after I downloaded a copy of Internet Explorer version 6, I was happy againat least, until I found Mozilla and then Firefox.&lt;br /&gt;&lt;br /&gt;My first impression was that there was something wrong with the Gecko XSLT processor, but there was a gnawing doubt. The reason for this was that I'd never personally found an error in a Gecko-based browser, and I had found several in Internet Explorer. So with a critical eye and a hard copy of the recommendation, I began to examine the "bugs" that I had found in the Gecko XSLT processor.&lt;br /&gt;&lt;br /&gt;The results came as no surprise to me. Gecko strictly followed the published recommendation, whereas IE seemed somewhat looser around the edges. My problem was that I had developed some bad habits developing in a microcosm and had a tendency to tailor my code to that microcosm. Because of this, I now try out my style sheets in at least two different XSLT processors before I consider them even partially tested.&lt;br /&gt;&lt;br /&gt;Let's take a look at how to create an instance of the XSLT processor in Microsoft Internet Explorer and every other web browser on the planeter, I mean Firefox, yeah, Firefox. Listing 11-5 shows a little cross-browser web page that uses one XML Data Island, the first containing the XML while the XSLT is loaded from the server via the XMLHttpRequest object. This is nothing flashy, merely a "proof of concept." It just creates an HTML select object and plops it on a page.&lt;br /&gt;&lt;br /&gt;Listing 11-5. XSLT Cross-Browser Web Page Example&lt;br /&gt;&lt;br /&gt;    &lt;head&gt;&lt;br /&gt;            &lt;title&gt;XML Data Island Test&lt;/title&gt;&lt;br /&gt;            &lt;style type="text/css"&gt;&lt;br /&gt;xml&lt;br /&gt;{&lt;br /&gt;      display: none;&lt;br /&gt;      font-size: 0px&lt;br /&gt;}&lt;br /&gt;            &lt;/style&gt;&lt;br /&gt;            &lt;script language="JavaScript"&gt;&lt;br /&gt;var _IE = (new RegExp('internet explorer','gi')).test(navigator.appName);&lt;br /&gt;var _XMLHTTP;                                               //&lt;br /&gt; XMLHttpRequest object&lt;br /&gt;var _objXML;                   // XML DOM document&lt;br /&gt;var _objXSL;                   //&lt;br /&gt;  Stylesheet&lt;br /&gt;var _objXSLTProcessor;         // XSL Processor&lt;br /&gt;var _xslt = 'stateSelect.xsl'; // Path to style sheet&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;    Function:     initialize&lt;br /&gt;      Programmer: Edmond Woychowsky&lt;br /&gt;      Purpose:    Perform page initialization.&lt;br /&gt;*/&lt;br /&gt;function initialize() {&lt;br /&gt;  if(_IE) {&lt;br /&gt;    _XMLHTTP = new ActiveXObject('Microsoft.XMLHTTP');&lt;br /&gt;&lt;br /&gt;      _objXML =&lt;br /&gt;       new ActiveXObject('MSXML2.FreeThreadedDOMDocument.3.0');&lt;br /&gt;      _objXSL =&lt;br /&gt;      new ActiveXObject('MSXML2.FreeThreadedDOMDocument.3.0');&lt;br /&gt;&lt;br /&gt;      _objXML.async = false;&lt;br /&gt;      _objXSL.async = false;&lt;br /&gt;&lt;br /&gt;      _objXML.load(document.getElementById('xmlDI').XMLDocument);&lt;br /&gt;   } else {&lt;br /&gt;      var _objParser = new DOMParser();&lt;br /&gt;&lt;br /&gt;      _XMLHTTP = new XMLHttpRequest();&lt;br /&gt;&lt;br /&gt;      _objXSLTProcessor = new XSLTProcessor();&lt;br /&gt;      _objXML =&lt;br /&gt;_objParser.parseFromString(document.getElementById('xmlDI').innerHTML,&lt;br /&gt;"text/xml");&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  _XMLHTTP.onreadystatechange = stateChangeHandler;&lt;br /&gt;&lt;br /&gt;  _XMLHTTP.open('GET',_xslt,true);&lt;br /&gt;  _XMLHTTP.send(null);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;    Function:     stateChangeHandler&lt;br /&gt;      Programmer: Edmond Woychowsky&lt;br /&gt;      Purpose:    Handle the asynchronous response to an&lt;br /&gt;                  XMLHttpRequest, transform the XML Data Island and&lt;br /&gt;                  display the resulting XHTML.&lt;br /&gt;*/&lt;br /&gt;function stateChangeHandler() {&lt;br /&gt;  var strXHTML;&lt;br /&gt;&lt;br /&gt;  if(_XMLHTTP.readyState == 4) {&lt;br /&gt;      if(_IE) {&lt;br /&gt;            var _objXSLTemplate =&lt;br /&gt;            new ActiveXObject('MSXML2.XSLTemplate.3.0');&lt;br /&gt;&lt;br /&gt;            _objXSL.loadXML(_XMLHTTP.responseText);&lt;br /&gt;            _objXSLTemplate.stylesheet = _objXSL;&lt;br /&gt;            _objXSLTProcessor = _objXSLTemplate.createProcessor;&lt;br /&gt;            _objXSLTProcessor.input = _objXML;&lt;br /&gt;&lt;br /&gt;            _objXSLTProcessor.transform();&lt;br /&gt;&lt;br /&gt;            strXHTML = _objXSLTProcessor.output;&lt;br /&gt;      } else {&lt;br /&gt;            var _objSerializer = new XMLSerializer();&lt;br /&gt;&lt;br /&gt;            _objXSL = _XMLHTTP.responseXML;&lt;br /&gt;&lt;br /&gt;            _objXSLTProcessor.importStylesheet(_objXSL);&lt;br /&gt;&lt;br /&gt;            strXHTML =&lt;br /&gt;_objSerializer.serializeToString(_objXSLTProcessor.transformToFragment&lt;br /&gt;(_objXML, document));&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      document.getElementById('target').innerHTML = strXHTML;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;            &lt;/script&gt;&lt;br /&gt;      &lt;/head&gt;&lt;br /&gt;      &lt;body onload="initialize()"&gt;&lt;br /&gt;            &lt;xml id="xmlDI"&gt;&lt;br /&gt;            &lt;states&gt;&lt;br /&gt;                 &lt;state&gt;&lt;br /&gt;                      &lt;state_abbreviation&gt;AB&lt;/state_abbreviation&gt;&lt;br /&gt;                      &lt;state_name&gt;Alberta&lt;/state_name&gt;&lt;br /&gt;                 &lt;/state&gt;&lt;br /&gt;                 &lt;state&gt;&lt;br /&gt;                      &lt;state_abbreviation&gt;AK&lt;/state_abbreviation&gt;&lt;br /&gt;                      &lt;state_name&gt;Alaska&lt;/state_name&gt;&lt;br /&gt;                 &lt;/state&gt;&lt;br /&gt;                 &lt;state&gt;&lt;br /&gt;                      &lt;state_abbreviation&gt;AL&lt;/state_abbreviation&gt;&lt;br /&gt;                      &lt;state_name&gt;Alabama&lt;/state_name&gt;&lt;br /&gt;                 &lt;/state&gt;&lt;br /&gt;                 &lt;state&gt;&lt;br /&gt;                      &lt;state_abbreviation&gt;AR&lt;/state_abbreviation&gt;&lt;br /&gt;                      &lt;state_name&gt;Arkansas&lt;/state_name&gt;&lt;br /&gt;                 &lt;/state&gt;&lt;br /&gt;            &lt;/states&gt;&lt;br /&gt;        &lt;/xml&gt;&lt;br /&gt;            &lt;b&gt;XML client-side transformation test&lt;/b&gt;&lt;br /&gt;        &lt;div id="target"&gt;&lt;/div&gt;&lt;br /&gt;      &lt;/body&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Alright, now that the proof of concept has been successfully completed, all that remains is to see how it can be applied to our e-commerce website.&lt;br /&gt;&lt;br /&gt;A Problem Revisited&lt;br /&gt;Now that we have some of the basics down, let's take a look at how XSLT can be used to provide additional functionality to our e-commerce website. I should point out, however, that when I originally proposed this idea to a client, I was called insane. The comments were that it would be unworkable and that nobody in their right mind would have even suggested it. In my defense, this was the client that used terms such as blink and was "looking into" converting all web applications into COBOL so that developers other than the consultants could understand it.&lt;br /&gt;&lt;br /&gt;That's enough introductions; without further ado, allow me to describe what I consider the ultimate "mad scientist" website.&lt;br /&gt;&lt;br /&gt;Excluding pop-ups, the site would be a single web page, with all communication between the server and the client taking place using the XMLHttpRequest object. Instead of subjecting the visitor to an endless cycle of unloads and reloads, the page would simply request whatever it needed directly. In addition, when a particular XSLT was obtained from the server, the client would cache it, meaning that the next time it was needed, it would already be there. It was within the realm of possibility that eventually the client would have all the XSLT cached on the web browser. The more the visitor did, the better the shopping experience would become.&lt;br /&gt;&lt;br /&gt;Needless to say, the website was never created, alas, and my contract was terminated because they felt that resources could be better used supporting their mainframe applications. Personally, I think that they lacked foresight, and if they had pursued the concept to its logical conclusion, they'd now be mentioned in the same breath as Google. Instead, they decided to regress into the future of the 1960s as opposed to the future of the twenty-first century. But I'm hardly an objective observer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1256749879512151332?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1256749879512151332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-11-ajax-using-xslt.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1256749879512151332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1256749879512151332'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-11-ajax-using-xslt.html' title='Chapter 11. Ajax Using XSLT'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-316517773720334003</id><published>2008-12-13T11:20:00.000-08:00</published><updated>2009-01-26T12:33:17.865-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>11.2. Tabular Information&lt;br /&gt;The previous chapter introduced several JavaScript class constructors in an effort to keep the client-side code manageable. Now is a good time to introduce another, a wrapper around the XSLT processor to handle the browser-specific details involving exactly what is required for XSL transformations. Displaying my usual lack of imagination, the class constructor is named appropriately enough: XSLTProcessor. Table 11-2 shows the properties and methods for this class.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Table 11-2. XSLTProcessor Name&lt;br /&gt; Parent Class&lt;br /&gt; Type&lt;br /&gt; Description&lt;br /&gt; &lt;br /&gt;XSLTProcessor&lt;br /&gt; &lt;br /&gt; Class&lt;br /&gt; Constructor&lt;br /&gt; &lt;br /&gt;importStylesheet&lt;br /&gt; XSLTProcessor&lt;br /&gt; Method&lt;br /&gt; Loads the XSL document for the transformation.&lt;br /&gt; &lt;br /&gt;load&lt;br /&gt; XSLTProcessor&lt;br /&gt; Method&lt;br /&gt; Loads the XML document to be transformed.&lt;br /&gt; &lt;br /&gt;output&lt;br /&gt; XSLTProcessor&lt;br /&gt; Method&lt;br /&gt; The serialized result of the previous transformation.&lt;br /&gt; &lt;br /&gt;readyState&lt;br /&gt; XSLTProcessor&lt;br /&gt; Method&lt;br /&gt; Either the ready state for the XML document or the XSL document, whichever is lower. When they are equal, the appropriate ready state value is returned.&lt;br /&gt; &lt;br /&gt;setParameter&lt;br /&gt; XSLTProcessor&lt;br /&gt; Method&lt;br /&gt; Set a parameter for the XSLT processor.&lt;br /&gt; &lt;br /&gt;transform&lt;br /&gt; XSLTProcessor&lt;br /&gt; Method&lt;br /&gt; Performs the transformation and returns the serialized result.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;With the creation of the XSLTProcessor constructor, the only items remaining are those that are absolutely essential to the website. The essential items are the XSL style sheets themselves, three in total. The first style sheet creates the HTML for the Items page. The purpose of the second style sheet is to create/render the Details page. The final style sheet renders the shopping cart in a slightly different manner than you'd expect. Each of these three items is covered as needed.&lt;br /&gt;&lt;br /&gt;11.2.1. Read Only&lt;br /&gt;Please bear with me; what I'm about to say deals only with read-only pages and, to some, might seem to be heresy. When using XSL for read-only pages, data binding isn't necessary; in fact, it is unnecessary overhead. Think about it for a moment: First, the information isn't going to change on the client side. In addition, the transformation process has already taken care of the display of the information. For the aforementioned reasons, it is perfectly acceptable to skip the bind when dealing with read-only information, as the style sheet in Listing 11-6 illustrates.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Listing 11-6. XSL Style Sheet to Produce a Nonbound Table&lt;br /&gt;&lt;?xml version='1.0'?&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0"&lt;br /&gt;xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;      &lt;xsl:output method="html" indent="yes" media-type="text/html"/&gt;&lt;br /&gt;&lt;br /&gt;      &lt;xsl:template match="/"&gt;&lt;br /&gt;            &lt;xsl:element name="div"&gt;&lt;br /&gt;                  &lt;xsl:call-template name="row"&gt;&lt;br /&gt;                        &lt;xsl:with-param name="string" select="'Guild&lt;br /&gt;Name:'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="top" select="'75px'" /&gt;&lt;br /&gt;                  &lt;/xsl:call-template&gt;&lt;br /&gt;                  &lt;xsl:call-template name="row"&gt;&lt;br /&gt;                        &lt;xsl:with-param name="string" select="'Item&lt;br /&gt;Name:'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="top" select="'92px'" /&gt;&lt;br /&gt;                  &lt;/xsl:call-template&gt;&lt;br /&gt;                  &lt;xsl:call-template name="row"&gt;&lt;br /&gt;                        &lt;xsl:with-param name="string"&lt;br /&gt;select="'Description:'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="top" select="'110px'" /&gt;&lt;br /&gt;                  &lt;/xsl:call-template&gt;&lt;br /&gt;                  &lt;xsl:call-template name="row"&gt;&lt;br /&gt;                        &lt;xsl:with-param name="string" select="'Price:'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="top" select="'127px'" /&gt;&lt;br /&gt;                  &lt;/xsl:call-template&gt;&lt;br /&gt;&lt;br /&gt;                  &lt;xsl:call-template name="row"&gt;&lt;br /&gt;                        &lt;xsl:with-param name="string"&lt;br /&gt;select="'guild_name'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="type" select="'data'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="top" select="'75px'" /&gt;&lt;br /&gt;                  &lt;/xsl:call-template&gt;&lt;br /&gt;                  &lt;xsl:call-template name="row"&gt;&lt;br /&gt;                        &lt;xsl:with-param name="string" select="'item_name'"&lt;br /&gt;/&gt;&lt;br /&gt;                        &lt;xsl:with-param name="type" select="'data'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="top" select="'92px'" /&gt;&lt;br /&gt;                  &lt;/xsl:call-template&gt;&lt;br /&gt;                  &lt;xsl:call-template name="row"&gt;&lt;br /&gt;                        &lt;xsl:with-param name="string"&lt;br /&gt;select="'item_description'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="type" select="'data'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="top" select="'110px'" /&gt;&lt;br /&gt;                  &lt;/xsl:call-template&gt;&lt;br /&gt;                  &lt;xsl:call-template name="row"&gt;&lt;br /&gt;                        &lt;xsl:with-param name="string"&lt;br /&gt;select="'item_price:'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="type" select="'data'" /&gt;&lt;br /&gt;                        &lt;xsl:with-param name="top" select="'127px'" /&gt;&lt;br /&gt;                  &lt;/xsl:call-template&gt;&lt;br /&gt;                  &lt;/xsl:element&gt;&lt;br /&gt;            &lt;/xsl:template&gt;&lt;br /&gt;&lt;br /&gt;            &lt;xsl:template name="row"&gt;&lt;br /&gt;                  &lt;xsl:param name="dataisland" select="' '" /&gt;&lt;br /&gt;                  &lt;xsl:param name="string" /&gt;&lt;br /&gt;                  &lt;xsl:param name="type" select="'header'" /&gt;&lt;br /&gt;                  &lt;xsl:param name="top" /&gt;&lt;br /&gt;&lt;br /&gt;                  &lt;xsl:variable name="apostrophe"&gt;'&lt;/xsl:variable&gt;&lt;br /&gt;                  &lt;xsl:variable name="nbsp"&gt;&amp;amp;nbsp;&lt;/xsl:variable&gt;&lt;br /&gt;&lt;br /&gt;            &lt;xsl:element name="div"&gt;&lt;br /&gt;                  &lt;xsl:attribute name="class"&gt;rowHeader&lt;/xsl:attribute&gt;&lt;br /&gt;                  &lt;xsl:attribute name="style"&gt;&lt;br /&gt;                        &lt;xsl:choose&gt;&lt;br /&gt;                              &lt;xsl:when test="$type = 'header'"&gt;&lt;br /&gt;                                    &lt;xsl:value-of&lt;br /&gt;select="concat($apostrophe,'position: absolute; left: 50px; right: auto%;&lt;br /&gt;bottom: auto; width: 200px; top: ',$top,$apostrophe)" /&gt;&lt;br /&gt;                              &lt;/xsl:when&gt;&lt;br /&gt;                              &lt;xsl:otherwise&gt;&lt;br /&gt;                                    &lt;xsl:value-of&lt;br /&gt;select="concat($apostrophe,'position: absolute; left: 255px; right: auto%;&lt;br /&gt;bottom: auto; width: 600px; top: ',$top,$apostrophe)" /&gt;&lt;br /&gt;                              &lt;/xsl:otherwise&gt;&lt;br /&gt;                        &lt;/xsl:choose&gt;&lt;br /&gt;                  &lt;/xsl:attribute&gt;&lt;br /&gt;&lt;br /&gt;                  &lt;xsl:choose&gt;&lt;br /&gt;                        &lt;xsl:when test="$type = 'header'"&gt;&lt;br /&gt;                              &lt;xsl:value-of disable-output-escaping="yes"&lt;br /&gt;select="concat($nbsp,$string)" /&gt;&lt;br /&gt;                        &lt;/xsl:when&gt;&lt;br /&gt;                        &lt;xsl:otherwise&gt;&lt;br /&gt;                              &lt;xsl:attribute name="xmlDI"&gt;&lt;br /&gt;                                    &lt;xsl:value-of select="$dataisland" /&gt;&lt;br /&gt;                              &lt;/xsl:attribute&gt;&lt;br /&gt;                              &lt;xsl:attribute name="xmlNode"&gt;&lt;br /&gt;                                    &lt;xsl:value-of select="$string" /&gt;&lt;br /&gt;                              &lt;/xsl:attribute&gt;&lt;br /&gt;                        &lt;/xsl:otherwise&gt;&lt;br /&gt;                  &lt;/xsl:choose&gt;&lt;br /&gt;            &lt;/xsl:element&gt;&lt;br /&gt;      &lt;/xsl:template&gt;&lt;br /&gt;&lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This style sheet first creates an HTML Table element with the required attributes to give the site a common look and feel. Next, the column headers are rendered and a template is invoked to create the individual rows, which is the Table element in the source XML document. If there are no Table elements, only the HTML table headers will be produced. The individual cells are produced based upon the node name, and we're done.&lt;br /&gt;&lt;br /&gt;Before proceeding any further, however, I want to explain two statements in the style sheet. The first of these is the one that defines the apostrophe variable:&lt;br /&gt;&lt;br /&gt;&lt;xsl:variable name="apostrophe"&gt;'&lt;/xsl:variable&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The second statement is the one that uses the apostrophe variable:&lt;br /&gt;&lt;br /&gt;&lt;xsl:value-of select="concat('javascript:pageLoad&lt;br /&gt;(',$apostrophe,'itemsDisplay.xsl',$apostrophe,',&lt;br /&gt;',guild_id,',null)')" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;These two statements might seem somewhat odd because if you're even slightly familiar with XSL, you know that there is a perfectly acceptable entity that can be used to render apostrophes. The entity that I refer to is &amp;apos;, which, unfortunately, would cause quite a few headaches if used here. The entity would be treated as if it were, in fact, an apostrophe. The XSLT processor would then consider the previous statement to be equivalent to the following.&lt;br /&gt;&lt;xsl:value-of select="concat('javascript:pageLoad&lt;br /&gt;(',','itemsDisplay.xsl',',',',guild_id,',null)')" /&gt;&lt;br /&gt;As you can see, this would lead to an error and a nasty error message instead of the page shown in Figure 11-1.&lt;br /&gt;11.2.2. Updateable&lt;br /&gt;Unlike the previous read-only example, binding cannot be ignored when using XSLT to create updateable web pages. Even so, several advantages exist that were unavailable in earlier chapters. For example, there are the funky looping and concatenating strings to build the HTML with the correct number of rows. XSL takes care of those annoying details &lt;br /&gt;11.3. Advantages and Disadvantages&lt;br /&gt;A number of advantages exist for designing a site that uses client-side XSLT. The first is that it really looks good on the old resuméstrike that. The first is that it becomes possible to design more dynamic websites that can take advantage of the client's machine. In addition, the amount of information can be reduced by caching the XSL style sheets on the client machine. However, if the resources available on the client become something of an issue, there are always alternatives.&lt;br /&gt;&lt;br /&gt;The first alternative that comes to mind is to not cache the XSL at all; instead, it could be sent back and forth along with the XML. For large sites, another possibility is to cache only a certain number of pages. This could be handled in sort of a stack: first in, first out.&lt;br /&gt;&lt;br /&gt;Concerning caching, one additional idea comes to mind: Forgo the preload entirely. Instead, style sheets could be loaded on an as-needed basis. After being loaded, they could then be cached. The interesting thing about this idea is that, from the client's perspective, performance would improve over timealmost as if the site got better with practice. Talk about mad scientist stuff!&lt;br /&gt;&lt;br /&gt;Alas, all of this is for naught if the client's browser doesn't support transformations. Not all of them do. I suppose that an alternative should be made available for those that, for some reason, are still running Microsoft Internet Explorer version 3.0. No, I don't mean server-side transformations to accommodate luddites; I'm thinking more along the lines of a link to www.mozilla.org, where they can join everyone else in the twenty-first&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-316517773720334003?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/316517773720334003/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/11.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/316517773720334003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/316517773720334003'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/11.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1568961084138671859</id><published>2008-12-13T11:19:00.001-08:00</published><updated>2009-01-26T12:33:17.865-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>Chapter 12. Better Living Through Code Reuse&lt;br /&gt;At one time in my career, I was a consultant, or, if you prefer, a hired gun. My job was to ride into town, clean up things, and then ride off into the sunset. It was like being a Wild West hero, just me and my horsealright, just me and my little blue car. Please believe me when I say that I ride like the late movie star Lee Marvin; have you ever seen Cat Balloo? If you haven't, let's just say that my posture in the saddle isn't the best.&lt;br /&gt;&lt;br /&gt;The reason that I bring this up is that, like those heroes of old, I lived by my wits, or approximately half of my wits, and what I could carry with me. However, instead of a Colt Dragoon, I carried a laptop loaded with every little tool I had ever written or downloaded. Some of the tools were useful and some of them were not so useful, but nevertheless, it contained everything that I could possibly need, not counting the games. I suppose another way to look at it is that I'm a packrat, but once I code something, I'd rather not code it again.&lt;br /&gt;&lt;br /&gt;Of course, it wasn't that I was avoiding coding; actually, I was avoiding the debugging. The act of debugging isn't distasteful, but the act of debugging the same thing again and again gets old really fast. Ever hear the phrase "don't reinvent the wheel"? Well, I wholeheartedly agree with it. Although, maybe if I could make it better ....&lt;br /&gt;&lt;br /&gt;The best part of these Ajax tools is that they aren't carved in stone; they are actually more scribbled in crayon. Because of this, they are fluid, meant to be more of a guide than gospel. However, even if you choose not to use these, I recommend that you at least look at them. Most of these functions work pretty much the same.&lt;br /&gt;&lt;br /&gt;Why?&lt;br /&gt;&lt;br /&gt;The reason is pretty simple. You see, Ajax applications are just like lemonade. In other words, there are a few basic ingredients, as with lemons, sugar, and water. Of course, not all lemonades are created equal. This is mostly because of the amounts of each ingredient and the little extras, such as vodka or checking an object's readyState property.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1568961084138671859?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1568961084138671859/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-12.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1568961084138671859'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1568961084138671859'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-12.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5537062588204770316</id><published>2008-12-13T11:18:00.001-08:00</published><updated>2009-01-26T12:33:17.866-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>12.1. Reuse = Laziness&lt;br /&gt;I'm not really sure whether it is a character flaw or a skill, but I have a tendency to code some routines twice. The first time is to solve the particular problem at hand; the second time is so that I have a generic solution if the problem crops up somewhere else. Sometimes it does and sometimes it doesn't, but it is nice to be able to accept an assignment and have at least part of the solution coded. It is also a great way to make sure that there is always time to read User Friendly.&lt;br /&gt;&lt;br /&gt;Unfortunately, when I started my career, this wasn't the case, mostly because I encountered managers who believed in the puritan work ethic: Work constantly until you die, or quit before the age of 33, a burnt-out husk. Basically, the more lines of code, the better, although they sometimes cloaked their philosophy behind the words "I need it so that everyone can understand it" or avoid "mad scientist stuff." However, during the years, this type of manager has largely either died off or retired. I suppose that, on some level, I will miss them, in much the same way as a headache that has gone away. Yes, I will sorely miss the threats of nonpayment for reusing code to create new applications.&lt;br /&gt;&lt;br /&gt;"Hello, my name is Ed. I reuse code to death and I am not lazy!"&lt;br /&gt;&lt;br /&gt;12.1.1. Paid by the Line&lt;br /&gt;Several years ago, as a consultant, I was assigned the responsibility to write client-side JavaScript whose sole purpose was to speed up the client's website. The problem was that they had a vision of what they wanted, but they didn't quite know how to implement it. For example, let's say that a web page consisted of 20 rows in an HTML table, each of which had a select created from a database query, and that each select had the same options. They saw nothing wrong with executing the same query 20 times and using VBScript 20 times to create the 20 selects. Oh, there were two other things: With the exception of looping through the results of the query, there were no loops, and there wasn't even a function that was called 20 times. The code was one straight run. Because it had been written by the lead developer only about six months before and I was only a consultant, I never asked the burning question: Why?&lt;br /&gt;&lt;br /&gt;It didn't take me more than a couple of days to figure out the answer. In fact, all it took was one glance at their JavaScript library. The entire library consisted of a single function whose purpose was to determine whether a parameter was numeric, not that it was used anywhere. It was almost like I had stepped through a rift in the fabric of space-time and found myself in an alternate reality. The more I examined the site, the more I kept looking around expecting to see Rod Serling. To give you an idea, it was after Y2K and they were still using HTML FONT tags. There was not a single example of Cascading Style Sheets anywhere. The word deprecated didn't exist in their world.&lt;br /&gt;&lt;br /&gt;There were classic ASP pages that were in excess of 30,000 lines of mixed script and HTML. I was a stranger in a strange land where developers were paid by the line. It was a new application, not yet in production, so it couldn't have been maintained into incomprehensibility. What else could explain the way that things were?&lt;br /&gt;&lt;br /&gt;12.1.2. Paid by the Page&lt;br /&gt;Fortunately, I was paid by the pagealright, actually, it was by the hour, but I had a limited number of hours to produce each page. Couple this with the fact that I'm a hunt-and-peck typist, and you'll quickly understand why I'm a big believer in code reuse. The odd thing was that, with one exception, nobody ever noticed that code was being reused left and right.&lt;br /&gt;&lt;br /&gt;On one of my last consulting assignments I met an intern who was fresh out of school yet was one of the sharpest developers I ever met. After working together for about six months, he asked me why it seemed that whenever possible I wrote reusable code that often used reusable code that I had written previously. There was only one way to answer: "I like writing tools to make tools."&lt;br /&gt;&lt;br /&gt;A simple enough phrase, "tools to make tools," but what does it mean?&lt;br /&gt;&lt;br /&gt;Ask me what I mean, and I'll say that it means that there is an underlying architecture that can be built upon. But to me personally, it goes much deeper than that. Take a moment and look around you; what do you see? You're surrounded by toolstools that shelter us, tools that entertain us, tools that preserve our images and thoughts beyond our individual lifespan.&lt;br /&gt;&lt;br /&gt;Where did these tools that have become so important come from? Somebody created them, another person used them, and yet another person improved them. In essence, the Internet is merely an improvement of a cave painting taken to the nth degree. There's a long history of our species creating "tools to make tools." Therefore, it is only natural to create tools, share those tools, every once in a while wonder who will improve them, and lament the fact that you can't get a good mastodon sandwich anymore.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5537062588204770316?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5537062588204770316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/12_13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5537062588204770316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5537062588204770316'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/12_13.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-4970276547193105221</id><published>2008-12-13T11:15:00.000-08:00</published><updated>2009-01-26T12:33:17.866-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>12.2. JavaScript Objects&lt;br /&gt;Although it's not an object-oriented language, JavaScript is an object-based language. This means that, although it might not be as powerful as PHP, Ruby, or Java, it is still pretty darn powerful. Add the fact that it is currently the best/only choice available, and you'll quickly understand why objects are important.&lt;br /&gt;&lt;br /&gt;Although there are several ways to create objects in JavaScript, I usually use only two. The first method of creating an object in JavaScript is simply a matter of writing a function and assigning it to a variable using the new operator to create an instance, as shown in Listing 12-1.&lt;br /&gt;&lt;br /&gt;Listing 12-1. Example function Class Constructor&lt;br /&gt;function word() {&lt;br /&gt;      var _setCount = 0;            //    Protected variable&lt;br /&gt;&lt;br /&gt;      this.theWord;                 //    Public property&lt;br /&gt;      this.setWord = _setWord;      //    Public method setWord&lt;br /&gt;      this.getWord = _getWord;      //    Public method getWord&lt;br /&gt;      this.count = _getSetCount;    //    Public method count&lt;br /&gt;&lt;br /&gt;      function _setWord(theWord) {&lt;br /&gt;               //    Public exposed as getWord&lt;br /&gt;            this.theWord = theWord;&lt;br /&gt;            _incrementCount();&lt;br /&gt;      }&lt;br /&gt;      function _getWord() {         //    Public exposed as setWord&lt;br /&gt;            return(this.theWord);&lt;br /&gt;      }&lt;br /&gt;      function _getSetCount() {     //    Public exposed as count&lt;br /&gt;            return(_setCount);&lt;br /&gt;      }&lt;br /&gt;      function _incrementCount() {  //    Private method&lt;br /&gt;            ++_setCount;&lt;br /&gt;      }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var myInstance = new word();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now we have an instance of the property word assigned to the variable myInstance, and the only question is, how do we use it? Thankfully, the notation for addressing properties and methods is a relatively standard instancename.property or instancename.method(). If you're looking at the constructor, the way to distinguish them is that they are all preceded by the this keyword. The way to tell which are properties and which are methods is that methods always are equal to a function. It is important to point out that the parentheses are omitted because including them would cause the method to be invoked as well as exposed.&lt;br /&gt;&lt;br /&gt;Although the previous class constructor is essentially useless, it does show the details of how to create a constructor. It has private members, _setCount, and private methods, _incrementCount. Also, as explained previously, it has both public properties, as in theWord, and public methods, as in setWord, getWord, and getSetCount. Of course, an example that is actually useful might not have all of these.&lt;br /&gt;&lt;br /&gt;12.2.1. Collections&lt;br /&gt;I might be wrong, but I am of the opinion that the most useful type of data structure that has ever been conceived, excluding the DOM, is perhaps an associative array. If you're unfamiliar with this type of data structure, information is stored in name/value pairs. If you know the name, you can find the value. And the value isn't limited to any particular data type; come to think of it, neither is the name. A good use would be to cache XSL style sheets because they usually don't change very often. After they're cached, it is no longer necessary to bother the web server to get them; all that is necessary is to retrieve them from the cache. However, there is one danger, and that danger is caching information that shouldn't be cached because someone else might change it, as in the results of database queries.&lt;br /&gt;&lt;br /&gt;Listing 12-2 is an example of a constructor for a lightweight cache/associative array. The single private property, _cache, is a JavaScript object that is the cache itself. There are three public methods to handle inserting name/value pairs, retrieving values, and purging either selected name/value pairs or the entire contents of the cache.&lt;br /&gt;&lt;br /&gt;Listing 12-2. Cache Class Constructor (Associative Array)&lt;br /&gt;&lt;!-- &lt;![CDATA[&lt;br /&gt;/*&lt;br /&gt;      Class:    Cache&lt;br /&gt;      Function: Cache&lt;br /&gt;      Purpose:  To act as a client-side cache(associative array).&lt;br /&gt;             Data are stored as name/value pairs.&lt;br /&gt;*/&lt;br /&gt;function Cache() {&lt;br /&gt;  var _cache = new Object();&lt;br /&gt;               // Object to store information&lt;br /&gt;  var _namesArray = new Array();     // Array for names&lt;br /&gt;&lt;br /&gt;  this.insert = _insert;             // Method: cache an object&lt;br /&gt;  this.retrieve = _retrieve;         // Method: retrieve object&lt;br /&gt;  this.purge = _purge;               // Method: purge object(s)&lt;br /&gt;  this.names = _names;               // Method: return names&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;      Function: _insert&lt;br /&gt;      Method:   insert&lt;br /&gt;      Purpose:  Inserts a name/value pair into the cache.&lt;br /&gt;  */&lt;br /&gt;  function _insert(name,value) {&lt;br /&gt;    _cache[name] = value;            // Cache object&lt;br /&gt;&lt;br /&gt;    _namesArray.push(name);          // Store name&lt;br /&gt;  }&lt;br /&gt;  /*&lt;br /&gt;      Function: _retrieve&lt;br /&gt;      Method:   retrieve&lt;br /&gt;      Purpose:  Retrieves a value from the cache using a name.&lt;br /&gt;  */&lt;br /&gt;  function _retrieve(name) {&lt;br /&gt;    if(typeof(_cache[name]) == 'undefined')&lt;br /&gt;      return(null);                  // Object not cached&lt;br /&gt;    else&lt;br /&gt;      return(_cache[name]);          // Return object&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;      Function: _purge&lt;br /&gt;      Method:   purge&lt;br /&gt;      Purpose:  Purges one or more name/value pairs from&lt;br /&gt;                the cache.&lt;br /&gt;  */&lt;br /&gt;  function _purge() {&lt;br /&gt;    if(arguments.length == 0) {&lt;br /&gt;      _cache = new Object();         // Create new cache object&lt;br /&gt;      _namesArray = new Array();     // Create new names array&lt;br /&gt;    } else {&lt;br /&gt;      var singleName;&lt;br /&gt;&lt;br /&gt;      _namesArray = new Array();     // Create new names array&lt;br /&gt;&lt;br /&gt;      for(var i=0;i &lt; arguments.length;i++)&lt;br /&gt;        _cache[arguments[i]] = null;&lt;br /&gt;&lt;br /&gt;      for(singleName in _cache)&lt;br /&gt;        if(_cache[singleName] != null)&lt;br /&gt;          _namesArray.push(singleName);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;     Function:    _names&lt;br /&gt;     Method:   names&lt;br /&gt;     Purpose:  Returns an array consisting of the names from the&lt;br /&gt;               cache.&lt;br /&gt;  */&lt;br /&gt;  function _names() {&lt;br /&gt;    return(_namesArray);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;// ]]&gt; --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;As with the previous example, it is necessary to create an instance of the object before using it. Listing 12-3 shows the object being put through its paces, along with the expected results shown in the comments.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Listing 12-3. Listing Head Here&lt;br /&gt;&lt;br /&gt;var magicWords = new Cache();&lt;br /&gt;&lt;br /&gt;magicWords.insert(1,'xyzzy'); // Insert key = 1, value = 'xyzzy'&lt;br /&gt;magicWords.insert(2,'plugh'); // Insert key = 2, value = 'plugh'&lt;br /&gt;magicWords.insert(3,'plover');&lt;br /&gt;// Insert key = 3, value = 'plover'&lt;br /&gt;&lt;br /&gt;alert(magicWords.names());          // 1,2,3&lt;br /&gt;alert(magicWords.retrieve(1));      // 'xyzzy'&lt;br /&gt;alert(magicWords.retrieve(2));      // 'plugh'&lt;br /&gt;&lt;br /&gt;magicWords.purge(3);&lt;br /&gt;// Purge key/value pair - key = 3&lt;br /&gt;&lt;br /&gt;alert(magicWords.retrieve(3));      // null&lt;br /&gt;alert(magicWords.names());          // 1,2&lt;br /&gt;&lt;br /&gt;magicWords.purge();                 // Purge all key/value pairs&lt;br /&gt;&lt;br /&gt;alert(magicWords.retrieve(1));      // null&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The caching class is pretty straightforward; it is only a wrapper around a JavaScript object that has public methods that allow for changes to the object and retrieval from the object.&lt;br /&gt;&lt;br /&gt;12.2.2. XML&lt;br /&gt;Without a doubt, my biggest complaint concerning client-side XML is the lack of a single cross-browser way to create an XML document. This is one of those areas in which cross-browser coding can be a real drag because I have a tendency to create a page using a single browser. Only when I get it working in my browser of choice do I go back and try to make it work for Internet Explorer. In case you are wondering, this makes for some really ugly JavaScript, all sewn together from various mismatched parts. I may be a mad scientist, but there is something to be said for reusability.&lt;br /&gt;&lt;br /&gt;That's the reason I cobbled together a few class constructors to neaten things up around the old lab. It's not like I'm using coasters or anything. I'm just trying to make sure that I can understand what I wrote six months from now. They say that the memory is the first thing to goor is it the hair? Whatever, I can't even remember who "they" are anyway, so it can't be important.&lt;br /&gt;&lt;br /&gt;The first of these class constructors is to handle the details involved with using the XMLHttpRequest object. It deals with whether the browser is Microsoft Internet Explorer or any other browser, and then it creates the XMLHTTPRequest object using the syntax appropriate to the specific browser. In addition, it handles readyState changes for asynchronous requests. Unlike the previous example, which was created in much the same manner as a regular JavaScript class, this time a prototype object is created. Although they're not used for these constructors, prototypes offer the advantage of allowing for the possibility of inheritance if it is deemed necessary in the future. Listing 12-4 shows what the constructor looks like.&lt;br /&gt;&lt;br /&gt;Listing 12-4. Cross-Browser (Gecko and IE) XMLHttp Class Constructor&lt;br /&gt;&lt;br /&gt;&lt;!-- &lt;![CDATA[&lt;br /&gt;XMLHttpRequest.prototype = new XMLHttpRequest;&lt;br /&gt;XMLHttpRequest.prototype.constructor = XMLHttpRequest;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLHttpRequest&lt;br /&gt;      Function:    XMLHttpRequest&lt;br /&gt;      Method:      n/a&lt;br /&gt;      Description: Constructor for this class.&lt;br /&gt;*/&lt;br /&gt;function XMLHttpRequest() {&lt;br /&gt;  try {&lt;br /&gt;    var x = new DOMParser();&lt;br /&gt;    this._IE = false;&lt;br /&gt;  }&lt;br /&gt;  catch(e) { this._IE = true; };&lt;br /&gt;  this._XMLHttp;                     // XMLHttp request object&lt;br /&gt;  this._requestHeader = new Cache();&lt;br /&gt;&lt;br /&gt;  if(this._IE)&lt;br /&gt;    this._XMLHttp = new ActiveXObject('Microsoft.XMLHttp');&lt;br /&gt;  else&lt;br /&gt;    this._XMLHttp = new XMLHttpRequest();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Property: GET, POST or HEAD&lt;br /&gt;XMLHttpRequest.prototype.action = 'GET';&lt;br /&gt;                                     // Property: true/false&lt;br /&gt;XMLHttpRequest.prototype.asynchronous = true;&lt;br /&gt;                                     // Property: package to send&lt;br /&gt;XMLHttpRequest.prototype.envelope = null&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLHttpRequest&lt;br /&gt;      Function:    XMLHttpRequest_readyState&lt;br /&gt;      Method:      readyState&lt;br /&gt;      Description: Returns the readyState for the XMLHttpRequest&lt;br /&gt;                object.&lt;br /&gt;*/&lt;br /&gt;function XMLHttpRequest_readyState() {&lt;br /&gt;  return(this._XMLHttp.readyState);&lt;br /&gt;}&lt;br /&gt;XMLHttpRequest.prototype.readyState = XMLHttpRequest_readyState;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLHttpRequest&lt;br /&gt;      Function:    XMLHttpRequest_getResponseHeader&lt;br /&gt;      Method:      getResponseHeader&lt;br /&gt;      Description: Returns a single response header from the last&lt;br /&gt;                XMLHttpRequest.&lt;br /&gt;*/&lt;br /&gt;function XMLHttpRequest_getResponseHeader(name) {&lt;br /&gt;  return(this._XMLHttp.getResponseHeader(name));&lt;br /&gt;}&lt;br /&gt;XMLHttpRequest.prototype.getResponseHeader =&lt;br /&gt;XMLHttpRequest_getResponseHeader;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLHttpRequest&lt;br /&gt;      Function:    XMLHttpRequest_getAllResponseHeaders&lt;br /&gt;      Method:      getAllResponseHeaders&lt;br /&gt;      Description: Returns all of the response headers from&lt;br /&gt;                   the last XMLHttpRequest.&lt;br /&gt;*/&lt;br /&gt;function XMLHttpRequest_getAllResponseHeaders() {&lt;br /&gt;  return(this._XMLHttp.getAllResponseHeaders());&lt;br /&gt;}&lt;br /&gt;XMLHttpRequest.prototype.getAllResponseHeaders =&lt;br /&gt;XMLHttpRequest_getAllResponseHeaders;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLHttpRequest&lt;br /&gt;      Function:    XMLHttpRequest_responseText&lt;br /&gt;      Method:      responseText&lt;br /&gt;      Description: Returns the text response from the last&lt;br /&gt;                   XMLHttpRequest.&lt;br /&gt;*/&lt;br /&gt;function XMLHttpRequest_responseText() {&lt;br /&gt;  return(this._XMLHttp.responseText);&lt;br /&gt;}&lt;br /&gt;XMLHttpRequest.prototype.responseText =&lt;br /&gt;XMLHttpRequest_responseText;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLHttpRequest&lt;br /&gt;      Function:    XMLHttpRequest_responseXML&lt;br /&gt;      Method:      responseXML&lt;br /&gt;      Description: Returns the XML DOM document response from&lt;br /&gt;                   the last XMLHttpRequest.&lt;br /&gt;*/&lt;br /&gt;function XMLHttpRequest_responseXML() {&lt;br /&gt;  if(this._IE) {&lt;br /&gt;    var xml =&lt;br /&gt;    new ActiveXObject('MSXML2.FreeThreadedDOMDocument.3.0');&lt;br /&gt;    xml.async = true;&lt;br /&gt;&lt;br /&gt;    xml.loadXML(this._XMLHttp.responseText);&lt;br /&gt;&lt;br /&gt;    return(xml);&lt;br /&gt;  } else&lt;br /&gt;    return(this._XMLHttp.responseXML);&lt;br /&gt;}&lt;br /&gt;XMLHttpRequest.prototype.responseXML =&lt;br /&gt;XMLHttpRequest_responseXML;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLHttpRequest&lt;br /&gt;      Function:    XMLHttpRequest_stateChangeHandler&lt;br /&gt;      Method:      n/a&lt;br /&gt;      Description: Dummy state change handler for&lt;br /&gt;                   asynchronous requests.&lt;br /&gt;*/&lt;br /&gt;function XMLHttpRequest_stateChangeHandler() { }&lt;br /&gt;XMLHttpRequest.prototype.stateChangeHandler =&lt;br /&gt;XMLHttpRequest_stateChangeHandler;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       setRequestHeader&lt;br /&gt;      Function:    XMLHttpRequest_setRequestHeader&lt;br /&gt;      Method:      setRequestHeader&lt;br /&gt;      Description: Inserts to the cache of HTTP request headers.&lt;br /&gt;*/&lt;br /&gt;function XMLHttpRequest_setRequestHeader(name,value) {&lt;br /&gt;  this.removeRequestHeader(name);&lt;br /&gt;  this._requestHeader.insert(name,value);&lt;br /&gt;}&lt;br /&gt;XMLHttpRequest.prototype.setRequestHeader =&lt;br /&gt;XMLHttpRequest_setRequestHeader;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       setRequestHeader&lt;br /&gt;      Function:    XMLHttpRequest_removeRequestHeader&lt;br /&gt;      Method:      n/a&lt;br /&gt;      Description: Removes from the cache of HTTP&lt;br /&gt;                   request headers.&lt;br /&gt;*/&lt;br /&gt;function XMLHttpRequest_removeRequestHeader(name) {&lt;br /&gt;  this._requestHeader.purge(name);&lt;br /&gt;}&lt;br /&gt;XMLHttpRequest.prototype.removeRequestHeader =&lt;br /&gt;XMLHttpRequest_removeRequestHeader;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLHttpRequest&lt;br /&gt;      Function:    XMLHttpRequest_send&lt;br /&gt;      Method:      send&lt;br /&gt;      Description: Sends XMLHttpRequest.&lt;br /&gt;*/&lt;br /&gt;function XMLHttpRequest_send() {&lt;br /&gt;  var successful = false;&lt;br /&gt;&lt;br /&gt;  if(arguments.length != 0)&lt;br /&gt;    this.envelope = arguments[0];&lt;br /&gt;&lt;br /&gt;  switch(this._XMLHttp.readyState) {&lt;br /&gt;    case(4):&lt;br /&gt;    case(0):&lt;br /&gt;      try {&lt;br /&gt;        if(this._IE)&lt;br /&gt;              this._XMLHttp.onreadystatechange =&lt;br /&gt;this.stateChangeHandler;&lt;br /&gt;            else&lt;br /&gt;              this._XMLHttp.stateChangeHandler =&lt;br /&gt;this.XMLHttpRequest_stateChangeHandler;&lt;br /&gt;&lt;br /&gt;        this._XMLHttp.open(this.action,this.uri,this.asynchronous);&lt;br /&gt;&lt;br /&gt;        var names = this._requestHeader.names();&lt;br /&gt;&lt;br /&gt;        for(var i=0;i &lt; names.length;i++)&lt;br /&gt;&lt;br /&gt;this._XMLHttp.setRequestHeader(names[i],this._requestHeader.retrieve(names&lt;br /&gt;[i]));&lt;br /&gt;&lt;br /&gt;        this._XMLHttp.send(this.envelope);&lt;br /&gt;&lt;br /&gt;        successful = true;&lt;br /&gt;      }&lt;br /&gt;      catch(e) { }&lt;br /&gt;&lt;br /&gt;      break;&lt;br /&gt;    default:&lt;br /&gt;&lt;br /&gt;      break;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return(successful);&lt;br /&gt;}&lt;br /&gt;XMLHttpRequest.prototype.send = XMLHttpRequest_send;&lt;br /&gt;// ]]&gt; --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The constructor shown does exactly what the handwritten code from the beginning of Chapter 8, "AJAX Using XML and XMLHttpRequest," does. In a nutshell, it sends an XMLHttpRequest to the server, waits for the response, and then acts upon the response. This is not a big deal; just create an instance, and it takes care of everythingunless, of course, you're paid by the line.&lt;br /&gt;&lt;br /&gt;Now that we've got a constructor to handle the getting of XML, it might be a good idea to figure out a place to put it. What's needed, as if you didn't already know, is a generic XML document object. It doesn't have to be perfect; it only has to workand by "work," I mean offer a single set of properties and methods. From the previous chapters, you're already aware that this is written, so let's take a gander at it in Listing 12-5.&lt;br /&gt;&lt;br /&gt;Listing 12-5. Cross-Browser XML Document Class Constructor&lt;br /&gt;&lt;br /&gt;&lt;!-- &lt;![CDATA[&lt;br /&gt;XMLDocument.prototype = new XMLDocument;&lt;br /&gt;XMLDocument.prototype.constructor = XMLDocument;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLDocument&lt;br /&gt;      Method:      n/a&lt;br /&gt;      Description: Constructor for this class.&lt;br /&gt;*/&lt;br /&gt;function XMLDocument() {&lt;br /&gt;  try {&lt;br /&gt;    var x = new DOMParser();&lt;br /&gt;    this._IE = false;&lt;br /&gt;  }&lt;br /&gt;  catch(e) { this._IE = true; };&lt;br /&gt;  this._XMLHttpRequest = new XMLHttpRequest();&lt;br /&gt;  this._XML;                 // XML DOM document&lt;br /&gt;  this._DOMParser;           // XML DOM parser (Gecko only)&lt;br /&gt;  this._XMLSerializer;       // XML serializer (Gecko only)&lt;br /&gt;  this._state = 0;           // Pseudo readyState&lt;br /&gt;&lt;br /&gt;  if(!this._IE) {&lt;br /&gt;    this._DOMParser = new DOMParser();&lt;br /&gt;    this._XMLSerializer = new XMLSerializer();&lt;br /&gt;&lt;br /&gt;    this._XML =&lt;br /&gt;    document.implementation.createDocument("", "", null);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLDocument_load&lt;br /&gt;      Method:      load&lt;br /&gt;      Description: Loads the specified XML document.&lt;br /&gt;*/&lt;br /&gt;function XMLDocument_load(xml) {&lt;br /&gt;  var isXMLText = false;&lt;br /&gt;  var isXMLDocument = (typeof(xml) == 'object');&lt;br /&gt;&lt;br /&gt;  try {                              // Test for elements&lt;br /&gt;    isXMLText = (new RegExp('&lt;','g')).test(xml);&lt;br /&gt;}&lt;br /&gt;catch(e) { }&lt;br /&gt;&lt;br /&gt;switch(true) {&lt;br /&gt;  case(this._IE &amp;&amp; isXMLText):     // Internet Explorer &amp; text&lt;br /&gt;    this._XML =&lt;br /&gt;    new ActiveXObject('MSXML2.FreeThreadedDOMDocument.3.0');&lt;br /&gt;&lt;br /&gt;    this._XML.async = true;&lt;br /&gt;&lt;br /&gt;    this._XML.loadXML(xml);&lt;br /&gt;    this._state = 4;               // Ready state complete&lt;br /&gt;&lt;br /&gt;    break;&lt;br /&gt;  case(!this._IE &amp;&amp; isXMLText):    // Not IE &amp; text&lt;br /&gt;    this._XML =&lt;br /&gt;    this._DOMParser.parseFromString(xml,"text/xml");&lt;br /&gt;    this._state = 4;                // Ready state is complete&lt;br /&gt;&lt;br /&gt;    break;&lt;br /&gt;  case(this._IE &amp;&amp; isXMLDocument):&lt;br /&gt;  // Internet Explorer &amp; XML DOM&lt;br /&gt;    this._XML =&lt;br /&gt;    new ActiveXObject('MSXML2.FreeThreadedDOMDocument.3.0');&lt;br /&gt;&lt;br /&gt;    this._XML.async = true;&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;      this._XML.loadXML(xml.serialize());&lt;br /&gt;    }&lt;br /&gt;    catch(e) {&lt;br /&gt;      this._XML = xml;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    this._state = 4;                // Ready state complete&lt;br /&gt;&lt;br /&gt;    break;&lt;br /&gt;  case(!this._IE &amp;&amp; isXMLDocument): // Not IE &amp; XML DOM&lt;br /&gt;    try {&lt;br /&gt;      this._XML = xml.DOMDocument();&lt;br /&gt;    }&lt;br /&gt;    catch(e) {&lt;br /&gt;      this._XML = xml;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    this._state = 4;                // Ready state is complete&lt;br /&gt;&lt;br /&gt;    break;&lt;br /&gt;  default:&lt;br /&gt;    this._XMLHttpRequest.uri = xml;&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;        this._XMLHttpRequest.send();&lt;br /&gt;&lt;br /&gt;        this._state = 1;&lt;br /&gt;      }&lt;br /&gt;      catch(e) {&lt;br /&gt;        if(this._IE) {&lt;br /&gt;          this._XML =&lt;br /&gt;          new ActiveXObject('MSXML2.FreeThreadedDOMDocument.3.0');&lt;br /&gt;&lt;br /&gt;          this._XML.async = true;&lt;br /&gt;        } else&lt;br /&gt;          this._XML =&lt;br /&gt;          this._DOMParser.parseFromString(' ','text/xml');&lt;br /&gt;&lt;br /&gt;        this._state = 4;             // Error - force complete&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if(this._state == 4)&lt;br /&gt;    this._XMLHttpRequest = new XMLHttpRequest();&lt;br /&gt;}&lt;br /&gt;XMLDocument.prototype.load = XMLDocument_load;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLDocument_serialize&lt;br /&gt;      Method:      serialize&lt;br /&gt;      Description: Returns the result of the prior transformation&lt;br /&gt;                   as a serialize XML DOM document (text).&lt;br /&gt;*/&lt;br /&gt;function XMLDocument_serialize() {&lt;br /&gt;  try {&lt;br /&gt;    if(this.readyState() == 4) {&lt;br /&gt;&lt;br /&gt;      if(this._XMLHttpRequest.readyState() == 4)&lt;br /&gt;        this.load(this._XMLHttpRequest.responseXML());&lt;br /&gt;&lt;br /&gt;      if(this._IE)&lt;br /&gt;        return(this._XML.xml)&lt;br /&gt;      else&lt;br /&gt;        return(this._XMLSerializer.serializeToString(this._XML));&lt;br /&gt;    } else&lt;br /&gt;      return(null);                  // Not loaded&lt;br /&gt;  }&lt;br /&gt;  catch(e) {&lt;br /&gt;    return(null);                    // Invalid document&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;XMLDocument.prototype.serialize = XMLDocument_serialize;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLDocument_DOMDocument&lt;br /&gt;      Method:      DOMDocument&lt;br /&gt;      Description: Returns the result of the prior transformation&lt;br /&gt;                   as a Browser-native XML DOM document.&lt;br /&gt;*/&lt;br /&gt;function XMLDocument_DOMDocument() {&lt;br /&gt;  try {&lt;br /&gt;    if(this.readyState() == 4) {&lt;br /&gt;      if(this._XMLHttpRequest.readyState() == 4)&lt;br /&gt;        this.load(this._XMLHttpRequest.responseXML());&lt;br /&gt;&lt;br /&gt;        return(this._XML);&lt;br /&gt;    } else&lt;br /&gt;      return(null);                  // Document not loaded&lt;br /&gt;  }&lt;br /&gt;  catch(e) {&lt;br /&gt;    return(null);                    // Invalid document&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;XMLDocument.prototype.DOMDocument = XMLDocument_DOMDocument;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLDocument_readyState&lt;br /&gt;      Method:      readyState&lt;br /&gt;      Description: Returns the readyState for the XML document.&lt;br /&gt;*/&lt;br /&gt;function XMLDocument_readyState() {&lt;br /&gt;if(this._XMLHttpRequest.readyState() == 0)&lt;br /&gt;  return(4);&lt;br /&gt;else&lt;br /&gt;  return(this._XMLHttpRequest.readyState());&lt;br /&gt;}&lt;br /&gt;XMLDocument.prototype.readyState = XMLDocument_readyState;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLHttpRequest_setRequestHeader&lt;br /&gt;      Method:      n/a&lt;br /&gt;      Description: Inserts to the cache of HTTP request headers.&lt;br /&gt;*/&lt;br /&gt;function XMLDocument_setRequestHeader(name,value) {&lt;br /&gt;      this._XMLHttpRequest.setRequestHeader(name,value);&lt;br /&gt;}&lt;br /&gt;XMLDocument.prototype.setRequestHeader =&lt;br /&gt;XMLDocument_setRequestHeader;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLDocument_getResponseHeader&lt;br /&gt;      Method:      getResponseHeader&lt;br /&gt;      Description: Returns a single response header from the last&lt;br /&gt;                XMLHttpRequest.&lt;br /&gt;*/&lt;br /&gt;function XMLDocument_getResponseHeader(name) {&lt;br /&gt;  return(this._XMLHttpRequest.getResponseHeader(name));&lt;br /&gt;}&lt;br /&gt;XMLDocument.prototype.getResponseHeader =&lt;br /&gt;XMLDocument_getResponseHeader;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLDocument_getAllResponseHeaders&lt;br /&gt;      Method:      getAllResponseHeaders&lt;br /&gt;      Description: Returns all of the response headers from&lt;br /&gt;                   the last XMLHttpRequest.&lt;br /&gt;*/&lt;br /&gt;function XMLDocument_getAllResponseHeaders() {&lt;br /&gt;  return(this._XMLHttpRequest.getAllResponseHeaders());&lt;br /&gt;}&lt;br /&gt;XMLDocument.prototype.getAllResponseHeaders =&lt;br /&gt;XMLDocument_getAllResponseHeaders;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLDocument_setEnvelope&lt;br /&gt;      Method:      setEnvelope&lt;br /&gt;      Description: Sets the envelope for an XMLHttpRequest.&lt;br /&gt;*/&lt;br /&gt;function XMLDocument_setEnvelope(value) {&lt;br /&gt;  this._XMLHttpRequest.envelope = value;&lt;br /&gt;  this._XMLHttpRequest.action = 'POST';&lt;br /&gt;}&lt;br /&gt;XMLDocument.prototype.setEnvelope = XMLDocument_setEnvelope;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLDocument_selectNodes&lt;br /&gt;      Method:      selectNodes&lt;br /&gt;      Description: Returns an array of XMLDocument based upon&lt;br /&gt;                   an XPath statement.&lt;br /&gt;*/&lt;br /&gt;function XMLDocument_selectNodes(xpath) {&lt;br /&gt;  var results;&lt;br /&gt;  var resultArray = new Array();     // XML Document result array&lt;br /&gt;&lt;br /&gt;  if(this.readyState() == 4)&lt;br /&gt;    if(this._XMLHttpRequest.readyState() == 4)&lt;br /&gt;      this.load(this._XMLHttpRequest.responseXML());&lt;br /&gt;&lt;br /&gt;  if(_IE) {&lt;br /&gt;    results = this._XML.selectNodes(xpath);&lt;br /&gt;    for(var i=0;i &lt; results.length;i++) {&lt;br /&gt;      resultArray.push(new XMLDocument());&lt;br /&gt;      resultArray[i].load(results[i].xml);&lt;br /&gt;    }&lt;br /&gt;  } else {                           // XPath evaluator&lt;br /&gt;    var evaluator = new XPathEvaluator();&lt;br /&gt;    var resolver =&lt;br /&gt;evaluator.createNSResolver(this._XML.documentElement);&lt;br /&gt;    var result;                      // Single XPath result&lt;br /&gt;    var xml;&lt;br /&gt;    var i = 0;                       // Counter&lt;br /&gt;&lt;br /&gt;    results =&lt;br /&gt;evaluator.evaluate(xpath,this._XML,resolver,XPathResult.ANY_TYPE,null);&lt;br /&gt;&lt;br /&gt;    while(result = results.iterateNext()) {&lt;br /&gt;      xml = document.implementation.createDocument("", "",null);&lt;br /&gt;&lt;br /&gt;      xml.appendChild(xml.importNode(result,true));&lt;br /&gt;      resultArray.push(new XMLDocument());&lt;br /&gt;      resultArray[i].load(this._XMLSerializer.serializeToString(xml));&lt;br /&gt;&lt;br /&gt;      ++i;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return(resultArray);&lt;br /&gt;}&lt;br /&gt;XMLDocument.prototype.selectNodes = XMLDocument_selectNodes;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XMLDocument&lt;br /&gt;      Function:    XMLDocument_selectSingleNode&lt;br /&gt;      Method:      selectSingleNode&lt;br /&gt;      Description: Returns a single XML document based upon an&lt;br /&gt;                   XPath statement.&lt;br /&gt;*/&lt;br /&gt;function XMLDocument_selectSingleNode(xpath) {&lt;br /&gt;  return(this.selectNodes(xpath)[0]);&lt;br /&gt;}&lt;br /&gt;XMLDocument.prototype.selectSingleNode =&lt;br /&gt;XMLDocument_selectSingleNode;&lt;br /&gt;// ]]&gt; --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now that there is a generic constructor for XML documents and a constructor for the XSLT Request object, the next task is to ask the nice web service for an XML document. To do this, a quick and easy way of producing a SOAP envelope is required. In writing this constructor, I learned something about SOAP that I hadn't realized in the past: SOAP is, in some ways, like a car. With a car, there is a base model, and, regardless of the options, the base model remains the same. Oh, sure, some cars have better sound systems and some have bigger engines, but underneath all the little extras, the cars are essentially the same. Take my car, for example; with the exception of the dirt and the dent on the hood from a flower pot, when you get past the options, it is just like the other car from that model year.&lt;br /&gt;&lt;br /&gt;This same approach was used when writing the SOAPEnvelope constructor. A basic template serves as a starting point, and all of the other options are then added on. These options consist of things such as the operator, content, and namespaceall required, but very often different from request to request. Listing 12-6 shows the inner workings of this constructor.&lt;br /&gt;&lt;br /&gt;Listing 12-6. Cross-Browser SOAPEnvelope Class Constructor That Uses Regular Expressions&lt;br /&gt;&lt;br /&gt;&lt;!-- &lt;![CDATA[&lt;br /&gt;SOAPEnvelope.prototype = new SOAPEnvelope;&lt;br /&gt;SOAPEnvelope.prototype.constructor = SOAPEnvelope;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       SOAPEnvelope&lt;br /&gt;      Function:    SOAPEnvelope&lt;br /&gt;      Method:      n/a&lt;br /&gt;      Description: Constructor for this class.&lt;br /&gt;*/&lt;br /&gt;&lt;!-- &lt;![CDATA[&lt;br /&gt;function SOAPEnvelope() {&lt;br /&gt;  this._template = '&lt;?xml version="1.0" encoding="utf-8"?&gt;';&lt;br /&gt;&lt;br /&gt;  this._template += '&lt;soap:Envelope&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xmlns:xsd="http://www.w3.org/2001/XMLSchema"&lt;br /&gt;xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;';&lt;br /&gt;  this._template += '&lt;soap:Body&gt;';&lt;br /&gt;  this._template += '&lt;_operator xmlns="_namespace"&gt;';&lt;br /&gt;  this._template += '_package';&lt;br /&gt;  this._template += '&lt;/_operator&gt;';&lt;br /&gt;  this._template += '&lt;/soap:Body&gt;';&lt;br /&gt;  this._template += '&lt;/soap:Envelope&gt;';&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;SOAPEnvelope.prototype.operator = null;&lt;br /&gt;SOAPEnvelope.prototype.namespace = 'http://tempuri.org/';&lt;br /&gt;SOAPEnvelope.prototype.content = null;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       SOAPEnvelope&lt;br /&gt;      Function:    SOAPEnvelope_envelope&lt;br /&gt;      Method:      envelope&lt;br /&gt;      Description: Returns the readyState for the XMLHttpRequest&lt;br /&gt;                object.&lt;br /&gt;*/&lt;br /&gt;function SOAPEnvelope_envelope() {&lt;br /&gt;  var work;&lt;br /&gt;&lt;br /&gt;  work = this._template.replace(/_operator/g,this.operator);&lt;br /&gt;  work = work.replace(/_namespace/g,this.namespace);&lt;br /&gt;  work = work.replace(/_package/g,this.content);&lt;br /&gt;&lt;br /&gt;  return(work);&lt;br /&gt;}&lt;br /&gt;SOAPEnvelope.prototype.envelope = SOAPEnvelope_envelope;&lt;br /&gt;// ]]&gt; --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;12.2.3. XSLT&lt;br /&gt;The final constructor that was used in the examples was the XSLTProcessor constructor, which serves as the poster child for code reuse. It has two instances of XMLDocument objects, one for the XML document and one for the XSL style sheet. It also serves fairly well to show some of the difference between Gecko-based browsers such as Firefox, Mozilla, and Netscape, and Microsoft Internet Explorer.&lt;br /&gt;&lt;br /&gt;These differences range from Internet Explorer needing a template to create a processor to something as simple as Firefox needing a serializer to obtain the text representation of an XML document. Listing 12-7 shows the constructor for the XSLTProcessor.&lt;br /&gt;&lt;br /&gt;Listing 12-7. Cross-Browser XSLTProcessor Class, Used for Transformations&lt;br /&gt;&lt;br /&gt;&lt;!-- &lt;![CDATA[&lt;br /&gt;XsltProcessor.prototype = new XsltProcessor;&lt;br /&gt;XsltProcessor.prototype.constructor = XsltProcessor;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XsltProcessor&lt;br /&gt;      Function:    XsltProcessor&lt;br /&gt;      Method:      n/a&lt;br /&gt;      Description: Constructor for this class.&lt;br /&gt;*/&lt;br /&gt;function XsltProcessor() {&lt;br /&gt;  try {&lt;br /&gt;    var x = new DOMParser();&lt;br /&gt;    this._IE = false;&lt;br /&gt;  }&lt;br /&gt;  catch(e) { this._IE = true; };&lt;br /&gt;  this._xsl = new XMLDocument(); // Input XSL style sheet&lt;br /&gt;  this._xml = new XMLDocument(); // Input XML document&lt;br /&gt;  this._output;                  // Output (text)&lt;br /&gt;  this._XMLSerializer;           // XML serializer (Gecko only)&lt;br /&gt;  this._XSLTemplate;             // XSLT template (IE only)&lt;br /&gt;  this._XsltProcessor;           // XSLT processor&lt;br /&gt;&lt;br /&gt;  if(!this._IE)&lt;br /&gt;    this._XMLSerializer = new XMLSerializer();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XsltProcessor&lt;br /&gt;      Function:    XsltProcessor_initialize&lt;br /&gt;      Method:      _initialize&lt;br /&gt;      Description: Initializes/re-initializes the XSLT processor.&lt;br /&gt;*/&lt;br /&gt;function XsltProcessor_initialize() {&lt;br /&gt;  if(this._IE) {&lt;br /&gt;    this._XSLTemplate =&lt;br /&gt;    new ActiveXObject('MSXML2.XSLTemplate.3.0');&lt;br /&gt;&lt;br /&gt;    this._XSLTemplate.stylesheet = this._xsl.DOMDocument();&lt;br /&gt;&lt;br /&gt;    this._XsltProcessor = this._XSLTemplate.createProcessor;&lt;br /&gt;  } else&lt;br /&gt;    this._XsltProcessor = new XSLTProcessor();&lt;br /&gt;}&lt;br /&gt;XsltProcessor.prototype._initialize = XsltProcessor_initialize;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XsltProcessor&lt;br /&gt;      Function:    XsltProcessor_setParameter&lt;br /&gt;      Method:      setParameter&lt;br /&gt;      Description: Inserts an XSLT parameter to the parameter&lt;br /&gt;                   cache.&lt;br /&gt;*/&lt;br /&gt;function XsltProcessor_setParameter(name,value) {&lt;br /&gt;  try {&lt;br /&gt;    if(this._IE)&lt;br /&gt;      this._XsltProcessor.addParameter(name,value);&lt;br /&gt;    else&lt;br /&gt;      this._XsltProcessor.setParameter(null,name,value);&lt;br /&gt;  }&lt;br /&gt;  catch(e) {&lt;br /&gt;    this._initialize();&lt;br /&gt;    this.setParameter(name,value);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;XsltProcessor.prototype.setParameter =&lt;br /&gt;XsltProcessor_setParameter;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XsltProcessor&lt;br /&gt;      Function:    XsltProcessor_load&lt;br /&gt;      Method:      load&lt;br /&gt;      Description: Loads the XML document to be transformed.&lt;br /&gt;*/&lt;br /&gt;function XsltProcessor_load(xml) {&lt;br /&gt;  try {&lt;br /&gt;    this._xml.load(xml);&lt;br /&gt;  }&lt;br /&gt;  catch(e) {&lt;br /&gt;    this._initialize();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;XsltProcessor.prototype.load = XsltProcessor_load;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XsltProcessor&lt;br /&gt;      Function:    XsltProcessor_importStylesheet&lt;br /&gt;      Method:      importStylesheet&lt;br /&gt;      Description: Loads the XSL style sheet for the&lt;br /&gt;                   transformation.&lt;br /&gt;*/&lt;br /&gt;function XsltProcessor_importStylesheet(xsl) {&lt;br /&gt;  try {&lt;br /&gt;    this._xsl.load(xsl);&lt;br /&gt;  }&lt;br /&gt;  catch(e) {&lt;br /&gt;    this._initialize();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;XsltProcessor.prototype.importStylesheet =&lt;br /&gt;XsltProcessor_importStylesheet;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XsltProcessor&lt;br /&gt;      Function:    XsltProcessor_readyState&lt;br /&gt;      Method:      readyState&lt;br /&gt;      Description: Returns the readyState for a combination of&lt;br /&gt;                   the XML document and the XSL style sheet.&lt;br /&gt;*/&lt;br /&gt;function XsltProcessor_readyState() {&lt;br /&gt;  switch(true) {&lt;br /&gt;    case((this._xsl.readyState() == 0) &amp;&amp; (this._xsl.readyState() == 0)):&lt;br /&gt;      return(this._xsl.readyState());&lt;br /&gt;&lt;br /&gt;      break;&lt;br /&gt;    case((this._xsl.readyState() &gt; 0) &amp;&amp; (this._xsl.readyState() &lt; 4)):&lt;br /&gt;      return(this._xsl.readyState());&lt;br /&gt;&lt;br /&gt;      break;&lt;br /&gt;    case((this._xml.readyState() &gt; 0) &amp;&amp; (this._xml.readyState() &lt; 4)):&lt;br /&gt;      return(this._xml.readyState());&lt;br /&gt;&lt;br /&gt;      break;&lt;br /&gt;    default:&lt;br /&gt;      return(4);&lt;br /&gt;&lt;br /&gt;      break;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;XsltProcessor.prototype.readyState = XsltProcessor_readyState;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XsltProcessor&lt;br /&gt;      Function:    XsltProcessor_transform&lt;br /&gt;      Method:      transform&lt;br /&gt;      Description: Performs the XSL transformation using the&lt;br /&gt;                   supplied XML document and XSL style sheet.&lt;br /&gt;                   Returns the result as an XML document.&lt;br /&gt;*/&lt;br /&gt;function XsltProcessor_transform() {&lt;br /&gt;  if(this._IE) {&lt;br /&gt;    this._XsltProcessor.input = this._xml.DOMDocument();&lt;br /&gt;&lt;br /&gt;    this._XsltProcessor.transform();&lt;br /&gt;&lt;br /&gt;    this._output = this._XsltProcessor.output;&lt;br /&gt;  } else {&lt;br /&gt;    this._XsltProcessor.importStylesheet(this._xsl.DOMDocument());&lt;br /&gt;&lt;br /&gt;    this._output =&lt;br /&gt;this._XMLSerializer.serializeToString(this._XsltProcessor.transformToDocum&lt;br /&gt;ent(this._xml.DOMDocument(),document));&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  this._initialize();&lt;br /&gt;&lt;br /&gt;  return(this._output);&lt;br /&gt;}&lt;br /&gt;XsltProcessor.prototype.transform = XsltProcessor_transform;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;      Class:       XsltProcessor&lt;br /&gt;      Function:    XsltProcessor_serialize&lt;br /&gt;      Method:      serialize&lt;br /&gt;      Description: Returns the result of the prior transformation&lt;br /&gt;                   as a serialize XML document (text).&lt;br /&gt;*/&lt;br /&gt;function XsltProcessor_serialize() {&lt;br /&gt;  return(this._output);&lt;br /&gt;}&lt;br /&gt;XsltProcessor.prototype.serialize = XsltProcessor_serialize;&lt;br /&gt;// ]]&gt; --&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;12.2.4. Serialization Without Berries&lt;br /&gt;One common item that you'll notice throughout each of the previous constructors is that serialization plays a big part in handling XML. Several reasons account for this, the first being that XML was designed to be human readable, and humans read text, not binary. For example, when was the last time you heard, "ASCII 65, uppercase 'A'"? I'm the one who was called a mad scientist, and I don't deal with that stuff, so I can't imagine the more mundane members of humanity doing things like that.&lt;br /&gt;&lt;br /&gt;The second reason for serialization is the underlying architecture of the web, the Hypertext Transfer Protocol, or HTTP, for short. The HTML, XHTML, JavaScript, CSS, XML, and XSL travel back and forth from the server to the client as text. Without serialization, all of the "X-stuff," as an old supervisor of mine put it, wouldn't be going anywhere.&lt;br /&gt;&lt;br /&gt;Another reason for serialization is that, unlike an XML object, very little overhead is associated with text. An XML DOM document requires between three and ten times the memory of the equivalent text document. This overhead could cause some issues in the client's browser on older machines. Of course, the issue of overhead has to be weighted against parsing the text to load a document.&lt;br /&gt;&lt;br /&gt;My final reason for serialization is that it is just so easy to load an XML document from a text document. In Microsoft Internet Explorer, it is simply a matter of using the loadXML method. With Firefox, a little more work is necessary, but not too much. Just use the DOMParser's parseFromString method and reconstituted XML, just like freeze-dried coffee or freeze-dried minions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-4970276547193105221?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/4970276547193105221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/12.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4970276547193105221'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4970276547193105221'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/12.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-4751539034763158513</id><published>2008-12-13T11:12:00.001-08:00</published><updated>2009-01-26T12:33:17.866-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'>Chapter 13. Traveling with Ruby on Rails</title><content type='html'>Mention the subject of Ajax, and within five minutes somebody will bring up Ruby on Rails. Just as with Ajax, Ruby on Rails has become a winning phrase in corporate buzzword bingo. It is kind of sad that both topics have been relegated to buzzwords, with managers wielding them interchangeably, like they're some kind of weapons. Unfortunately, managers are just as likely to hurt themselves as somebody else, which just goes to show that it is a good idea to know what the tools are before attempting to use them.&lt;br /&gt;&lt;br /&gt;In this chapter, we cover some of the history of Ruby on Rails, followed by what it is and how to install it on a system running Windows XP. From there, we examine how to start developing, using Ruby on Rails, and how to solve a simple problem using it.&lt;br /&gt;&lt;br /&gt;Unfortunately, it is beyond the scope of this book to do more than introduce Ruby on Rails. There is actually a logical reason for this, beyond the fact that I'm more of a JavaScript guy than a Ruby guy. The reason for this is college.&lt;br /&gt;&lt;br /&gt;Huh?&lt;br /&gt;&lt;br /&gt;When I was in college, some students, well, complained about how the professors taught. The problem is that the professors didn't give them the code required for every assignment. We were taught, for example, how to create a data structure, but not the particular data structure for Question 6 on the midterm. The professors pointed us in a direction and expected us to reach the destination on our own. Gee, the nerve of those professorsthey pointed us in a particular direction and expected us to find the way ourselves.&lt;br /&gt;&lt;br /&gt;Seriously, this is merely an example, not the answer to Question 6. So if you choose to seriously examine Ruby on Rails, allow me to point the way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-4751539034763158513?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/4751539034763158513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-13-traveling-with-ruby-on-rails.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4751539034763158513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4751539034763158513'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-13-traveling-with-ruby-on-rails.html' title='Chapter 13. Traveling with Ruby on Rails'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-3190973573698349547</id><published>2008-12-13T11:11:00.000-08:00</published><updated>2009-01-26T12:33:17.866-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>13.1. What Is Ruby on Rails?&lt;br /&gt;A single word in the English language, in my opinion, sums up what Ruby on Rails is: synergy. Just in case you're unaware of the meaning of the word synergy, it roughly means that the whole is greater than the sum of its parts. Need a few examples of synergy? How about chocolate and peanut butter? Individually, either ingredient is good, but put them together and, well, yum!&lt;br /&gt;&lt;br /&gt;With Ruby on Rails, instead of chocolate and peanut butter, there is Ruby and Rails. This realization leads me to two additional questions. The first is "Beyond being a deep-red corundum crystal, just what is Ruby?" There is, after all one thing that I am certain of, and it is that Ruby is a language and not a mineral, although it is possible to create a laser using a ruby, and lasers are the meat and potatoes of most mad scientists.&lt;br /&gt;&lt;br /&gt;13.1.1. Ruby&lt;br /&gt;The Ruby that is referred to in this chapter is an object-oriented programming language created by Yukihiro Matsumoto of Japan in 1993. In Japan, not surprisingly, Ruby quickly became quite popular, with home-field advantage and all that kind of stuff. However, because of its price tag of zero (it is, after all, an open source language), Ruby began to catch on outside of Japan. Yes, against all odds, Ruby become something of a phenomenon.&lt;br /&gt;&lt;br /&gt;Although some might consider it odd that an open source language from a land far away from our little piece of the universe planted the seed of the idea of Ajax, I do not. I, for one, am open to ideas, regardless of the source. Alright, I'm a little more open to the ideas that relate to food, but, then, I'm one of those developers who eats anything that doesn't try to eat me first.&lt;br /&gt;&lt;br /&gt;The interesting thing is that, even with people like me, mad scientists without enough time who like sushi and green tea ice cream, Ruby's popularity was growing only slowlyfaster than a bonsai tree, but slower than Godzilla, Pokemon, or Yu-gi-oh. Fortunately, something changed back in 2004. No, radiation was not involved, but what happened is that Ruby got Rails.&lt;br /&gt;&lt;br /&gt;13.1.2. Ruby on Rails&lt;br /&gt;The word Rails is rather interesting; it brings up connotations of a sleek, silent, fast electric train moving into the future. That's a pretty nice connotation, especially when tied to web development, which, in my opinion, more often resembles a runaway steam train with no brakes on a downgrade, going into a hairpin curve during a snowstorm on Monday. In short, the average project is an accident waiting to happen. The accident might never happen, but the potential is there regardless. Rails is a full-stack programming framework implemented in Ruby whose purpose is to smooth the development of web applications.&lt;br /&gt;&lt;br /&gt;Created by a Danish college student, David Heinemeier Hansson, Rails is open source and is based upon two simple principles. The first is that fewer lines of code equal fewer coding errors. This is a sensible idea because smaller, tighter code requires less time to write and debug. This remaining time could then be put toward testing or toward the inevitable feature creep that rises like a monster from a slab.&lt;br /&gt;&lt;br /&gt;The second principle of Rails is configuration. Unlike many environments, Rails doesn't use configuration files. Instead, Rails uses information in application code itself to determine its configuration. This eliminates the "Doh!" factor that occurs whenever an application is moved to another environment, even when the environment is merely another developer's laptop. Although I can't speak for anyone else, I do know from personal experience that configuration files are one of those things that fall through the cracks about 20 percent of the time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-3190973573698349547?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/3190973573698349547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/13_7736.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/3190973573698349547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/3190973573698349547'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/13_7736.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1846822410908193298</id><published>2008-12-13T11:08:00.000-08:00</published><updated>2009-01-26T12:33:17.866-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>13.2. Installation&lt;br /&gt;This entire preamble leads to the two important questions of where to get Ruby and where to get Rails. That's easy. A simple Google search for "ruby rails" is enough to answer both questions simultaneously. I do recommend a single search instead of individual searches, unless, of course, you are also interested in jewelry and traveling by train.&lt;br /&gt;&lt;br /&gt;The process of installing Ruby is dependent upon which operating system your machine is running. For wimps like me who happen to be running Windows XP Professional, listening to Jethro Tull, and writing a book, installation is simply a matter of downloading an .exe and double-clicking it to get the ball rolling. It installs just like the shrink-wrapped software that you purchase, minus the autorun CD and price tag, as Figures 13-1 and 13-2 show.&lt;br /&gt;If the lack of an autorun CD makes you nervous, then, by all means, create your own autorun CD. However, if the lack of a price tag makes you nervous, I recommend that you buy a second copy of this book and give it to a friend as a gift. In this manner, you've got a bill and you've also given the nice people at Prentice Hall a reason to send me a check. In short, everyone is happy all around.&lt;br /&gt;&lt;br /&gt;In a Windows environment, the installation of Ruby on Rails requires a couple additional steps. The first of these steps is to install Rails itself. If you have an Internet connection, this is just a single line; it is at the command prompt, but, nevertheless, it is a single line (see Figure 13-3).&lt;br /&gt;However, if you are a real web developer and not a quiche-eating Windows user, installation will be a little more complex. Don't worry, it isn't a "Windows is superior" thingin fact, it is more of a "Windows has training wheels" thing. Now that I've thoroughly confused you, the fact is that the RubyGems package manager is part of the Windows installer, which isn't the case with Linux. However, because Linux isn't a stagnant environment, I recommend checking the Ruby website for the latest installation procedures.&lt;br /&gt;&lt;br /&gt;Now that you've (hopefully), installed Ruby and Rails, it is time to kick the steel wheels (ouch) and take it out for a little spin. Woo-hoo!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;13.3. A Little Ruby on Rails Warm-Up&lt;br /&gt;As stated previously, Ruby is the object-oriented programming language, and Rails is the framework used to develop applications. Let's say, for example, that I want to create a mad scientist application using Ruby on Rails. The steps would be something like the following:&lt;br /&gt;1.  If it doesn't exist, create a folder/directory to hold each of my Ruby on Rails applications. In this example, I created a folder called rails on my C: drive.&lt;br /&gt;2.  Using the command prompt, enter cd rails. This changes the current directory to C:\rails.&lt;br /&gt;3.  Create an empty web application by running the command rails madscientist, as shown in Figure 13-4.&lt;br /&gt;4.  Start the web server WEBrick, which is included with Ruby, as shown in Figure 13-5.&lt;br /&gt;5.  Check out what is out on the web server in the browser of your choice (see Figure 13-6).&lt;br /&gt;6.  Now is a good time to type Ctrl+C in the command prompt window to shut down WEBrick, as shown in Figure 13-7, before falling back and regrouping. Well, we're only partway there; in fact, we should consider ourselves lucky that there is anything at all to show. Satisfied? Neither am I, so to progress further, we need to understand where things go in a Rails application.&lt;br /&gt;&lt;br /&gt;The rails madscientist command created a number of folders and files that perform various functions. Take, for example, the database.yml file in the config folder; its purpose is to provide the application with details regarding the database to be used by the application. This is an example of the Rails "place for everything and everything in its place" approach. Personally, I wish this idea was more widespread. It would have gotten me out of some embarrassing moments in the past.&lt;br /&gt;&lt;br /&gt;Another folder that is of interest is the public folder. Along with its three child folders, images, javascripts, and stylesheets, it provides a standard location for stashing the aforementioned. In most other environments, locating these types of files is more akin to a treasure hunt than web development.&lt;br /&gt;&lt;br /&gt;The final folders that I'll cover are the app folder, along with the child folders called: controllers, helpers, models, and views. Still feel like you're in the dark? Give me a moment to illuminate. The first directory, controllers, contains classes that handle web requests from the visitor. The helpers directory holds helper classes, which are used by other classes, such as controller classes. Model classes, contained in the models subdirectory, are used to wrap the data stored in a database. Personally, I think that this is where application development can get really messy and often goes wrong. Finally, there is the views subdirectory, which holds the views. Views are the templates that are converted to HTML and returned to the visitor's web browsers.&lt;br /&gt;&lt;br /&gt;Although at first glance it might seem that the application is spread around a bit, that really isn't the case. Instead of the normal "I know it is around here somewhere" approach usually associated with web development, Rails provides a consistent location for each class. If only this approach could be applied to the real world, I would spend a lot less time looking for my watch.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1846822410908193298?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1846822410908193298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/13_3617.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1846822410908193298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1846822410908193298'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/13_3617.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5506803345268956487</id><published>2008-12-13T11:05:00.000-08:00</published><updated>2009-01-26T12:33:17.866-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>13.4. A Problem Revisited&lt;br /&gt;Now that I've got some kind of idea (yeah, right) of what I'm doing with Ruby on Rails, the next question is how to use it in an application. The first task is to identify exactly what I want to do. For example, let's say that I want to display the items contained in the item table. The first necessary task is to generate a data model using the command console, as shown in Figure 13-8.&lt;br /&gt;The next step is to update the database.yml in the config directory to use the MySQL database from the previous chapters. The following is a snippet of the necessary code.&lt;br /&gt;&lt;br /&gt;development:&lt;br /&gt;  adapter: mysql&lt;br /&gt;  host: localhost&lt;br /&gt;  database: ajax&lt;br /&gt;  username: root&lt;br /&gt;  password: wyvern&lt;br /&gt;&lt;br /&gt;1.  Generate a controller for the item data model (see Figure 13-9). &lt;br /&gt;&lt;br /&gt;These are the subsequent steps:&lt;br /&gt;2.  Add a single line to the generated controller (See Listing 13-1). &lt;br /&gt;Listing 13-1. &lt;br /&gt;class ItemController &lt; ApplicationController&lt;br /&gt;  scaffold :item&lt;br /&gt;end&lt;br /&gt;3.  Fire up WEBrick to see what happens (see Figure 13-10).&lt;br /&gt; Hmm, not exactly what I expected. It seems that Rails changed the table name item to items. Not good. Being among the lazy, I decided to go into the MySQL Query Browser and change the table name from item to items (see Figure 13-11) and try again (see Figure 13-12).&lt;br /&gt;That is a little closer to what I am looking for. The trick is that, by default, Rails generates a query assuming that item is the row and items is the table. This isn't a big deal; it is just something to keep in mind when creating tables and using the defaults.&lt;br /&gt;&lt;br /&gt;But what if you don't want to use the stuff generated by default, and where does Ajax fit into things?&lt;br /&gt;&lt;br /&gt;The answer to the first question is simple enough: Just generate a scaffold, as Figure 13-13 shows.&lt;br /&gt;It is then necessary to add the logic to the controller, the view, the layout, and the various templates.&lt;br /&gt;&lt;br /&gt;This leaves only one question unanswered: Ajax? Remember the javascripts folder under the public folder? Well, in there is a file named prototypes.js that has all the logic required for asynchronous JavaScript and XML in Ruby on Rails. If you're interested, I'll offer a hint: Look at the xml_http_request? method. There's a lot to it, and I recommend playing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5506803345268956487?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5506803345268956487/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/13_13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5506803345268956487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5506803345268956487'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/13_13.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-2604800971196750999</id><published>2008-12-13T11:04:00.002-08:00</published><updated>2009-01-26T12:33:17.867-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>13.5. Whither Ajax?&lt;br /&gt;Considering the number of goodies built into the Rails API, finding exactly where the Ajax functionality is hidden could take a little work. However, because I'm really crumby at keeping secrets, I'll spill the beans; everything that we're interested in is in the JavaScriptHelper module, as Table 13-1 shows.&lt;br /&gt;&lt;br /&gt;Table 13-1. JavaScriptHelper Methods Method&lt;br /&gt; Description&lt;br /&gt; &lt;br /&gt;define_javascript_functions()&lt;br /&gt; Includes all the JavaScriptHelper's JavaScript functions in the page.&lt;br /&gt; &lt;br /&gt;draggable_element (element_id, options = {})&lt;br /&gt; Makes the element with the corresponding ID draggable.&lt;br /&gt; &lt;br /&gt;drop_receiving_element (element_id, options = {})&lt;br /&gt; Forces the dropping (drag and drop) of an element. Also makes an Ajax call.&lt;br /&gt; &lt;br /&gt;escape_javascript(javascript)&lt;br /&gt; Escapes the provided JavaScript.&lt;br /&gt; &lt;br /&gt;evaluate_remote_response()&lt;br /&gt; Creates a JavaScript function that can evaluate a document returned from the server.&lt;br /&gt; &lt;br /&gt;form_remote_tag(options = {})&lt;br /&gt; Creates an HTML form that will be submitted using the XMLHttpRequest object.&lt;br /&gt; &lt;br /&gt;javascript_tag(content)&lt;br /&gt; Creates a JavaScript HTML tag/end tag that contains the provided content.&lt;br /&gt; &lt;br /&gt;link_to_function(name, function, html_options = {})&lt;br /&gt; Creates a hyperlink that links to a client-side JavaScript function.&lt;br /&gt; &lt;br /&gt;link_to_remote(name, options = {}, html_options = {})&lt;br /&gt; Creates a hyperlink that links to the server via an asynchronous XMLHttpRequest request.&lt;br /&gt; &lt;br /&gt;observe_field(field_id, options = {})&lt;br /&gt; Watches a field with the provided ID for user changes.&lt;br /&gt; &lt;br /&gt;observe_form(form_id, options = {})&lt;br /&gt; Watches the form with the provided ID for user changes.&lt;br /&gt; &lt;br /&gt;periodically_call_remote (options = {})&lt;br /&gt; Calls a provided URL whenever the interval elapses. If no interval is provided, a default of 10 seconds is used.&lt;br /&gt; &lt;br /&gt;remote_function(options)&lt;br /&gt; Returns a JavaScript snippet necessary for a remote function.&lt;br /&gt; &lt;br /&gt;sortable_element(element_id, options = {})&lt;br /&gt; Alters the HTML element with the corresponding element_id so that the element is sortable via an Ajax call.&lt;br /&gt; &lt;br /&gt;submit_to_remote(name, value, options = {})&lt;br /&gt; Displays a button that submits a form using the XMLHttpRequest object asynchronously.&lt;br /&gt; &lt;br /&gt;update_element_function (element_id, options = {}, &amp;block)&lt;br /&gt; Updates the browser's DOM using the passed arguments.&lt;br /&gt; &lt;br /&gt;visual_effect(name, element_id = false, js_options = {})&lt;br /&gt; Returns JavaScript code that uses Ajax callbacks for visual effects.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Because I find myself in pretty much the same situation as one of the professors when I went to collegeat least, as far as Ruby on Rails is concernedI'm putting off an example of Ajax using Ruby on Rails until Chapter 14, "Traveling Farther with Ruby." The reason for this is that I'm a little out of my comfort zone here; like the professor, I'm essentially taking a class during the day and teaching it at night.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-2604800971196750999?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/2604800971196750999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2604800971196750999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2604800971196750999'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/13.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7796561021351181669</id><published>2008-12-13T11:04:00.001-08:00</published><updated>2009-01-26T12:33:17.867-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'>Chapter 14. Traveling Farther with Ruby</title><content type='html'>If you're one of those developers who has never ventured outside the world of shrink-wrapped software, you've probably never heard of Ruby, the programming language I introduced in Chapter 13, "Traveling with Ruby on Rails," not the gem. As I noted in the last chapter Ruby, the language, is an object-oriented language that was created by Yukihiro Matsumoto of Japan and released into the wild in 1995. Ruby has many advantages over other programming languages that fill the same niche.&lt;br /&gt;&lt;br /&gt;The first of these advantages is that Ruby is interpreted instead of compiled. On the surface, this might sound like a disadvantage, but it really isn't. Because I'm currently running only Windows XP, at times there has been a binary version of a program that only works on another operating system, such as Linux. However, with a scripted language such as Ruby, as long as I've installed it, I am good to go. Now all I need is to find a Ruby version of Hunt the Wumpus, and I'm all set.&lt;br /&gt;&lt;br /&gt;Like Godzilla, it has expanded beyond its humble roots as a glimmer in its creator's eye to become something of a cult phenomenon. Oh, I mean cult in the good senseno chanting or wearing funny clothes like those strange people who get dressed up to go to Renaissance festivals.&lt;br /&gt;&lt;br /&gt;Seriously, Ruby is an object-oriented language that has capabilities and features that today's fast-paced development environment needs. And did I mention that Ruby is open source? Yes, when you get past the cost of the hardware, all that's required is the cost of an Internet connection and the time that it takes to download and install. I'd do the math for you, but fractions are not really my strong suit.&lt;br /&gt;&lt;br /&gt;Instead, you can take a closer look at Ruby's data types while I take off the sword belt. Because there are unwritten rules that grapefruit must be served in halves and all introductions to programming languages must start with data types, we start there.&lt;br /&gt;&lt;br /&gt;The layout of this chapter goes pretty much like this:&lt;br /&gt;&lt;br /&gt;Data types&lt;br /&gt;&lt;br /&gt;Operators&lt;br /&gt;&lt;br /&gt;Flow-control statements&lt;br /&gt;&lt;br /&gt;Threads&lt;br /&gt;&lt;br /&gt;Ajax&lt;br /&gt;&lt;br /&gt;There is that word again, Ajax. You knew that it would pop up again somewhere. There is, however, a minor difference; basically, we take a quick look at the generated code to see how it works. I don't know about you, but I've always paid attention to the man behind the curtain.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7796561021351181669?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7796561021351181669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-14-traveling-farther-with-ruby.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7796561021351181669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7796561021351181669'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-14-traveling-farther-with-ruby.html' title='Chapter 14. Traveling Farther with Ruby'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-6177624627196226745</id><published>2008-12-13T11:03:00.002-08:00</published><updated>2009-01-26T12:33:17.867-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>14.1. Data Types&lt;br /&gt;Data types in Ruby aren't the data types that you're used to from the more traditional languages, such as C, COBOL, or Pascal. Because Ruby is purely object-oriented, you won't even find the primitive data types available in Java, for instance. In Ruby, you see, all data types are based upon classes.&lt;br /&gt;&lt;br /&gt;This doesn't mean that there is no such thing as an integer or a string in Ruby; it means only that they are instances of the Integer and String classes. To some, this "everything is a class" approach might sound like overkill, but it also makes a lot of sense. Personally, I think it would be easier to code without having to change gears all the time. Just put my mind in OOP gear and go. This leaves the question, go where? I'm thinking of an island.&lt;br /&gt;&lt;br /&gt;14.1.1. Numeric&lt;br /&gt;"I am not a number, I'm a free man!" is the somewhat well-known quote from the British television series The Prisoner. I really don't see what Number Six was complaining aboutit could have been worse. He could, for example, have had a job that he hated in a nuclear power plant, like Number Five did. Number Six does, however, share something in common with Homerer, Number Five. You see, they were both integers.&lt;br /&gt;&lt;br /&gt;Integer, with a capital I, is the base class from which all things integer are derived. Examples of classes derived from Integer are Bignum and Fixnum. Although each has its own characteristics, they both inherit from the Integer base class, whose properties and methods appear in Table 14-1.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Table 14-1. Integer Properties and Methods Method&lt;br /&gt; Class&lt;br /&gt; Description&lt;br /&gt; &lt;br /&gt;chr&lt;br /&gt; Integer&lt;br /&gt; Returns a string containing the character equivalent to the number value.&lt;br /&gt; &lt;br /&gt;downto&lt;br /&gt; Integer&lt;br /&gt; Iterates a block of code.&lt;br /&gt; &lt;br /&gt;integer?&lt;br /&gt; Integer&lt;br /&gt; Returns true.&lt;br /&gt; &lt;br /&gt;next&lt;br /&gt; Integer&lt;br /&gt; Increments the value by 1.&lt;br /&gt; &lt;br /&gt;size&lt;br /&gt; Bignum&lt;br /&gt; Returns the number of bytes used to store the value.&lt;br /&gt; &lt;br /&gt;size&lt;br /&gt; Fixnum&lt;br /&gt; Returns the number of bytes used to store the value.&lt;br /&gt; &lt;br /&gt;step&lt;br /&gt; Integer&lt;br /&gt; Increments the value to an ending value in increments of a set value.&lt;br /&gt; &lt;br /&gt;succ&lt;br /&gt; Integer&lt;br /&gt; Increments the value by 1. Essentially, the same as the next method.&lt;br /&gt; &lt;br /&gt;times&lt;br /&gt; Integer&lt;br /&gt; Executes a block of code a preset number of times.&lt;br /&gt; &lt;br /&gt;to_f&lt;br /&gt; Bignum&lt;br /&gt; Converts the value to a float. When the value is too large to be contained in a float, infinity is returned.&lt;br /&gt; &lt;br /&gt;to_f&lt;br /&gt; Fixnum&lt;br /&gt; Converts the value to a float.&lt;br /&gt; &lt;br /&gt;to_i&lt;br /&gt; Bignum&lt;br /&gt; Returns a Bignum.&lt;br /&gt; &lt;br /&gt;to_i&lt;br /&gt; Fixnum&lt;br /&gt; Returns a Bignum.&lt;br /&gt; &lt;br /&gt;to_s&lt;br /&gt; Bignum&lt;br /&gt; Returns a String.&lt;br /&gt; &lt;br /&gt;to_s&lt;br /&gt; Fixnum&lt;br /&gt; Returns a String.&lt;br /&gt; &lt;br /&gt;upto&lt;br /&gt; Integer&lt;br /&gt; Executes a block of code, incrementing the value by 1 until the indicated value is reached.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;However, with the exception of those poor souls trapped on the island, there is more to life than integers; there's floating point, called Float in Ruby. In case you've forgotten, floating-point numbers are those numbers with fractions, like when the statisticians say that the average American family has 2.6 children. The number 2.6 is a floating-point number and, depending on my mood, is either of my two half-brothers.&lt;br /&gt;&lt;br /&gt;As with the Integer class, the Float class has a number of properties and methods, which are described in Table 14-2.&lt;br /&gt;&lt;br /&gt;Table 14-2. Float Properties and Methods Method&lt;br /&gt; Description&lt;br /&gt; &lt;br /&gt;ceil&lt;br /&gt; Returns the closest integer, either equal to or greater than the float's value.&lt;br /&gt; &lt;br /&gt;finite?&lt;br /&gt; A Boolean indicating whether the value is a valid floating-point number.&lt;br /&gt; &lt;br /&gt;floor&lt;br /&gt; Returns the largest integer that is less than or equal to the value.&lt;br /&gt; &lt;br /&gt;infinite?&lt;br /&gt; Returns true or false, indicating whether the value is infinite.&lt;br /&gt; &lt;br /&gt;nan?&lt;br /&gt; Returns true or false, indicating whether the value is Not A Number.&lt;br /&gt; &lt;br /&gt;round&lt;br /&gt; Rounds the value to the nearest integer.&lt;br /&gt; &lt;br /&gt;to_f&lt;br /&gt; Returns a Float.&lt;br /&gt; &lt;br /&gt;to_i&lt;br /&gt; Converts the value to an integer.&lt;br /&gt; &lt;br /&gt;to_s&lt;br /&gt; Returns a String.&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;14.1.2. String&lt;br /&gt;For people who program in more than one language, there is a major advantage to strings being instances of the String class. Think of it as one-stop shopping; if something needs to be done, there's a really good chance that there is a method to do it. In fact, there are so many that I recommend going to the Ruby home page (www.ruby-lang.org/en/) to see them all.&lt;br /&gt;&lt;br /&gt;14.1.3. Boolean&lt;br /&gt;In programming, there are always two possible answers to any question: true and false. Maybe that is why there are two classes, trueclass and Falseclass. Actually, with the dynamic nature of variables in Ruby, that is the truth. The trueclass represents a logically true value, and the Falseclass represents a logically false class.&lt;br /&gt;&lt;br /&gt;14.1.4. Objects&lt;br /&gt;Possibly because of the total lack of primitives, the built-in objects in Ruby are incredibly rich and varied. There are objects for hashing, objects for file access, and even an object for arrays. In many instances, if you can imagine it, an object probably already is available for what is necessary, as the following list of built-in classes shows:&lt;br /&gt;&lt;br /&gt;Array                                      FalseClass&lt;br /&gt;&lt;br /&gt;Bignum                                     File::Stat&lt;br /&gt;&lt;br /&gt;Binding                                    File&lt;br /&gt;&lt;br /&gt;Class                                      Fixnum&lt;br /&gt;&lt;br /&gt;Continuation                               Float&lt;br /&gt;&lt;br /&gt;Dir                                        Hash&lt;br /&gt;&lt;br /&gt;Exception                                  Integer&lt;br /&gt;IO                                          Regexp&lt;br /&gt;&lt;br /&gt;MatchData                                   String&lt;br /&gt;&lt;br /&gt;Method                                      Struct&lt;br /&gt;&lt;br /&gt;Module                                      Struct::Tms&lt;br /&gt;&lt;br /&gt;NilClass                                    ThreadGroup&lt;br /&gt;&lt;br /&gt;Numeric                                     Thread&lt;br /&gt;&lt;br /&gt;Object                                      Time&lt;br /&gt;&lt;br /&gt;Proc                                        TrueClass&lt;br /&gt;&lt;br /&gt;Range&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;With all those built-in properties and methods, it might be a little while before it is necessary to write an object of our own, but it might be a good idea to give it a try. Let's say, for example, that we want to add a math class that would have two methods: add and subtract. Through diligent work and clean living, we would create the code shown in Listing 14-1.&lt;br /&gt;&lt;br /&gt;Listing 14-1. myMath Class&lt;br /&gt;class MyMath&lt;br /&gt;  def add(a, b)&lt;br /&gt;    puts a + b&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def subtract(a, b)&lt;br /&gt;    puts a - b&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;m = MyMath.new&lt;br /&gt;m.add(1, 1)&lt;br /&gt;m.subtract(4,2)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That's all there is to creating and using a class in Ruby. Unfortunately, I was evil and skipped ahead a little by using variables and operators. Thinking about it, this is a little like a college class I had. After an unusually difficult test, the professor announced that no one got Question 10 correct, and perhaps the reason was that he had forgotten to teach that. Hmm ....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-6177624627196226745?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/6177624627196226745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/14_13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/6177624627196226745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/6177624627196226745'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/14_13.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-2106682747987553322</id><published>2008-12-13T11:03:00.001-08:00</published><updated>2009-01-26T12:33:17.867-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>14.2. Variables&lt;br /&gt;Ruby supports a couple different types of variables, instance variables and class variables. Instead of making you guess whether their names actually mean what they say, I'll just come out and say it. The names mean what they say. Instance variables are created for each instance of the class. With class variables, on the other hand, all instances of the class share one variable. Although instance variables are common, class variables are somewhat less so. This does not mean that they aren't as useful; in fact, many times there is simply no substitute for a class variable.&lt;br /&gt;&lt;br /&gt;The only question concerning variables is how to distinguish between instance variables and class variables. Are there little signs hanging off them that say "instance variable" and "class variable"? In a word, yes.&lt;br /&gt;&lt;br /&gt;Instance variables and class variables are distinguished by the prefix. Instance variables are prefixed by a single @, whereas class variables are prefixed by two @. So @Bob is an instance variable, and @@Paul is a class variable.&lt;br /&gt;&lt;br /&gt;Now that we have someplace to put our information, let's do something to it.&lt;br /&gt;&lt;br /&gt;14.3. Operators&lt;br /&gt;Regardless of the language, there is usually some commonality. There's addition, subtraction, multiplication, division, and assignment. In some languages, including Ruby and JavaScript, the addition operator does double duty as the concatenation operator. This means that examples such as the following are pretty much the same, regardless of the language:&lt;br /&gt;&lt;br /&gt;X = 1 + 1&lt;br /&gt;X = 1  1&lt;br /&gt;X = 1 * 1&lt;br /&gt;X = 1 / 1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;However, occasionally will you see something a little out of the ordinary, usually in languages that borrow some of their syntax from C. In Ruby, they're called multiple assignments; I like to think of them as less typing. Consider, for a moment, the following line of code:&lt;br /&gt;&lt;br /&gt;X = X + 5&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;All that it does is increment the variable X by 5, so wouldn't it be easier to type this instead?&lt;br /&gt;&lt;br /&gt;X += 5&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Yeah, all that I'm saving is two keystrokes, the second X and a space, but it adds up. Imagine for a moment the variable name was my last name, Woychowsky instead of X. Having to type it only once would greatly extend the life of the W key. The same shortcut is available for subtraction, multiplication, and division.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-2106682747987553322?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/2106682747987553322/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/14.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2106682747987553322'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2106682747987553322'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/14.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1216857567938439004</id><published>2008-12-13T11:00:00.000-08:00</published><updated>2009-01-26T12:33:17.867-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>Section 14.4.  Flow-Control Statements&lt;table width="100%" border="0" cellpadding="0" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="top"&gt;&lt;a name="ch14lev1sec4"&gt;&lt;/a&gt; &lt;h3&gt; class="docSection1Title" id="title-IDAXCZGB"&gt;14.4. Flow-Control Statements&lt;/h3&gt; &lt;p class="docText"&gt;In any type of nontrivial program, flow control is possibly the  most important factor in programming. Without some kind of flow control in  programming languages, computers would essentially be very expensive desktop  ornaments. Come to think of it, when you got past the forwarding of every e-mail  received each day to his team, I once had a manager whose computer was a very  expensive desktop ornament. He actually once forwarded the same message 14 times  before realizing that he had somehow been added to his address list for the  team. But I'm wandering, so let's get back to flow control, starting with  conditions.&lt;/p&gt;&lt;a name="ch14lev2sec5"&gt;&lt;/a&gt; &lt;h4 class="docSection2Title" id="title-IDACDZGB"&gt;14.4.1. Conditions&lt;/h4&gt; &lt;p class="docText"&gt;In your average run-of-the-mill language, there is the  &lt;tt&gt;if&lt;/tt&gt; statement, and that is pretty much all there is to it. Ruby has an  &lt;tt&gt;if&lt;/tt&gt; that looks something like this:&lt;/p&gt; &lt;div class="docText"&gt;&lt;pre&gt;if x == 1   b = 2 end &lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p class="docText"&gt;Pretty easy. Let's add a layer of complexity with an  &lt;tt&gt;else&lt;/tt&gt;:&lt;/p&gt; &lt;div class="docText"&gt;&lt;pre&gt;if x == 1   b = 2 else   b = 3 end &lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p class="docText"&gt;In Ruby, it is also possible to take it to a higher degree of  complexity by using the &lt;tt&gt;elsif&lt;/tt&gt; statement:&lt;/p&gt; &lt;div class="docText"&gt;&lt;pre&gt;if x == 1   b = 2 elsif x == 2   b = 4 else   b = 3 end &lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p class="docText"&gt;&lt;a name="iddle1248"&gt;&lt;/a&gt;&lt;a name="iddle1544"&gt;&lt;/a&gt;&lt;a name="iddle1832"&gt;&lt;/a&gt;&lt;a name="iddle2206"&gt;&lt;/a&gt;&lt;a name="iddle2411"&gt;&lt;/a&gt;&lt;a name="iddle2442"&gt;&lt;/a&gt;&lt;a name="iddle2493"&gt;&lt;/a&gt;Before I forget, for the purpose of  clarity, Ruby permits the addition of a &lt;tt&gt;then&lt;/tt&gt; to the &lt;tt&gt;if&lt;/tt&gt;  statement:&lt;/p&gt; &lt;div class="docText"&gt;&lt;pre&gt;if x == 1 then   b = 2 end &lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p class="docText"&gt;Remember all the way back to &lt;a class="docLink" href="http://www.blogger.com/ch04.html#ch04"&gt;Chapter 4&lt;/a&gt;, "JavaScript"? Remember conditional  operators? Well, they're back! In fact, here is an example:&lt;/p&gt; &lt;div class="docText"&gt;&lt;pre&gt;b = (x == 1 ? 2 : 3)&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p class="docText"&gt;A few years ago, I grew a goatee, which I have since shaved  off. At the time, my reason for growing it was strictly personal and strange.  You see, I wanted to pass myself off as the evil Ed from a parallel dimension.  My plan for work domination failed, but it gave me the opportunity to appreciate  the evil things from parallel dimensions. For example, did you know that Ruby  has an evil &lt;tt&gt;if&lt;/tt&gt; called &lt;tt&gt;unless&lt;/tt&gt;?&lt;/p&gt; &lt;p class="docText"&gt;The &lt;tt&gt;unless&lt;/tt&gt; statement executes the code within only  when the condition is false. If this doesn't fit the textbook, or, at least  &lt;span class="docEmphasis"&gt;Star Trek,&lt;/span&gt; example of something from a parallel  dimension, I don't know what does.&lt;/p&gt;&lt;a name="ch14lev2sec6"&gt;&lt;/a&gt; &lt;h4 class="docSection2Title" id="title-IDAWHZGB"&gt;14.4.2. Looping&lt;/h4&gt; &lt;p class="docText"&gt;Some days I feel like I'm going around in circles, usually in  the morning while I'm getting ready for work. The problem probably stems from a  deep-seated need for coffee to get moving in the morning. This wasn't always the  case, but back in high school, I worked in a pancake house and got hooked. The  free coffee just seemed to helpthat is, until I drank fifteen 20-ounce cups in  the course of a day. I could have threaded a sewing machine needle while the  machine was running. It hasn't been that bad in a while, but my morning ritual  still requires coffee, as Ruby, shown in &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch14list02"&gt;Listing 14-2&lt;/a&gt;, illustrates.&lt;/p&gt;&lt;a name="ch14list02"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDANIZGB"&gt;Listing 14-2. My Morning in Ruby:  &lt;tt&gt;while&lt;/tt&gt; Loop&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;cupsofcoffee = 0  while cupsofcoffee &lt;&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt; &lt;p class="docText"&gt;The great thing about describing one's morning programmatically  is that there are always alternative ways of expressing one's self. For example,  some &lt;a name="iddle1560"&gt;&lt;/a&gt;&lt;a name="iddle1970"&gt;&lt;/a&gt;&lt;a name="iddle2209"&gt;&lt;/a&gt;&lt;a name="iddle2413"&gt;&lt;/a&gt;&lt;a name="iddle2446"&gt;&lt;/a&gt;mornings the blanket monster is holding  me back and I just can't seem to get moving until there is a certain level of  coffee in my system. Mornings like these are better expressed by the code shown  in &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch14list03"&gt;Listing 14-3&lt;/a&gt;.&lt;/p&gt;&lt;a name="ch14list03"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDAGKZGB"&gt;Listing 14-3. My Morning in Ruby:  &lt;tt&gt;until&lt;/tt&gt; Loop&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;cupsofcoffee = 0  until cupsofcoffee &gt;= 4   puts "hurry..."   cupsofcoffee += 1 end &lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt; &lt;p class="docText"&gt;A while back, I used to have one of those coffee pots that had  a timer. On those mornings when I had programmed it the night before, coffee was  already going. Ah, a set number of cups of coffee just waiting for cream and  sugar. I suppose &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch14list04"&gt;Listing 14-4&lt;/a&gt; best sums  it up.&lt;/p&gt;&lt;a name="ch14list04"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDACLZGB"&gt;Listing 14-4. My Morning in Ruby:  &lt;tt&gt;for&lt;/tt&gt;/&lt;tt&gt;in&lt;/tt&gt; Loop&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;puts "for-in loop" for x in ["hurry...", "hurry...", "hurry...", "hurry..."]        puts x end &lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt; &lt;p class="docText"&gt;Nowadays, I have one of those coffee makers that takes a Pod.  Just drop in the Pod and hit the button, and 90 seconds later there's coffee.  This takes making coffee from being an art to being more of a science, a feeling  that is best conveyed by the example shown in &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch14list05"&gt;Listing 14-5&lt;/a&gt;.&lt;/p&gt;&lt;a name="ch14list05"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDAAMZGB"&gt;Listing 14-5. My Morning in Ruby:  &lt;tt&gt;for&lt;/tt&gt;/&lt;tt&gt;in&lt;/tt&gt; Loop&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;puts "Iterators" 1.step(4,1) do |x|   puts "hurry..." end &lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;h3 class="docSection1Title" id="title-IDAB1XCL"&gt;14.5. Threads&lt;/h3&gt; &lt;p class="docText"&gt;Ruby has a feature that every language should have: the  capability to multithread. Personally, I'm fond of forking a thread whenever  something that I'm about to do is time consuming. For instance, any kind of  input/output operation or attempt to obtain information from another server  deserves another thread.&lt;/p&gt; &lt;p class="docText"&gt;&lt;a name="iddle1259"&gt;&lt;/a&gt;&lt;a name="iddle2213"&gt;&lt;/a&gt;In Ruby, threads  are compatible across all platforms, which is quite an accomplishment. However,  I recommend further reading on the subject of multithreading. From personal  experience, I know that multithreading is truly a dark art and is not meant to  be undertaken lightly&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1216857567938439004?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1216857567938439004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/section-14.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1216857567938439004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1216857567938439004'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/section-14.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7405909237960737445</id><published>2008-12-13T10:59:00.000-08:00</published><updated>2009-01-26T12:33:17.867-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'>Chapter 15. The Essential Cross-Browser HTML DOM</title><content type='html'>&lt;p class="docText"&gt;Whether or not the average web developer is aware of it, it is  out there, unseen and unnoticed, but nevertheless out there. Allow me to explain  before you decide that I've popped a gasket and need to be taken to a nice soft  room, the kind with padded walls. I am referring to the HTML Document Object  Modelyes, that often ignored application programming interface that can be both  a blessing and a curse.&lt;/p&gt; &lt;p class="docText"&gt;Yes, the average web developer uses the HTML DOM only to the  extent that is absolutely necessary to perform the job, and no further. The  reasons for this are many, ranging from the fact that in the early days of web  browsers, everybody did their own thing, to the fact that client-side code is  often considered unreliable because some people are using web browsers that  belong more fittingly in a museum than in a computer that was manufactured in  the twenty-first century.&lt;/p&gt; &lt;p class="docText"&gt;I suppose that this could be considered a major issue, the idea  that web applications need to work on every browser released since the beginning  of time. You might consider me something of a snob for saying this, but why  should everyone who is willing to advance beyond the mid-1990s be penalized? You  don't see electrical power being looked down upon because some groups don't  approve of it. Regardless of the reason for ignoring the HTML DOM, unless  they're fond of web applications that behave like mainframe applications from  the 1970s, people will have to either get with the program or be left  behind.&lt;/p&gt; &lt;p class="docText"&gt;This chapter is organized along the following lines:&lt;/p&gt; &lt;ul&gt;&lt;li&gt; &lt;p class="docList"&gt;&lt;a class="docLink" href="ch15lev1sec1.html#ch15lev1sec1"&gt;Interfaces&lt;/a&gt;&lt;/p&gt; &lt;/li&gt;&lt;li&gt; &lt;p class="docList"&gt;&lt;a class="docLink" href="ch15lev1sec2.html#ch15lev1sec2"&gt;Document&lt;/a&gt;&lt;/p&gt; &lt;/li&gt;&lt;li&gt; &lt;p class="docList"&gt;&lt;a class="docLink" href="ch15lev1sec3.html#ch15lev1sec3"&gt;Frames&lt;/a&gt;&lt;/p&gt; &lt;/li&gt;&lt;li&gt; &lt;p class="docList"&gt;&lt;a class="docLink" href="ch15lev1sec4.html#ch15lev1sec4"&gt;Collections&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7405909237960737445?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7405909237960737445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-15-essential-cross-browser-html.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7405909237960737445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7405909237960737445'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-15-essential-cross-browser-html.html' title='Chapter 15. The Essential Cross-Browser HTML DOM'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7575345747005159847</id><published>2008-12-13T10:55:00.003-08:00</published><updated>2009-01-26T12:33:17.867-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>Alright, now we are officially dealing with the HTML Document  Object Model in all its hierarchical glory. The only question is, what does the  word &lt;span class="docEmphasis"&gt;hierarchical&lt;/span&gt; mean in reference to the HTML  DOM?&lt;/p&gt; &lt;p class="docText"&gt;To me, it means that I envision the structure as a tree, but  not the binary kind or the kind growing outside. It has a single root and  branches (elements), and sometimes those branches have branches (more elements).  In my mind, the only difference from the growing kind of tree is that the root  is at the top, but since I'm in Pennsylvania, I think of trees in China and  everything is alright. If you happen to be in China, just envision trees in  Pennsylvania, and you'll be fine. Ex-mainframe programmers should think IMS DB  to get themselves through this section.&lt;/p&gt; &lt;p class="docText"&gt;Seriously, as weird as it sounds, the concept of hierarchical  data has been around for a long time. Consider the HTML document shown in &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch15list01"&gt;Listing 15-1&lt;/a&gt; for a moment.&lt;/p&gt;&lt;a name="ch15list01"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDAZ5OEL"&gt;Listing 15-1. An HTML Document&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;   &lt;h1&gt;Test 1&lt;/h1&gt;&lt;br /&gt;   &lt;h2&gt;Test 2&lt;/h2&gt;&lt;br /&gt;   &lt;h3&gt;Test 3&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt; &lt;p class="docText"&gt;This document could alternatively be depicted graphically as  shown in &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch15fig01"&gt;Figure 15-1&lt;/a&gt;.&lt;/p&gt; &lt;a name="ch15fig01"&gt;&lt;/a&gt; &lt;p&gt; &lt;/p&gt;&lt;center&gt; &lt;h5 class="docFigureTitle"&gt;Figure 15-1. Graphic depiction of HTML document in &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch15list01"&gt;Listing 15-1&lt;/a&gt;&lt;/h5&gt; &lt;p class="docText"&gt; &lt;/p&gt;&lt;div class="v1"&gt;&lt;a href="http://www.blogger.com/images/15ajx01_alt.jpg" target="_self"&gt;[View full size  image]&lt;/a&gt;&lt;/div&gt;&lt;img alt="" src="http://www.blogger.com/images/15ajx01.jpg" width="498" border="0" height="103" /&gt; &lt;/center&gt;&lt;br /&gt;&lt;p class="docText"&gt;&lt;a name="iddle1677"&gt;&lt;/a&gt;&lt;a name="iddle1885"&gt;&lt;/a&gt;&lt;a name="iddle2132"&gt;&lt;/a&gt;See, it's hierarchical. There is a single root, the  &lt;tt&gt;html&lt;/tt&gt; element, which has two children, the &lt;tt&gt;head&lt;/tt&gt; and  &lt;tt&gt;body&lt;/tt&gt; elements. The &lt;tt&gt;head&lt;/tt&gt; and &lt;tt&gt;body&lt;/tt&gt; elements are  siblings because they both share the same parent. The &lt;tt&gt;head&lt;/tt&gt; element has  two children, and the &lt;tt&gt;title&lt;/tt&gt; and &lt;tt&gt;script&lt;/tt&gt; elements and the  &lt;tt&gt;body&lt;/tt&gt; element have three children: the &lt;tt&gt;h1&lt;/tt&gt;, &lt;tt&gt;h2&lt;/tt&gt;, and  &lt;tt&gt;h3&lt;/tt&gt; elements. The &lt;tt&gt;title&lt;/tt&gt; and &lt;tt&gt;script&lt;/tt&gt; elements are  siblings, and the &lt;tt&gt;H1&lt;/tt&gt;, &lt;tt&gt;H2&lt;/tt&gt;, and &lt;tt&gt;H3&lt;/tt&gt; elements are  siblings, but the two groups of elements are not siblings because they have  different parents.&lt;/p&gt; &lt;p class="docText"&gt;So far, this has pretty much been an intellectual exercise, so  how excited can someone get about a picture? Um, I mean, a picture that doesn't  come with a rating!&lt;/p&gt; &lt;p class="docText"&gt;What I mean is, maybe it would help if there were a convenient  table that covered the various properties and methods available through the  document interface. Fortunately, Igor has put together &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch15table02"&gt;Table 15-2&lt;/a&gt; to give you some idea of what is  available.&lt;/p&gt;&lt;a name="ch15table02"&gt;&lt;/a&gt; &lt;p&gt; &lt;table class="allBorders" rules="groups" border="1" cellpadding="5" cellspacing="0"&gt; &lt;caption&gt; &lt;h5 class="docTableTitle"&gt;Table 15-2. HTML DOM Properties/Methods&lt;/h5&gt;&lt;/caption&gt; &lt;colgroup span="2" align="left"&gt; &lt;col width="100"&gt; &lt;col width="450"&gt;&lt;/colgroup&gt; &lt;thead&gt; &lt;tr&gt; &lt;th class="bottomBorder thead" scope="col" valign="top" align="left"&gt; &lt;p class="docText"&gt;Property/Method&lt;/p&gt;&lt;/th&gt; &lt;th class="bottomBorder thead" scope="col" valign="top" align="left"&gt; &lt;p class="docText"&gt;Description&lt;/p&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;anchors&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A collection consisting of the anchors in the current  document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;applets&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A collection consisting of the applets in the current  document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;attributes&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A collection consisting of the attributes for the current  node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;body&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The &lt;tt&gt;body&lt;/tt&gt; element of the page.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;childNodes&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A nodeset consisting of the child nodes of the current node.  Please note that the nodeset can be empty.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;cookie&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A collection consisting of the cookies associated with the  current document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;doctype&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The Document Type Declaration associated with this XML  document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;documentElement&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The document's root element.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;domain&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The server's domain name.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;firstChild&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The first child node of the current node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;forms&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A collection consisting of the forms in the current  document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;frames&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A collection consisting of the frames in the current  document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;images&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A collection consisting of the images in the current  document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;implementation&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The &lt;tt&gt;DOMImplementation&lt;/tt&gt; for this document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;lastChild&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The last child of the current node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;links&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A collection consisting of the links in the current  document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;nextSibling&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The next child of the current node's parent.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;nodeName&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The name of the node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;nodeType&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The type of the node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;nodeValue&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The value of the node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;ownerDocument&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The Document associated with the current element.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;parentNode&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The parent of the current node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;previousSibling&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The previous child of the current node's parent.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;referrer&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The URI of the page that linked to this page.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;title&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The title of the HTML document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;URL&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The current page's URL.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;appendChild(new)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Appends the new child node as the last child.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;cloneNode(deep)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Duplicates the specified node. The Boolean parameter  &lt;tt&gt;deep&lt;/tt&gt; is used to indicate a deep copy, whether or not the children  should be copied.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;close()&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Closes the document stream and also causes the document to be  rendered.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;createAttribute(name)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Creates an attribute.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;createCDATASection(data)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Creates a &lt;tt&gt;CDATASection&lt;/tt&gt; node using the data  provided.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;createComment(data)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Creates a comment node using the data provided.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;createDocumentFragment()&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Creates an empty document fragment.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;createElement(tagName)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Creates the specified element.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;createEntityReference(name)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Creates an &lt;tt&gt;EntityReference&lt;/tt&gt;.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;createProcessingInstruction (target,data)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Creates a &lt;tt&gt;ProcessingInstruction&lt;/tt&gt; node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;createTextNode(data)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Creates a &lt;tt&gt;Text&lt;/tt&gt; element using the &lt;span class="docEmphStrong"&gt;data&lt;/span&gt; provided.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;getElementById(elementId)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Returns a single element based upon that element's &lt;tt&gt;id&lt;/tt&gt;  attribute. When there is more than one element with the same &lt;tt&gt;id&lt;/tt&gt;, only  the first is returned.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;getElementByName(elementName)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Returns a collection of elements based upon the element's  name.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;getElementsByTagName(tagname)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Returns a nodeset consisting of elements with matching tag  names.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;hasChildNodes()&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Returns &lt;tt&gt;TRue&lt;/tt&gt; if child nodes exist and &lt;tt&gt;false&lt;/tt&gt;  if child nodes do not exist.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;insertBefore(new,reference)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Inserts the new child node before the reference child  node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;open()&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Opens the document stream for writing.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;removeChild(old)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Removes the old child node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;replaceChild(new, old)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Replaces the old child node with the new child  node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;write()&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Writes a text string to the document.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;writeln()&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Writes a text string to the document and appends a newline  character.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="docText"&gt;Before moving on, I want to remind you that the document is  hierarchical. This means that each element has properties and methods of its  own. Rather than go crazy trying to create some kind of uber table with every  possible property and method for the interfaces shown in &lt;a class="docLink" href="http://www.blogger.com/ch15lev1sec1.html#ch15table01"&gt;Table 15-1&lt;/a&gt;, I decided to create &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch15table03"&gt;Table 15-3&lt;/a&gt;. &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch15table03"&gt;Table 15-3&lt;/a&gt; covers the properties and methods common to  the various elements.&lt;/p&gt;&lt;a name="ch15table03"&gt;&lt;/a&gt; &lt;p&gt; &lt;table class="allBorders" rules="groups" border="1" cellpadding="5" cellspacing="0"&gt; &lt;caption&gt; &lt;h5 class="docTableTitle"&gt;Table 15-3. Properties/Methods Common to the Various  HTML DOM Interfaces&lt;/h5&gt;&lt;/caption&gt; &lt;colgroup span="2" align="left"&gt; &lt;col width="200"&gt; &lt;col width="350"&gt;&lt;/colgroup&gt; &lt;thead&gt; &lt;tr&gt; &lt;th class="bottomBorder thead" scope="col" valign="top" align="left"&gt; &lt;p class="docText"&gt;Property/Method&lt;/p&gt;&lt;/th&gt; &lt;th class="bottomBorder thead" scope="col" valign="top" align="left"&gt; &lt;p class="docText"&gt;Description&lt;/p&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;attributes&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A collection consisting of the attributes for the current  node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;childNodes&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;A nodeset consisting of the child nodes of the current node.  Please note that the nodeset can be empty.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;className&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The element's &lt;tt&gt;class&lt;/tt&gt; attribute.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;dir&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The element's text direction.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;firstChild&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The first child node of the current node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;id&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The element's identifier.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;lang&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The element's language code.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;lastChild&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The last child of the current node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;nextSibling&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The next child of the current node's parent.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;nodeName&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The name of the node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;nodeType&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The type of the node. See &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch15table02"&gt;Table 15-2&lt;/a&gt; for accepted values.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;nodeValue&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The value of the node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;ownerDocument&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The document associated with the current element.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;parentNode&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The parent of the current node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;previousSibling&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The previous child of the current node's parent.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;tagName&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The tag name of the element.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;title&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The element's title.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;appendChild(new)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Appends the new child node as the last child.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;cloneNode(deep)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Duplicates the specified node. The Boolean parameter  &lt;tt&gt;deep&lt;/tt&gt; is used to indicate a deep copy, whether or not the children  should be copied.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;getAttribute(name)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Returns the value of an attribute based upon  name.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;getAttributeNode(name)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Retrieves an &lt;tt&gt;Attr&lt;/tt&gt; node by name.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;getElementsByTagName(tagname)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Returns a nodeset consisting of elements with matching tag  names.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;hasChildNodes()&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Returns &lt;tt&gt;true&lt;/tt&gt; if child nodes exist and &lt;tt&gt;false&lt;/tt&gt;  if child nodes do not exist.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;insertBefore(new,reference)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Inserts the new child node before the reference child  node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;normalize()&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Normalizes the specified element and children of the specified  element.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;removeAttribute(name)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Removes an attribute by name.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;removeAttributeNode(name)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Removes an &lt;tt&gt;Attr&lt;/tt&gt; node by name.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;removeChild(old)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Removes the old child node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;replaceChild(new,old)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Replaces the old child node with the new child  node.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;setAttribute(name,value)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Creates an attribute and sets its value.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;setAttributeNode(name)&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Adds an &lt;tt&gt;Attr&lt;/tt&gt; node by  name.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="docText"&gt;I want to add a little hint on how to find some of the  remaining properties or methods for the various interfaces. Basically, it goes  like this: If it is a property or method of the element, there is a really good  chance that it is also a property or method of the interface. It might sound  strange that this has to be mentioned, but I've found that everyone has a blind  spot concerning something in their career. &lt;a name="iddle1236"&gt;&lt;/a&gt;&lt;a name="iddle1582"&gt;&lt;/a&gt;&lt;a name="iddle1673"&gt;&lt;/a&gt;&lt;a name="iddle1674"&gt;&lt;/a&gt;&lt;a name="iddle1855"&gt;&lt;/a&gt;&lt;a name="iddle2129"&gt;&lt;/a&gt;&lt;a name="iddle2130"&gt;&lt;/a&gt;In case you were  wondering, mine is peasants with pitchforks and torches.&lt;/p&gt;&lt;h3 class="docSection1Title" id="title-IDAIHTTF"&gt;15.3. Frames&lt;/h3&gt; &lt;p class="docText"&gt;From an HTML Document Object Model point of view, frames are  rather odd creatures because they are essentially HTML documents within HTML  documents. Consider for a moment the fact that it is possible to have more than  one document at a time. For example, the following is perfectly legal:&lt;/p&gt; &lt;div class="docText"&gt;&lt;pre&gt;document.frames[1].document.body&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p class="docText"&gt;It refers to the body of the document in the frame with an  index of &lt;tt&gt;1&lt;/tt&gt;. This has a tendency to throw off quite a number of people,  probably because it is a "wheels within wheels" kind of relationship, a bit  tough to grasp the first time around. There is also the added complexity that if  the script is executing in a frame itself, it could quite be playing with either  the parent document or a sibling document, or even the child of a sibling. The  important thing to remember is that anything that can be done with the current  document can also be done with another document.&lt;/p&gt;&lt;h3 class="docSection1Title" id="title-IDAZ51GB"&gt;15.4. Collections&lt;/h3&gt; &lt;p class="docText"&gt;As you probably noticed in &lt;a class="docLink" href="http://www.blogger.com/ch15lev1sec1.html#ch15table01"&gt;Table 15-1&lt;/a&gt;, there is an interface whose  sole purpose is to deal with collections. Add to this the various collections  defined in &lt;a class="docLink" href="http://www.blogger.com/ch15lev1sec2.html#ch15table02"&gt;Tables 15-2&lt;/a&gt;  and &lt;a class="docLink" href="http://www.blogger.com/ch15lev1sec2.html#ch15table03"&gt;15-3&lt;/a&gt;, and it  becomes apparent very quickly that somebody really likes collections. Who can  blame them?&lt;/p&gt; &lt;p class="docText"&gt;Collections make for very compact code that can be stepped  through in a sequential manner. &lt;a class="docLink" href="http://www.blogger.com/post-create.do#ch15table04"&gt;Table  15-4&lt;/a&gt; details the single property and two methods available through the  collection interface.&lt;/p&gt;&lt;a name="ch15table04"&gt;&lt;/a&gt; &lt;p&gt; &lt;table class="allBorders" rules="groups" border="1" cellpadding="5" cellspacing="0"&gt; &lt;caption&gt; &lt;h5 class="docTableTitle"&gt;Table 15-4. The Property and the Methods Available  Through the Collection Interface&lt;/h5&gt;&lt;/caption&gt; &lt;colgroup span="2" align="left"&gt; &lt;col width="150"&gt; &lt;col width="400"&gt;&lt;/colgroup&gt; &lt;thead&gt; &lt;tr&gt; &lt;th class="bottomBorder thead" scope="col" valign="top" align="left"&gt; &lt;p class="docText"&gt;Property/Method&lt;/p&gt;&lt;/th&gt; &lt;th class="bottomBorder thead" scope="col" valign="top" align="left"&gt; &lt;p class="docText"&gt;Description&lt;/p&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;length&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;The number of items in the collection&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;item()&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Retrieves an individual item from a collection based upon that  item's index&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;namedItem()&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Retrieves an individual item from a collection based upon that  item's identifier&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7575345747005159847?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7575345747005159847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/alright-now-we-are-officially-dealing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7575345747005159847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7575345747005159847'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/alright-now-we-are-officially-dealing.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-3749779227723721705</id><published>2008-12-13T10:55:00.001-08:00</published><updated>2009-01-26T12:33:17.868-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>&lt;h2 class="docChapterTitle" id="title-IDARAFII"&gt;Chapter 16. Other Items of  Interest&lt;/h2&gt; &lt;p class="docText"&gt;Although I do have a rather loose grip on reality, my grip  isn't so loose that I think that the information contained within these pages is  the be all and end all concerning asynchronous JavaScript and XML. Ajax is  nearly unique in having both the excitement associated with a new topic and the  maturity that is associated with only a well-established technique. In fact, the  last topic that I can think of that had the same dual nature was NASA's Apollo  program. On one hand, the idea of sending people to the Moon and returning them  safely to Earth was the stuff of science fiction. On the other hand, humanity  has been playing with rockets for centuries, occasionally with disastrous  results.&lt;/p&gt; &lt;p class="docText"&gt;Come to think of it, Ajax and the Apollo program have a great  deal in common. On one hand, the idea of web applications that have the look and  feel of Linux and Windows applications is the stuff of science fiction. On the  other hand, humanity has been creating web applications for the last several  years, occasionally with disastrous results. Hmm, there seems to be some kind of  pattern going on here.&lt;/p&gt; &lt;p class="docText"&gt;In this chapter, I address some technologies that are  complementary to Ajax, one that is similar or is a kind of proprietary approach  to Ajax, and then finish with some further/final thoughts on browsers.  Essentially, the purpose of this chapter is not only to sum up everything that  has been covered in this book, but also to provide a starting point on where to  look for other possible ways of doing things. For example, about two months ago,  I spoke with a developer who did Ajax. However, his technique was to use a Java  applet for communications instead of the &lt;tt&gt;XMLHttpRequest&lt;/tt&gt; object. What I  am trying to convey is that there are multiple answers to every question, all of  them equally correct. So here are some of the answers, with my personal opinions  sprinkled about.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-3749779227723721705?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/3749779227723721705/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-16.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/3749779227723721705'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/3749779227723721705'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/chapter-16.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-2495983116550564918</id><published>2008-12-13T10:54:00.000-08:00</published><updated>2009-01-26T12:33:17.868-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>&lt;h3 class="docSection1Title" id="680422-853"&gt;16.1. Sarissa&lt;/h3&gt; &lt;p class="docText"&gt;&lt;a name="iddle1169"&gt;&lt;/a&gt;&lt;a name="iddle2223"&gt;&lt;/a&gt;Although it's  officially only an open source cross-browser JavaScript XML library, Sarissa is  one of those libraries whose capabilities extend far beyond the basic XML  support that I expected. This is a rare occurrence in today's world, where we  can all remember being disappointed by movies, jobs, and most members of  Congress. Sarissa wraps the browser's native XML application programming  interfaces with common interfaces. This makes life much easier for the  client-side developer than it would otherwise be.&lt;/p&gt; &lt;p class="docText"&gt;Unlike my home-grown library, which supports only Microsoft  Internet Explorer and Gecko-based browsers such as Firefox, Flock, Mozilla, and  Netscape, Sarissa supports a wide range of browsers on multiple platforms. This  serves as a really good example of what a number of dedicated developers can  accomplish when they put their minds to it, as opposed to the lone mad scientist  or even the bloated corporation. Sarissa supports, at least partially, the  following web browsers:&lt;/p&gt; &lt;ul&gt;&lt;li&gt; &lt;p class="docList"&gt;Firefox&lt;/p&gt; &lt;/li&gt;&lt;li&gt; &lt;p class="docList"&gt;Konqueror (KDE 3.3)&lt;/p&gt; &lt;/li&gt;&lt;li&gt; &lt;p class="docList"&gt;Microsoft Internet Explorer (MSXML 3.0)&lt;/p&gt; &lt;/li&gt;&lt;li&gt; &lt;p class="docList"&gt;Mozilla&lt;/p&gt; &lt;/li&gt;&lt;li&gt; &lt;p class="docList"&gt;Opera&lt;/p&gt; &lt;/li&gt;&lt;li&gt; &lt;p class="docList"&gt;Safari&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p class="docText"&gt;That's quite an impressive list of web browsers; I don't even  have a machine capable of running Safari. I normally just press my nose to the  window of the Apple Store and wish. Come to think of it, I usually do that with  most stores that sell computers, including online ones. Well, at least now my  wife knows how the monitor on her computer got the nose prints on it and who the  nose prints belong to.&lt;/p&gt;&lt;a name="ch16lev2sec1"&gt;&lt;/a&gt; &lt;h4 class="docSection2Title" id="title-IDA1UI0I"&gt;16.1.1. A Brief Overview of  Sarissa&lt;/h4&gt; &lt;p class="docText"&gt;&lt;a class="docLink" href="#ch16table01"&gt;Table 16-1&lt;/a&gt; briefly  examines the goodies available in Sarissa, which read like a Who's Who of Ajax  features.&lt;/p&gt; &lt;a name="ch16table01"&gt;&lt;/a&gt; &lt;p&gt; &lt;table class="allBorders" rules="groups" border="1" cellpadding="5" cellspacing="0"&gt; &lt;caption&gt; &lt;h5 class="docTableTitle"&gt;Table 16-1. Sarissa Features&lt;/h5&gt;&lt;/caption&gt; &lt;colgroup span="2" align="left"&gt; &lt;col width="220"&gt; &lt;col width="330"&gt;&lt;/colgroup&gt; &lt;thead&gt; &lt;tr&gt; &lt;th class="bottomBorder thead" scope="col" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;a name="iddle2224"&gt;&lt;/a&gt;&lt;a name="iddle2225"&gt;&lt;/a&gt;&lt;a name="iddle2226"&gt;&lt;/a&gt;&lt;a name="iddle2352"&gt;&lt;/a&gt;&lt;a name="iddle2536"&gt;&lt;/a&gt;Action&lt;/p&gt;&lt;/th&gt; &lt;th class="bottomBorder thead" scope="col" valign="top" align="left"&gt; &lt;p class="docText"&gt;Description&lt;/p&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;DOM Document Object (create)&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Creates a new instance of an XML DOM document&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;DOM Document Object (load)&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Loads an XML DOM document from either a remote source, such as  the server, or a string either synchronously or asynchronously&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Parse&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Parses an XML DOM document for errors&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Serialize&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Serializes an XML DOM document to a text string&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;&lt;tt&gt;XMLHttpRequest&lt;/tt&gt;&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Communicates with the web server via the  &lt;tt&gt;XMLHttpRequest&lt;/tt&gt; object&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;XPath&lt;/p&gt;&lt;/td&gt; &lt;td class="bottomBorder" valign="top" align="left"&gt; &lt;p class="docText"&gt;Provides the capability to apply an XPath statement with  JavaScript&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;br /&gt;&lt;p class="docText"&gt;The overall syntax for Sarissa is both logical and consistent.  By &lt;span class="docEmphasis"&gt;logical,&lt;/span&gt; I mean that if a particular parameter  is necessary for a certain object, it is there. The consistency that I'm  referring to is the capability to write a script once and be able to run it on  any of the supported web browsers, without having to monkey around with the code  too much. What a concept!&lt;/p&gt; &lt;p class="docText"&gt;To see what I mean, let's take a look at how to create an XML  DOM document using Sarissa:&lt;/p&gt; &lt;div class="docText"&gt;&lt;pre&gt;var myXMLDocument = Sarissa.getDomDocument();&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p class="docText"&gt;Relatively simple and painless, isn't it?&lt;/p&gt; &lt;p class="docText"&gt;Loading the XML document from a remote source is only slightly  more complex, unless you're indecisive, in which case you've got real problems  in deciding between synchronous and asynchronous. Never mind, I'll go out on a  limb and show how it is done synchronously in &lt;a class="docLink" href="#ch16list01"&gt;Listing 16-1&lt;/a&gt; and asynchronously in &lt;a class="docLink" href="#ch16list02"&gt;Listing 16-2&lt;/a&gt;.&lt;/p&gt;&lt;a name="ch16list01"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDATLJ0I"&gt;Listing 16-1. Loading  Synchronously&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;var myXMLDocument = Sarissa.getDomDocument();&lt;br /&gt;&lt;br /&gt;myXMLDocument.async = false;&lt;br /&gt;myXMLDocument.load("duckzilla.xml");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt; &lt;a name="ch16list02"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDAGMJ0I"&gt;Listing 16-2. Loading  Asynchronously&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;var myXMLDocument = Sarissa.getDomDocument();&lt;br /&gt;&lt;br /&gt;myXMLDocument.async = true;&lt;br /&gt;myXMLDocument.onreadystatechange = readyStateHandler;&lt;br /&gt;myXMLDocument.load("duckzilla.xml");&lt;br /&gt;&lt;br /&gt;function readyStateHandler() {&lt;br /&gt; if(myXMLDocument.readyState == 4)&lt;br /&gt;   alert('Loaded.');&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt; &lt;p class="docText"&gt;&lt;a name="iddle1078"&gt;&lt;/a&gt;&lt;a name="iddle2222"&gt;&lt;/a&gt;&lt;a name="iddle2228"&gt;&lt;/a&gt;&lt;a name="iddle2512"&gt;&lt;/a&gt;&lt;a name="iddle2652"&gt;&lt;/a&gt;But what if the  XML isn't remote? Say, for example, that it is already on the page in a  JavaScript string. In that case, &lt;a class="docLink" href="#ch16list03"&gt;Listing  16-3&lt;/a&gt; is the example for you.&lt;/p&gt;&lt;a name="ch16list03"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDABOJ0I"&gt;Listing 16-3. Loading an XML  Document Already on the Page&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;var myXMLDocument = Sarissa.getDomDocument();&lt;br /&gt;var myDOMParser = new DOMParser();&lt;br /&gt;var myXMLString = '&lt;xyzzy&gt;plugh&lt;/xyzzy&gt;';&lt;br /&gt;&lt;br /&gt;myXMLDocument = myDOMParser.parseFromString(myXMLString,'text/xml');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt; &lt;p class="docText"&gt;Alright, now through one means or another, we have an XML  document loaded. This leaves only the question of what to do with it. That's a  minor detail; it isn't like it's leftover Thanksgiving turkey or anything like  that. We are not going to run out of ideas. Nobody has ever considered making  XML enchiladas or XML stroganoff. XML gives us two possible options; we can  either transform it or send it somewhere.&lt;/p&gt; &lt;p class="docText"&gt;We start with the option to transform it because I consider  myself something of an XSLT geek, especially when performing dangerous acts such  as client-side transformations. I'm always up for playing with anything that  could possibly make my job easier, and it doesn't get much easier than this.  There are only a couple simple rules to remember when using XSLT with Sarissa:  The XML is an XML document, and the XSL style sheet is also an XML document.  That's all there is to it, and &lt;a class="docLink" href="#ch16list04"&gt;Listing  16-4&lt;/a&gt; presents an example.&lt;/p&gt;&lt;a name="ch16list04"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDAAPJ0I"&gt;Listing 16-4. XSLT with Sarissa&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;var myXMLDocument = Sarissa.getDomDocument();&lt;br /&gt;var myXSLDocument = Sarissa.getDomDocument();&lt;br /&gt;var myXSLTProcessor = new XSLTProcessor();&lt;br /&gt;var myXMLTransformed;&lt;br /&gt;&lt;br /&gt;// Synchronous load of XML document&lt;br /&gt;&lt;br /&gt;myXMLDocument.async = false;&lt;br /&gt;myXMLDocument.load("jeckle.xml");&lt;br /&gt;&lt;br /&gt;// Synchronous load of XSL stylesheet&lt;br /&gt;myXSLDocument.async = false;&lt;br /&gt;myXSLDocument.load("hyde.xsl");&lt;br /&gt;&lt;br /&gt;// Import stylesheet&lt;br /&gt;myXSLTProcessor.importStylesheet(myXSLDocument);&lt;br /&gt;&lt;br /&gt;// Add a parameter 'take' value 'formula'&lt;br /&gt;myXSLTProcessor.setParameter(null, 'take', 'formula');&lt;br /&gt;&lt;br /&gt;// Transform, result in myXMLTransformed&lt;br /&gt;myXMLTransformed = myXSLTProcessor.transformToDocument(myXMLDocument);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt; &lt;p class="docText"&gt;&lt;a name="iddle1081"&gt;&lt;/a&gt;&lt;a name="iddle2227"&gt;&lt;/a&gt;&lt;a name="iddle2354"&gt;&lt;/a&gt;&lt;a name="iddle2568"&gt;&lt;/a&gt;With XSLT out of the way, this leaves  Sarissa's implementation of the &lt;tt&gt;XMLHttpRequest&lt;/tt&gt; object as the last piece  that I cover here. This implementation of the &lt;tt&gt;XMLHttpRequest&lt;/tt&gt; object  offers no surprises, unless you've jumped ahead to this chapter just to read  about Sarissa. If this is the case, allow me to explain that  &lt;tt&gt;XMLHttpRequest&lt;/tt&gt; is available in two distinct flavors: synchronous and  asynchronous. Synchronous is the one that waits quietly in line for its  response, and asynchronous is the one that does other things and expects a  callback with periodic updates. &lt;a class="docLink" href="#ch16list05"&gt;Listing  16-5&lt;/a&gt; shows an example of a synchronous request, and &lt;a class="docLink" href="#ch16list06"&gt;Listing 16-6&lt;/a&gt; shows an asynchronous request.&lt;/p&gt;&lt;a name="ch16list05"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDADZJ0I"&gt;Listing 16-5. Synchronous  Request&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;var myXMLHttpRequest = new XMLHttpRequest();&lt;br /&gt;&lt;br /&gt;myXMLHttpRequest.open('GET','manticore.xml',false);&lt;br /&gt;myXMLHttpRequest.send(null);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt;&lt;a name="ch16list06"&gt;&lt;/a&gt; &lt;h5 class="docExampleTitle" id="title-IDAUZJ0I"&gt;Listing 16-6. Asynchronous  Request&lt;/h5&gt; &lt;p&gt; &lt;table width="90%" border="1" cellpadding="5" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td&gt;&lt;pre&gt;var myXMLHttpRequest = new XMLHttpRequest();&lt;br /&gt;&lt;br /&gt;myXMLHttpRequest.open('GET','ELP.xml',true);&lt;br /&gt;&lt;br /&gt;myXMLHttpRequest.onreadystatechange = function() {&lt;br /&gt; if(myXMLHHttpRequest.readyState == 4)&lt;br /&gt;   alert('Done.');&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;myXMLHttpRequest.send(null);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/p&gt; &lt;p class="docText"&gt;&lt;a name="iddle1065"&gt;&lt;/a&gt;&lt;a name="iddle1795"&gt;&lt;/a&gt;&lt;a name="iddle1799"&gt;&lt;/a&gt;&lt;a name="iddle1990"&gt;&lt;/a&gt;If you're interested in using Sarissa  for an Ajax application or any web application of your own, I heartily recommend  it. The source code for Sarissa is available for download from SourceForge.net,  whose URL is, coincidentally, &lt;a class="docLink" href="http://www.sourceforge.net/" target="_blank"&gt;www.sourceforge.net&lt;/a&gt;. If you're unfamiliar with  SourceForge.net, I recommend that you put aside an afternoon, and about 30 blank  CDs, and peruse their selections of open source goodies. In addition to a vast  array of software, there is, amazingly enough, documentation to go along with  the software. It, like Sarissa, is well worth the time.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-2495983116550564918?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/2495983116550564918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/16_784.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2495983116550564918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2495983116550564918'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/16_784.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-1398083904616620803</id><published>2008-12-13T10:52:00.000-08:00</published><updated>2009-01-26T12:34:23.804-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>&lt;h3 class="docSection1Title" id="title-IDAPKTNO"&gt;16.2. JSON and JSON-RPC&lt;/h3&gt; &lt;p class="docText"&gt;There's definitely a Greek theme with many of the names  involved with using the &lt;tt&gt;XMLHttpRequest&lt;/tt&gt; object. First there is Ajax  itself, a legendary hero, followed by Microsoft's version called ATLAS, one of  the Titans. Finally, there is JSON, pronounced "Jason," which stands for  JavaScript Object Notation.&lt;/p&gt;&lt;a name="ch16lev2sec2"&gt;&lt;/a&gt; &lt;h4 class="docSection2Title" id="title-IDA3KTNO"&gt;16.2.1. JavaScript Object  Notation&lt;/h4&gt; &lt;p class="docText"&gt;Although I am by no means an expert on the subject, JavaScript  Object Notation (JSON) works as a kind of replacement for XML. This might sound  a little weird, but it makes perfect sense when viewed from a cross-browser  point of view. The reason for this is that more web browsers support JavaScript  than XML. This is just another way to distribute applications to as many people  as possible.&lt;/p&gt; &lt;p class="docText"&gt;JSON appears to work something along the lines of children's  building blocks. With blocks, a few basic shapes are used in conjunction with  imagination to create complex structures. The same can be said of JSON: A few  basic "shapes" are used in conjunction with imagination to create complex  structures. The only difference is that whereas children's blocks result in  physical structures, JSON results in logical structures.&lt;/p&gt; &lt;p class="docText"&gt;Let's take a look at the two basic data structures (blocks)  that are used to create more complex structures in JSON. The first of these  basic data structures is the name-value pair, which really isn't anything that  we have not already seen in earlier chapters. Just think along the lines of a  JavaScript collection or associative array, and you'll be fine.&lt;/p&gt; &lt;p class="docText"&gt;The second basic data structure in JSON has the formidable  description of "an ordered list of values." Ooh, sounds scary. In fact, it  sounds a lot scarier than its actual name, array. Say "an ordered list of  values," and people will pay attention; say "array," and unless you're talking  about an array of missile silos, nobody cares.&lt;/p&gt; &lt;p class="docText"&gt;&lt;a name="iddle1084"&gt;&lt;/a&gt;These structures, in turn, are used to  create somewhat more complex structures. The first of these more complex  structures is an object; such objects consist of an unordered list of name-value  pairs, with the following syntax for an empty object:&lt;/p&gt; &lt;div class="docText"&gt;&lt;pre&gt;object_name { }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p class="docText"&gt;Of course, an empty object isn't very useful, so it is  necessary to add members as string-value pairs. Of course, sometimes saying  nothing is enough.&lt;/p&gt; &lt;p class="docText"&gt;That is a high-level (as in, orbital) view of the concepts  behind JSON. All we need to look at now is the actual syntax. After all, because  the information going back and forth from the web server and the web browser has  to be text, an internal representation of a JavaScript array would probably  cause some problems when trying to send it to and fro.&lt;/p&gt;&lt;h3 class="docSection1Title" id="title-IDAPKTNO"&gt;16.2. JSON and JSON-RPC&lt;/h3&gt; &lt;p class="docText"&gt;There's definitely a Greek theme with many of the names  involved with using the &lt;tt&gt;XMLHttpRequest&lt;/tt&gt; object. First there is Ajax  itself, a legendary hero, followed by Microsoft's version called ATLAS, one of  the Titans. Finally, there is JSON, pronounced "Jason," which stands for  JavaScript Object Notation.&lt;/p&gt;&lt;a name="ch16lev2sec2"&gt;&lt;/a&gt; &lt;h4 class="docSection2Title" id="title-IDA3KTNO"&gt;16.2.1. JavaScript Object  Notation&lt;/h4&gt; &lt;p class="docText"&gt;Although I am by no means an expert on the subject, JavaScript  Object Notation (JSON) works as a kind of replacement for XML. This might sound  a little weird, but it makes perfect sense when viewed from a cross-browser  point of view. The reason for this is that more web browsers support JavaScript  than XML. This is just another way to distribute applications to as many people  as possible.&lt;/p&gt; &lt;p class="docText"&gt;JSON appears to work something along the lines of children's  building blocks. With blocks, a few basic shapes are used in conjunction with  imagination to create complex structures. The same can be said of JSON: A few  basic "shapes" are used in conjunction with imagination to create complex  structures. The only difference is that whereas children's blocks result in  physical structures, JSON results in logical structures.&lt;/p&gt; &lt;p class="docText"&gt;Let's take a look at the two basic data structures (blocks)  that are used to create more complex structures in JSON. The first of these  basic data structures is the name-value pair, which really isn't anything that  we have not already seen in earlier chapters. Just think along the lines of a  JavaScript collection or associative array, and you'll be fine.&lt;/p&gt; &lt;p class="docText"&gt;The second basic data structure in JSON has the formidable  description of "an ordered list of values." Ooh, sounds scary. In fact, it  sounds a lot scarier than its actual name, array. Say "an ordered list of  values," and people will pay attention; say "array," and unless you're talking  about an array of missile silos, nobody cares.&lt;/p&gt; &lt;p class="docText"&gt;&lt;a name="iddle1084"&gt;&lt;/a&gt;These structures, in turn, are used to  create somewhat more complex structures. The first of these more complex  structures is an object; such objects consist of an unordered list of name-value  pairs, with the following syntax for an empty object:&lt;/p&gt; &lt;div class="docText"&gt;&lt;pre&gt;object_name { }&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p class="docText"&gt;Of course, an empty object isn't very useful, so it is  necessary to add members as string-value pairs. Of course, sometimes saying  nothing is enough.&lt;/p&gt; &lt;p class="docText"&gt;That is a high-level (as in, orbital) view of the concepts  behind JSON. All we need to look at now is the actual syntax. After all, because  the information going back and forth from the web server and the web browser has  to be text, an internal representation of a JavaScript array would probably  cause some problems when trying to send it to and fro&lt;/p&gt;&lt;h3 class="docSection1Title" id="680422-974"&gt;16.3. ATLAS&lt;/h3&gt; &lt;p class="docText"&gt;ATLAS is Microsoft's answer to Ajax. Talk about a group that  suffers from the "not invented here" syndrome. For those of you who are  unfamiliar with this syndrome, it goes something along the lines of this:&lt;/p&gt; &lt;div style="font-weight: bold;"&gt; &lt;ol class="docList" type="1"&gt;&lt;li&gt; &lt;div style="font-weight: normal;"&gt; &lt;p class="docList"&gt;If we didn't invent it, then it is evil.&lt;/p&gt;&lt;/div&gt; &lt;/li&gt;&lt;li&gt; &lt;div style="font-weight: normal;"&gt; &lt;p class="docList"&gt;If we can sell a knock-off, then the original is evil and ours  is innovative.&lt;/p&gt;&lt;/div&gt; &lt;/li&gt;&lt;li&gt; &lt;div style="font-weight: normal;"&gt; &lt;p class="docList"&gt;In a product this innovative, there are bound to be some bugs,  but we're not at fault.&lt;/p&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt; &lt;p class="docText"&gt;The first time that I encountered this syndrome was in a  computer terminal that was manufactured by the company I worked at. It had a  detached keyboard that must have weighed 20 kilos or so, but it was considered  superior to those terminals with keyboards that could be placed on one's lap,  which is, in my opinion, the purpose of a detached keyboard.&lt;/p&gt; &lt;p class="docText"&gt;Over the years, I've encountered the syndrome in various  locations, usually associated with some kind of kludge. Usually it was a  software kludge, either a homegrown procedure or utility that might have filled  some kind of need, probably back during the Pliocene. Nevertheless, whatever it  was, it was created locally and was, therefore, better than anything from any  other source.&lt;/p&gt; &lt;p class="docText"&gt;Of course, there is an alternative reason for Microsoft  creating ATLAS beyond the "not invented here" syndrome. Perhaps Microsoft  intends to either Balkanize the technology by creating incompatible alternatives  or attempt to &lt;a name="iddle1161"&gt;&lt;/a&gt;&lt;a name="iddle2501"&gt;&lt;/a&gt;seize control by  having their own flavor. There is, however, the additional possibility that they  have allowed themselves to be blindsided again. Personally, I am most fond of  the last possibility because it is kind of reassuring to think that the company  that some consider to be "The Evil Empire" has once again missed the bus.&lt;/p&gt;&lt;a name="ch16lev2sec3"&gt;&lt;/a&gt; &lt;h4 class="docSection2Title" id="title-IDAO2ELF"&gt;16.3.1. A Picture of ATLAS&lt;/h4&gt; &lt;p class="docText"&gt;Unfortunately, to use Microsoft's ATLAS technologies, it is  necessary to have a machine running Windows and a copy of Visual Studio 2005.  Although my laptop does run Windows XP Professional, I don't have a copy of  Visual Studio 2005, and with a price tag of $549 for the Professional version,  it isn't something that I will be purchasing in the near future. After all, $549  will buy a large number of seasons of &lt;span class="docEmphasis"&gt;Stargate  SG1,&lt;/span&gt; Gummi Lab Rats, and turkey club sandwiches. For mad scientists, it  is all a matter of priorities&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-1398083904616620803?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/1398083904616620803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/16_13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1398083904616620803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/1398083904616620803'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/16_13.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-6162223816299426240</id><published>2008-12-13T10:50:00.000-08:00</published><updated>2009-01-26T12:34:23.804-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ajax And CSS'/><title type='text'></title><content type='html'>&lt;h3 class="docSection1Title" id="title-IDAD1XOO"&gt;16.4. The World Wide Web  Consortium&lt;/h3&gt; &lt;p class="docText"&gt;As I stated earlier, the World Wide Web Consortium is, in most  instances, the source of all things Web related. For this reason, I recommend  that you occasionally visit its website, &lt;a class="docLink" href="http://www.w3.org/" target="_blank"&gt;www.w3.org&lt;/a&gt;, to peruse the home page  and see if there is anything new. In fact, this is one of those great spots to  determine which skill to learn next. After all, unless we keep our skills  current, or even a little more than current, it is quite possible that we could  go the way of the dinosauror, at least, the way of the majority of American  steel workers.&lt;/p&gt; &lt;p class="docText"&gt;The World Wide Web Consortium is also one of those websites,  like SourceForge, where it is possible to find some free goodies. However,  unlike SourceForge, most people think of only documentation when they think of  the World Wide Web Consortium. Fortunately, there is much more to the World Wide  Web Consortium than a mere collection of HTML pages and PDF files. Many people  don't realize that, in addition to the all the documents describing various  technologies, there are quite often documents describing support for those  various technologiessuch as which web browsers support CSS Level 1, information  that can be of some use when shopping for a new web browser.&lt;/p&gt;&lt;br /&gt;16.5. Web Browsers&lt;br /&gt;The scary part about this section is that I had to actually look to see which web browsers are installed on my Toshiba notebook. Over the last several months, my collection has grown beyond my usual two browsers to include the following (in alphabetical order):&lt;br /&gt;&lt;br /&gt;Firefox (www.mozilla.org)&lt;br /&gt;&lt;br /&gt;Flock (www.flock.com)&lt;br /&gt;&lt;br /&gt;Microsoft Internet Explorer (www.microsoft.com)&lt;br /&gt;&lt;br /&gt;Netscape (http://browser.netscape.com)&lt;br /&gt;&lt;br /&gt;Opera (www.opera.com)&lt;br /&gt;&lt;br /&gt;In addition to adding browsers beyond the original two, several Firefox upgrades were installed during the same timeframe.&lt;br /&gt;&lt;br /&gt;All in all, I discovered several interesting things about these browsers and myself. The first is that, as annoying as Microsoft Internet Explorer is, it pales in comparison to Opera. Opera is closed as tight as an oyster. In addition, some versions of Opera lie, claiming to be Microsoft Internet Explorer. This wouldn't be a problem if it behaved the same way as Microsoft Internet Explorer, but, unfortunately, it doesn't. In the end, I was forced to abandon Opera.&lt;br /&gt;&lt;br /&gt;Of the remaining browsers, Firefox, Flock, and Netscape are all based upon Gecko, which means that if something works in one, it should work in all. In fact, I wasn't surprised to find this to be the case. Talk about consistency!&lt;br /&gt;&lt;br /&gt;However, I want to point out one item concerning these browsers. Because they are open source, they have a tendency to change more often than Microsoft Internet Explorerbut, then, years change more often than Microsoft Internet Explorer. This could be an issue in testing to keep in mind.&lt;br /&gt;&lt;br /&gt;Finally, there is Microsoft Internet Explorer, which, at this time, is still the number one web browser in use. Unlike the other browsers, unless you're running Windows or have an Apple computer, you're pretty much hosed if you want to run Internet Explorer. But there's always Firefox or Flock or Netscape.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-6162223816299426240?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/6162223816299426240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/16.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/6162223816299426240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/6162223816299426240'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/16.html' title=''/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5376888919047069366</id><published>2008-12-12T13:10:00.000-08:00</published><updated>2009-02-01T16:10:50.395-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Free Ebook Ajax'/><title type='text'>ENTERPRISE AJAX</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://freelibraryebooks.blogspot.com/2008/12/enterprise-ajax.html"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 221px; height: 295px;" src="http://1.bp.blogspot.com/_ok5-nbBFNYc/SSE-Kmj3TxI/AAAAAAAAAJA/L_yBelSx4gI/s400/buku7.GIF" alt="" id="BLOGGER_PHOTO_ID_5269561390870777618" border="0" /&gt;&lt;/a&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/enterprise-ajax.html"&gt;ENTERPRISE AJAX&lt;/a&gt;&lt;br /&gt;Strategies for Building High Performance Web Applications Dave Johnson, &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/enterprise-ajax.html"&gt;Alexei White&lt;/a&gt;, and Andre Charland Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this book, and the publisher was aware of a trademark claim, the designations have been printed with initial capital letters or in all capitals. The authors and publisher have taken care in the preparation of this book, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed&lt;br /&gt;for incidental or consequential damages in connection with or arising out of the use of the information or programs contained herein. The publisher offers excellent discounts on this book when ordered in quantity for bulk purchases or special sales, which may include electronic &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/enterprise-ajax.html"&gt;versions and/or custom covers&lt;/a&gt; and content particular to your business, training goals, marketing focus, and branding interests. For more information, please &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/enterprise-ajax.html"&gt;contact: U.S&lt;/a&gt;. Corporate and Government Sales (800) 382-3419 corpsales@pearsontechgroup.com For sales outside the United States, please contact: International Sales international@pearsoned.com&lt;br /&gt;&lt;a href="http://www.ziddu.com/download/2636371/Prentice.Hall.Enterprise.AJAX.Jul.2007.pdf.html"&gt;Download Link&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5376888919047069366?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5376888919047069366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/enterprise-ajax.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5376888919047069366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5376888919047069366'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/enterprise-ajax.html' title='ENTERPRISE AJAX'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_ok5-nbBFNYc/SSE-Kmj3TxI/AAAAAAAAAJA/L_yBelSx4gI/s72-c/buku7.GIF' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-4650178503011616912</id><published>2008-12-12T13:08:00.000-08:00</published><updated>2009-04-27T11:53:56.488-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Free Ebook Ajax'/><title type='text'>Ajax In Action</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://freelibraryebooks.blogspot.com/2008/12/ajax-in-action.html"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 242px; height: 320px;" src="http://1.bp.blogspot.com/_ok5-nbBFNYc/SSE_Czbyv_I/AAAAAAAAAJI/zxjZv192rwg/s400/buku.png" alt="Ajax In Action" id="BLOGGER_PHOTO_ID_5269562356399259634" border="0" /&gt;&lt;/a&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/ajax-in-action.html"&gt;Ajax in Action&lt;/a&gt;&lt;br /&gt;DAVE CRANE  ERIC PASCARELLO&lt;br /&gt;WITH DARREN JAMES For online information and ordering of this and other Manning books, please go to www.manning.com. The publisher offers discounts on this book when ordered in quantity. For more information, please contact: Special Sales Department&lt;br /&gt;Manning Publications Co. 209 Bruce Park Avenue Fax: (203) 661-9018 Greenwich, CT 06830 email: orders@manning.com ©2006 by Manning Publications Co. &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/ajax-in-action.html"&gt;All rights reserved&lt;/a&gt;. No part of this publication may be reproduced, stored in a retrieval system, or transmitted,&lt;br /&gt;in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher. Many of the designations used by manufacturers and sellers to distinguish their products&lt;br /&gt;are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademark claim, the designations have been printed in initial caps or all caps. Recognizing the importance of preserving what has been written, it is Manning’s policy to have the &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/ajax-in-action.html"&gt;books&lt;/a&gt; they publish printed on acid-free paper, and we exert our best efforts to that end&lt;br /&gt;&lt;a href="http://www.ziddu.com/download/2636265/Manning.Ajax.in.Action.pdf.html"&gt;Download Link&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-4650178503011616912?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/4650178503011616912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/ajax-in-action.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4650178503011616912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/4650178503011616912'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/ajax-in-action.html' title='Ajax In Action'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_ok5-nbBFNYc/SSE_Czbyv_I/AAAAAAAAAJI/zxjZv192rwg/s72-c/buku.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5910401252489492137</id><published>2008-12-12T13:02:00.001-08:00</published><updated>2009-04-27T11:50:42.185-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Free Ebook Ajax'/><title type='text'>Advanced Ajax</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://freelibraryebooks.blogspot.com/2008/12/advanced-ajax.html"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 301px; height: 400px;" src="http://2.bp.blogspot.com/_ok5-nbBFNYc/SSE7hdlFi0I/AAAAAAAAAI4/NvV-eVs1zOE/s400/buku5.GIF" alt="Advanced Ajax" id="BLOGGER_PHOTO_ID_5269558485062093634" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/advanced-ajax.html"&gt;Advanced Ajax&lt;/a&gt;&lt;br /&gt;Architecture and Best Practices Shawn M. Lauriat&lt;br /&gt;Upper Saddle River, NJ • Boston • Indianapolis • San Francisco New York • Toronto • Montreal • London • Munich • Paris • Madrid Cape Town • Sydney • Tokyo • Singapore • Mexico CityMany of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in this &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/advanced-ajax.html"&gt;book&lt;/a&gt;, and the publisher was aware of a trademark claim, the designations have been printed with initial capital letters or in&lt;br /&gt;all capitals. The author and publisher have taken care in the preparation of this book, but make no expressed or implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed for incidental or consequential damages in connection with or arising out of the use of the information or &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/advanced-ajax.html"&gt;programs&lt;/a&gt; contained herein.&lt;br /&gt;The publisher offers excellent discounts on this book when ordered in quantity for bulk purchases or special sales, which may include electronic versions and/or custom covers and content particu-lar to your business, training goals, marketing focus, and branding interests. For more informa-tion, please contact: U.S. Corporate and Government Sales (800) 382-3419 corpsales@pearsontechgroup.com &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/advanced-ajax.html"&gt;For sales&lt;/a&gt; outside the United States, please contact: International Sales international@pearsoned.com&lt;br /&gt;&lt;a href="http://www.ziddu.com/download/2636498/asd.pdf.html"&gt;Download Link&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5910401252489492137?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5910401252489492137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/advanced-ajax.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5910401252489492137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5910401252489492137'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/advanced-ajax.html' title='Advanced Ajax'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_ok5-nbBFNYc/SSE7hdlFi0I/AAAAAAAAAI4/NvV-eVs1zOE/s72-c/buku5.GIF' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-5558268395381225720</id><published>2008-12-12T12:59:00.000-08:00</published><updated>2009-02-01T16:16:17.429-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Free ebook Download'/><category scheme='http://www.blogger.com/atom/ns#' term='Ebook Networking'/><title type='text'>Network Programing Wiith TCP/IP</title><content type='html'>&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/network-programing-wiith-tcpip.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_ok5-nbBFNYc/SSLAslMiu8I/AAAAAAAAAJo/1z-QV6JVDkc/s320/networking.GIF" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/network-programing-wiith-tcpip.html"&gt;Three interrelated aspects:&lt;/a&gt;&lt;br /&gt;m TCP/IP protocol suite m standard Internet applications&lt;br /&gt;m coding using UNIX sockets API Books:&lt;br /&gt;1. W. Richard Stevens,  &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/network-programing-wiith-tcpip.html"&gt;"TCP/IP Illustrated&lt;/a&gt;.  Vol. 1: The protocols",  Addison Wesley,  1994,  (ISBN 0-201-63346-9).&lt;br /&gt;Explains the protocols using network monitoring tools without programming.&lt;br /&gt;2. Douglas E. Comer and David L. Stevens,  "Internetworking with&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/network-programing-wiith-tcpip.html"&gt; TCP/IP&lt;/a&gt;. Vol.3: Client-server programming and applications BSD socket version", Prentice Hall,  1993,  (ISBN 0-13-020272-X). Good book about principles of client/server design.  Assumes you have some knowledge or at least some other reference for actual programming.&lt;br /&gt;3. Michael Santifaller , translated by Stephen S. Wilson, "TCP/IP and ONC/NFS internetworking in a UNIX  environment", 2nd Edition,  Addison Wesley,  1994,&lt;br /&gt;(ISBN 0-201-42275-1). Covers more ground less deeply.  Translation from German seems good.&lt;br /&gt;4. W. Richard Stevens,  "&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/network-programing-wiith-tcpip.html"&gt;UNIX Network Programming&lt;/a&gt;", Prentice Hall,  1990, (ISBN 0-13-949876-1). A programming book.  I'm waiting for a copy, but Stevens is a good writer and&lt;br /&gt;this book is recommended by other authors.&lt;br /&gt;&lt;a href="http://www.ziddu.com/download/2688840/TCP-IP-complete.pdf.html"&gt;Download Link&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-5558268395381225720?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/5558268395381225720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/network-programing-wiith-tcpip.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5558268395381225720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/5558268395381225720'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/network-programing-wiith-tcpip.html' title='Network Programing Wiith TCP/IP'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_ok5-nbBFNYc/SSLAslMiu8I/AAAAAAAAAJo/1z-QV6JVDkc/s72-c/networking.GIF' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-7488841064479752259</id><published>2008-12-12T12:57:00.000-08:00</published><updated>2009-02-01T16:17:44.906-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Free ebook Download'/><title type='text'>Nautilus500 Installation Manual</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/nautilus500-installation-manual.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_ok5-nbBFNYc/SSLBYwYJ8NI/AAAAAAAAAJw/-5NsaoAce8s/s320/nautilus.GIF" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/nautilus500-installation-manual.html"&gt;Included Parts&lt;/a&gt; In the accessories bag you will find the&lt;br /&gt;following parts: 1pc. Cool block with 8ft of tubing&lt;br /&gt;(4 ft on each for intake and exhaust) 1pc. AMD Athlon64 (Socket 754, 939, and 940) retention bracket (2 pc. bracket + 1 pc. screw + 1 pc. metal plate) 1pc. Intel LGA 775 retention bracket (1 pc. bracket + 4 pc. standoff)&lt;br /&gt;1pc. Intel Socket 478 retention bracket&lt;br /&gt;1pc. Foam Pad&lt;br /&gt;1pc. Syringe with thermal grease&lt;br /&gt;1pc. PCI pass through bracket with internal 4 pin power  connecter 1pc. Power extension cable 2pc. Quick connect self sealing connectors 2pc. Quick grip clamps 1pc. Bottle of coolant 1pc. Operation manual Attaching the CPU water block For all types of Central Processing Units  (CPU)&lt;br /&gt;you will need to turn off your system and disconnect the power. It is recommended to ground yourself in order to prevent any transfer of Electrostatic Discharge (ESD) to your system components while installing the Nautilus500&lt;br /&gt;external water cooling kit. It is required to remove the&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/nautilus500-installation-manual.html"&gt; current CPU&lt;/a&gt; cooling mechanism from your&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/nautilus500-installation-manual.html"&gt; system&lt;/a&gt; prior to installing the Nautilus500 CPU water block. This includes removal of the thermal interface &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/nautilus500-installation-manual.html"&gt;material (TIM)&lt;/a&gt; that is used in conjunction with the stock CPU cooling mechanism. Please see the specific installation instructions listed below for your&lt;br /&gt;specific type of CPU.&lt;br /&gt;&lt;a href="http://www.ziddu.com/download/2688853/Nautilus500.pdf.html"&gt;Download Link&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-7488841064479752259?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/7488841064479752259/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/nautilus500-installation-manual.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7488841064479752259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/7488841064479752259'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/nautilus500-installation-manual.html' title='Nautilus500 Installation Manual'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_ok5-nbBFNYc/SSLBYwYJ8NI/AAAAAAAAAJw/-5NsaoAce8s/s72-c/nautilus.GIF' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-8717224343200862840</id><published>2008-12-12T12:55:00.000-08:00</published><updated>2009-02-01T16:19:43.224-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Free ebook Download'/><category scheme='http://www.blogger.com/atom/ns#' term='Free Ebook c++'/><title type='text'>C++ Professional Programer's</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/c-professional-programers.html" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_ok5-nbBFNYc/SSLC2frvEzI/AAAAAAAAAJ4/vPdAHupsjo8/s320/c%2B%2B.GIF" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/c-professional-programers.html"&gt;ANSI/ISO C++ Professional&lt;/a&gt;&lt;br /&gt;Programmer's Handbook The precursors of object-oriented programming can be traced back to the late 1960's: Classes, inheritance and virtual member functions were integral features of Simula67, a programming language that was mainly used for writing event-driven simulations. When Smalltalk first appeared back in 1972, it offered a pure object-oriented programming environment. In fact, Smalltalk defined object-oriented programming. This style of programming was so innovative and revolutionary at the time that it took more than a decade for it to become a standard in the software industry. Undoubtedly, the emergence of&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/c-professional-programers.html"&gt; C++&lt;/a&gt; in the early '80s provided the most considerable contribution to this revolution.&lt;br /&gt;The Origins of C++ In 1979, a young engineer at Bell (now AT&amp;amp;T) Labs, Bjarne Stroustrup, started to experiment with extensions to &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/c-professional-programers.html"&gt;C&lt;/a&gt; to make it a better tool for implementing large-scale projects. In those days, an average project consisted of tens of thousands of lines of &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/c-professional-programers.html"&gt;code&lt;/a&gt; (LOC).&lt;br /&gt;&lt;a href="http://www.ziddu.com/download/2688889/CProfessionalProgrammersHandbook.pdf.html"&gt;Download Link&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-8717224343200862840?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/8717224343200862840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/c-professional-programers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/8717224343200862840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/8717224343200862840'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/c-professional-programers.html' title='C++ Professional Programer&apos;s'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_ok5-nbBFNYc/SSLC2frvEzI/AAAAAAAAAJ4/vPdAHupsjo8/s72-c/c%2B%2B.GIF' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-2511966724163778394</id><published>2008-12-12T12:53:00.000-08:00</published><updated>2009-02-01T16:21:18.166-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Free Ebook Database'/><category scheme='http://www.blogger.com/atom/ns#' term='Free ebook Download'/><title type='text'>MySQL Database</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_ok5-nbBFNYc/SSLEBNiY4II/AAAAAAAAAKA/sg4nNV9NnFk/s1600-h/mysql.GIF" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img src="http://1.bp.blogspot.com/_ok5-nbBFNYc/SSLEBNiY4II/AAAAAAAAAKA/sg4nNV9NnFk/s320/mysql.GIF" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;Creating your &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/mysql-database.html"&gt;MySQL&lt;/a&gt; Database:&lt;br /&gt;Practical Design Tips and  &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/mysql-database.html"&gt;Techniques&lt;/a&gt; A short guide for everyone on how to structure their  data and set up their&lt;a href="http://freelibraryebooks.blogspot.com/2008/12/mysql-database.html"&gt; MySQL&lt;/a&gt; database tables eficiently and easily&lt;br /&gt;Copyright © 2006 Packt Publishing All rights reserved. No part of this &lt;a href="http://freelibraryebooks.blogspot.com/2008/12/mysql-database.html"&gt;book&lt;/a&gt; may be reproduced, stored in a retrieval  system, or transmitted in any form or by any means, without the prior written&lt;br /&gt;permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.&lt;br /&gt;Every effort has been made in the preparation of this book to ensure the accuracy of the information  resented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, Packt Publishing, nor its dealers or distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book. Packt Publishing has endeavored to provide trademark information about all the  companies and products mentioned in this book by the appropriate use of capitals.&lt;br /&gt;However, Packt Publishing cannot guarantee the accuracy of this information. First published: November 2006 Production Reference: 1141106  Published by Packt Publishing Ltd.&lt;br /&gt;32 Lincoln Road Olton Birmingham, B27 6PA, UK. ISBN 1-904811-30-2 www.packtpub.com&lt;br /&gt;&lt;a href="http://www.ziddu.com/download/2688922/MySQL.Database.pdf.html"&gt;Download Link&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2805388939215597768-2511966724163778394?l=freelibraryebooks.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://freelibraryebooks.blogspot.com/feeds/2511966724163778394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/mysql-database.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2511966724163778394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2805388939215597768/posts/default/2511966724163778394'/><link rel='alternate' type='text/html' href='http://freelibraryebooks.blogspot.com/2008/12/mysql-database.html' title='MySQL Database'/><author><name>Blogging Free Software</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/-KKW9u5Hyrj4/TmXCQLkhnRI/AAAAAAAAHpM/5wNlFPfTers/s1600/photo.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_ok5-nbBFNYc/SSLEBNiY4II/AAAAAAAAAKA/sg4nNV9NnFk/s72-c/mysql.GIF' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2805388939215597768.post-8375093183850264533</id><published>2008-12-12T12:51:00.000-08:00</published><updated>2009-02-01T16:23:06.166-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Free Ebook Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Free ebook Download'/><title type='text'></title><content type='html'>&lt;h3 class="post-title entry-title"&gt; &lt;a href="http://budak-sunda.blogspot.com/2008/11/core-jsp.html"&gt;Core JSP&lt;/a&gt; &lt;/h3&gt;   &lt;div class="separator" style="clear: both; text-align: c
