<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>chad's blog</title>
  <link rel="alternate" type="text/html" href="http://www.2tbsp.com/blogs/chad"/>
  <link rel="self" type="application/atom+xml" href="http://www.2tbsp.com/blog/1/atom/feed"/>
  <id>http://www.2tbsp.com/blog/1/atom/feed</id>
  <updated>2008-01-16T22:55:56-08:00</updated>
  <entry>
    <title>Evernote: Save notes, picts, clippings, and scribbles in one place</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/node/103" />
    <id>http://www.2tbsp.com/node/103</id>
    <published>2008-07-16T22:28:42-07:00</published>
    <updated>2008-07-17T16:29:07-07:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="Review" />
    <summary type="html"><![CDATA[<p><img src="http://www.evernote.com/about/img/logo.gif" alt="Evernote" width="228" height="60" align="right" />When inspiration or a sense of responsibility hits me I&#39;ll jot down a note or sketch something out with whatever means are available. If I&#39;m at work I&#39;ll send myself a to do list or a link to check out later in an email message. When out of reach of digitial devices, post it notes, scraps of paper, and the highly-versatile cocktail napkin receive the rest of my scribbles and scratches. Now if I could just remember where I&#39;ve squirreled away these bits of brilliance.<br />
Enter <a href="http://www.evernote.com">Evernote</a> , a new service to help you collect and manage your mental notes in each of their forms. Evernote allows you to send and store notes in text, image, and audio format through a variety of methods. I had signed up for a free account last month but hadn&#39;t had a chance to take Evernote for a spin until tonight.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><img src="http://www.evernote.com/about/img/logo.gif" alt="Evernote" width="228" height="60" align="right" />When inspiration or a sense of responsibility hits me I&#39;ll jot down a note or sketch something out with whatever means are available. If I&#39;m at work I&#39;ll send myself a to do list or a link to check out later in an email message. When out of reach of digitial devices, post it notes, scraps of paper, and the highly-versatile cocktail napkin receive the rest of my scribbles and scratches. Now if I could just remember where I&#39;ve squirreled away these bits of brilliance. </p>
<p>Enter <a href="http://www.evernote.com">Evernote</a> , a new service to help you collect and manage your mental notes in each of their forms. Evernote allows you to send and store notes in text, image, and audio format through a variety of methods. I had signed up for a free account last month but hadn&#39;t had a chance to take Evernote for a spin until tonight. </p>
<h2>The Basics</h2>
<p>It&#39;s easy to to get up and running. Submit notes through a web interface, your very own Evernote email address, desktop clients for Windows and Mac, or through mobile clients, including one for the iPhone. Create Notebooks to group your notes, add tags, and browse notes in either thumbnail or list views. </p>
<p><img src="/system/files/evernote-view.png" alt="Evernote notebooks" /> </p>
<h2>Email Notes and Attachments</h2>
<p>Each Evernote account comes with a custom email address. Save this address to your desktop and mobile device to send text notes with photo or scanned attachments. Subject titles are used as note titles and Evernote seems to do a good job retaining message format. No worries about spam here since Evernote account addresses are sufficiently randomized. </p>
<p>I was hoping that I&#39;d be able to rotate the image attachment shown below, but alas image rotation doesn&#39;t appear to be a feature yet. This was the only shortcoming I found with the service. </p>
<p><img src="/system/files/evernote-email.png" alt="Evernote Email" /></p>
<h2>
Send &#39;em from the Desktop<br />
</h2>
<p>Evernote  provides Mac and Windows users with handy desktop clients. Unfortunately Mac users with less than Leopard are left out. </p>
<p><img src="/system/files/evernote-mac.png" alt="Evernote for the Mac" /> </p>
<p>The client allows you to easily create and format new text notes, screenshots, clipboard contents, and iSight pictures. You can also keep notes in sync locally for offline viewing and search. </p>
<p><img src="/system/files/evernote-desktop.png" alt="Evernote desktop for the Mac" /></p>
<h2>
Speaking of search<br />
</h2>
<p>I was a bit skeptical of how well Evernote&#39;s OCR capabilities would work, especially with handwriting as poor as mine. I am blown away at how well Evernote&#39;s hand writing recognition worked. Keywords found in images are highlighted nicely as shown with the following &#39;FTP&#39; search result. </p>
<p><img src="/system/files/evernote-search.png" width="303" height="53" /></p>
<h2>
Impressive</h2>
<p>Overall I&#39;m really impressed with Evernote. I plan on piling my notes near my Brother multipage scanner for periodic capture and posting. No more rifling through piles of paper for me. Give it a try and see what you think. </p>
<p>&nbsp;</p>
    ]]></content>
  </entry>
  <entry>
    <title>Notes on Popular JavaScript Frameworks, Libraries, and Toolkits, Part 1</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/node/100" />
    <id>http://www.2tbsp.com/node/100</id>
    <published>2008-07-02T22:15:18-07:00</published>
    <updated>2008-07-03T11:16:35-07:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="JavaScript" />
    <category term="Review" />
    <category term="YUI" />
    <summary type="html"><![CDATA[<p>
Although my JavaScript development focus is currently on the <a href="http://developer.yahoo.com/yui/">Yahoo! User Interface Library (YUI)</a> I do try to keep up with some of the other libraries. Here I&#39;ll begin to offer up my recent notes and observations on five popular projects, Dojo, Ext JS, jQuery, Moo Tools, Prototype/Scriptaculous, and YUI.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
Although my JavaScript development focus is currently on the <a href="http://developer.yahoo.com/yui/">Yahoo! User Interface Library (YUI)</a> I do try to keep up with some of the other libraries. Here I&#39;ll begin to offer up my recent notes and observations on five popular projects, Dojo, Ext JS, jQuery, Moo Tools, Prototype/Scriptaculous, and YUI.<br />
<!--break-->
</p>
<p><img src="http://2tbsp.com/system/files/js-lib-logos.png" style="float:right" /></p>
<h2>What about &lt;insert JavaScript library here&gt;?</h2>
<p>
This is a fair question often asked while reading &quot;comparative literature.&quot; According to other blog posts on the subject, Google, benchmark test results, and web development job ads, the projects covered here have garnered more attention from the web development community than others.
</p>
<h2>JavaScript Projects According to Google</h2>
<p>
Last month Google gave an endorsement of sorts to jQuery, prototype/script.aculo.us, MooTools, and dojo by offering hosting of each through their <a href="http://code.google.com/apis/ajaxlibs/">AJAX Libraries API</a>. Any web developer in the world can now easily include the latest stable version of these libraries in their projects. I can&#39;t think of much higher praise for a project than a nod from Google. These projects can tout their selection and, more importantly, the  benefits of Google serving as their <a href="http://en.wikipedia.org/wiki/Content_Delivery_Network">CDN hosting service</a>.
</p>
<p>
Google probably isn&#39;t going to host a competitor&#39;s library, even if Yahoo! didn&#39;t provide <a href="http://developer.yahoo.com/yui/articles/hosting/">hosted versions of the YUI</a>. I&#39;m also guessing that the commercial component of Ext JS&#39;s dual licence ruled them out from the AJAX Library API.
</p>
<p>
<a href="http://trends.google.com">Google Trends</a> has become the latest judge in web popularity contests. Here&#39;s a Google Trend comparison of each project&#39;s web site: <a href="http://trends.google.com/websites?q=dojotoolkit.org%2C+extjs.com%2C+jquery.com%2C+prototypejs.org%2C+mootools.net&amp;geo=all&amp;date=all&amp;sort=0">dojotoolkit.org, extjs.com, jquery.com, prototypejs.org, mootools.net</a>.
</p>
<p><a href="http://www.scrnshots.com/users/ckieffer/screenshots/20330"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/20330/ScrnShotsDesktop-1214630240_large.png" /></a></p>
<p>
I initially included <a href="http://mochikit.com/">MochiKit</a> with the others but <a href="http://trends.google.com/websites?q=mochikit.com%2C+extjs.com%2C+jquery.com%2C+prototypejs.org%2C+mootools.net&amp;geo=all&amp;date=all&amp;sort=0">it did not fair well</a>. MochiKit is a well-established project with many merits and deserves an honorable mention here. Some will also note that the YUI isn&#39;t included. Yahoo! uses <em>http://developer.yahoo.com/yui/</em> instead of a dedicated subdomain for the YUI. The Google Trends report only showed data for <em>developer.yahoo.com</em>.
</p>
<h2>JavaScript Library Usage on Popular Sites</h2>
<p>
Pingdom, a server monitoring service, recently posted the results of a simple study of <a href="http://royal.pingdom.com/?p=305">JavaScript framework usage among top websites</a>. They chose to scan the HTML source of site home pages listed on the <a href="http://www.alexa.com/site/ds/top_sites?cc=US&amp;ts_mode=country&amp;lang=none">Alexa US Top 100</a> and the <a href="http://www.webware.com/html/ww/100/2008/winners.html">Webware Top 100 Web Apps</a>. They searched for specific keywords and file names associated with the use of Prototype, JQuery, MooTools, YUI, Dojo, ExtJS and MochiKit. The study includes a list of sites they found using each and basic summaries of the libraries (Note: My next post will expand on these summaries).
</p>
<p>
The study didn&#39;t find evidence of Dojo, Ext JS, or MochiKit in use on the site&#39;s home pages but the results should not be considered conclusive. I suspect that Ext JS usage would score quite high in a survey of corporate intranet sites. Ext JS provides formal training and support services which are typically valued in corporate IT environments. In regards to Dojo, I suspect that the recent <a href="http://devzone.zend.com/article/3545-Dojo-and-Zend-Framework-Partnership-Announcement">announcement of their partnership with the Zend Framework</a> will produce a spike in its usage after the 1.6 release of the Zend Framework later this summer.
</p>
<h2>JavaScript Size and Performance Benchmark Tests</h2>
<p>
Performance benchmark tests based on general and randomized cases may seem to provide a smoking gun when choosing one framework over another, but be careful. Regardless of the tester&#39;s reputation or methods, these tests weren&#39;t run against your application in your environment. Ahh, those darn variables always get in the way of simple calculations ;) Tests may reveal advantages in one framework but ultimately performance is determined by a framework coupled with your design ingenuity, coding skill, and infrastructure.
</p>
<p>
PBwiki recently conducted a <a href="http://jst.pbwiki.com/">JavaScript library performance benchmark test</a> that caught the interest of jQuery&#39;s creator, John Resig (for reasons that&#39;ll become more obvious in the next sentence). Of the libraries tested, jQuery did very well. Dojo and YUI were neck and neck in the middle of the pack. Prototype by itself was comparable to YUI and dojo but as soon as Scriptaculous was added to the mix, Prototype&#39;s performance seems to have suffered greatly. On his blog John provides <a href="http://ejohn.org/blog/library-loading-speed/">a summary of the test results</a> and emphasizes  why you <a href="http://ejohn.org/blog/the-performance-paradox/">shouldn&#39;t trust random-user-generated performance tests</a>. I wouldn&#39;t choose a library for a project solely on the numbers but I would likely cite poor results to discount one.
</p>
<h2>JavaScript Libraries in the Eyes of Employers</h2>
<p>
This aspect is of particular interest to those of you in the job market. If you&#39;re looking to expand your skill set, here are <a href="http://www.indeed.com/jobtrends?q=dojo%2C+extjs%2C+jquery%2C+mootools%2C+scriptaculous%2C+yui">the JavaScript libraries</a>  that <a href="http://www.indeed.com/">Indeed.com</a> says employers are looking for in their job ads.
</p>
<p>
<a href="http://www.scrnshots.com/users/ckieffer/screenshots/20458"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/20458/ScrnShotsDesktop-1214676849_large.png" /></a>
</p>
<p>
<em>Prototype</em> produced skewed results for obvious reasons and <em>Prototype js</em> didn&#39;t produce any results.
</p>
<p>
Obviously this is just a cursory comparison. I&#39;m currently spending some time with each project to provide a more thoughtful description of each. In the meantime, what were the deciding factors when you chose a specific library?
</p>
    ]]></content>
  </entry>
  <entry>
    <title>A Few Diversions</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/node/102" />
    <id>http://www.2tbsp.com/node/102</id>
    <published>2008-06-29T22:30:21-07:00</published>
    <updated>2008-06-29T22:36:53-07:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="Community/Social Networks" />
    <category term="Fun" />
    <category term="Sites" />
    <summary type="html"><![CDATA[<p><a href="http://scrnshots.com">ScrnShots.com</a> is yet another social networking site for the InterWeb. This one targets a small niche market, sharing screen shots. It may seem a bit too narrow of a focus, but I&#39;m going to give it a try for a bit. Specifically, I&#39;m going to start posting new screenshots used in tutorials and posts on this site. I&#39;ll also add it to my my list of design inspiration sites to review when I begin a new project.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><a href="http://scrnshots.com">ScrnShots.com</a> is yet another social networking site for the InterWeb. This one targets a small niche market, sharing screen shots. It may seem a bit too narrow of a focus, but I&#39;m going to give it a try for a bit. Specifically, I&#39;m going to start posting new screenshots used in tutorials and posts on this site. I&#39;ll also add it to my my list of design inspiration sites to review when I begin a new project.</p>
<p>ScrnShots includes all of the standard features, including tagging, favorites, feeds, and widgets. It also provides handy upload tools for both Mac and Windows. The Mac desktop uploader is available through a menu bar item and provides full screen, window, and area options. After capture you can easily caption and tag the screen shot then upload. </p>
<p><a href="http://wordle.net">Wordle.net</a>  is simple diversion for any typography or tag cloud fanatic. Enter a list of words and phrases or use a set of del.icio.us tags or the contents of an RSS feed to generate a stylized word cloud. Change the structure, colors, and font face to make the cloud your own.</p>
<p>Here&#39;s my del.icou.us tag cloud. </p>
<p><a href="http://scrnshots.com/users/ckieffer/screenshots/21038"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/21038/wordle-ckieffer_large.png" /></a></p>
<p>And here&#39;s one that brought a laugh followed by my own sad self realization :/
</p>
<p>
<a href="http://scrnshots.com/users/ckieffer/screenshots/21042"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/21042/wordle-funny_large.png" /></a>
</p>
<p>
Finally, if you like to doodle, <a href="http://www.scribbls.com/">Scribbls.com</a>  is for you. The idea is draw two things that create something totally different when they&#39;re combined. Words can&#39;t explain, so give it a try. Be sure to check the most hearted scribbls. </p>
<p><a href="http://scrnshots.com/users/ckieffer/screenshots/21050"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/21050/scribbls_bacon_large.png" /></a></p>
    ]]></content>
  </entry>
  <entry>
    <title>JavaScript Libraries Playing Nice with Others?</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/node/99" />
    <id>http://www.2tbsp.com/node/99</id>
    <published>2008-06-27T16:48:26-07:00</published>
    <updated>2008-06-27T16:51:41-07:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="JavaScript" />
    <category term="YUI" />
    <summary type="html"><![CDATA[<p>A common occurrence in Web 2.0 sites, and one that a recent <a href="http://royal.pingdom.com/?p=305">Pingdom study</a> notes, is the concurrent use of multiple JavaScript libraries. One explanation for this is that a required (more often desired) feature or widget may appear to only be available within one specific library.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>A common occurrence in Web 2.0 sites, and one that a recent <a href="http://royal.pingdom.com/?p=305">Pingdom study</a> notes, is the concurrent use of multiple JavaScript libraries. One explanation for this is that a required (more often desired) feature or widget may appear to only be available within one specific library.</p>
<p>This perception may have been true a few years ago but is certainly less likely today. What&#39;s more likely is that a developer sees a real or perceived obstacle in implementing or developing a widget with one library over another. &quot;Either the widget exists but I can&#39;t seem to install it or it&#39;s missing and I&#39;m having trouble building it.&quot;</p>
<p>Either way, I&#39;m beginning to develop more of a purist&#39;s view -- choose one framework for a project or environment and stick with it.</p>
<p>If a widget doesn&#39;t exist in a framework, I won&#39;t simply use another framework just to add it. Why you ask? Simplicity and performance. It&#39;s great that all of these JavaScript libraries reside in their own name space so as not to interfere with the others, but this makes it too easy to add unnecessary complexity and overhead to a site. </p>
<p>I&#39;ve developed a few sites that embed the <a href="http://gallery.menalto.com">Gallery Photo Manager</a> in <a href="http://drupal.org">Drupal</a>. At its core Gallery uses YUI while Drupal uses jQuery. To complicate matters I implemented a Script.aculo.us-based Lightbox effect. The use of Script.aculo.us introduced repetition in basic DOM handling functions that are already provided in YUI and jQuery. Although the repetition only adds up to a few extra kilobytes, these kilobytes add up.</p>
<p>I&#39;ve decided to replace the effect with a <a href="http://test.thecodecentral.com/demos/lightboxrev/lightbox.html">YUI equivalent</a>. One less library to complicate things and fewer file transfers to slow things down. What do you think? Are you using multiple JS libraries? Are you contemplating a JavaScript consolidation effort?</p>
    ]]></content>
  </entry>
  <entry>
    <title>How to Remove a Workspace in Eclipse under OS X</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/node/93" />
    <id>http://www.2tbsp.com/node/93</id>
    <published>2008-05-02T13:50:33-07:00</published>
    <updated>2008-05-03T10:28:03-07:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="Eclipse" />
    <category term="OS X" />
    <summary type="html"><![CDATA[<p>The other morning, before I had my morning coffee, I fired up Eclipse and when prompted to select my Workspace, I entered my password and hit return. Still in a haze, I wondered why I was looking at the default Workspace. After restarting and seeing my password in the selected Workspace I finally woke up. D'oh!</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>The other morning, before I had my morning coffee, I fired up Eclipse and when prompted to select my Workspace, I entered my password and hit return. Still in a haze, I wondered why I was looking at the default Workspace. After restarting and seeing my password in the selected Workspace I finally woke up. D'oh!</p>
<p>So where the heck is this Workspace list stored? I couldn't find the list under preferences. There wasn't a hidden settings file in my home directory. I then started poking around in /Applications/eclipse. Ah ha! Here's the setting file that contains recent workspaces.</p>
<p><div class="geshifilter"><pre class="geshifilter-html4strict">/Applications/eclipse/configuration/.settings/org.eclipse.ui.ide.prefs</pre></div></p>
<p>Opened this file up and deleted the workspace from the RECENT_WORKSPACES. I had to make sure that I didn't remove to many line feeds (\n) which separate each workspace. I'm not sure why eclipse stores these preferences in the Applications folder. Why isn't this information stored in my home directory? </p>
<p>Oh well. I may never make this mistake again, but you never know. Hope this helps someone else out there.</p>
    ]]></content>
  </entry>
  <entry>
    <title>YUI Rollover Part 2: Improving JavaScript Performance and Scalability</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/node/92" />
    <id>http://www.2tbsp.com/node/92</id>
    <published>2008-05-01T16:14:33-07:00</published>
    <updated>2008-05-01T16:27:40-07:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="JavaScript" />
    <category term="YUI" />
    <summary type="html"><![CDATA[<p>In my <a href="/node/91">previous article</a> we traded in old school JavaScript habits for unobtrusive methods and the Yahoo! User Interface Library (YUI). The YUI's Event and DOM extensions greatly simplify basic DOM scripting tasks. Let's build on this foundation and improve the rollover script's performance and scalability.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>In my <a href="/node/91">previous article</a> we traded in old school JavaScript habits for unobtrusive methods and the Yahoo! User Interface Library (YUI). The YUI's Event and DOM extensions greatly simplify basic DOM scripting tasks. Let's build on this foundation and improve the rollover script's performance and scalability.<!--break--></p>
<p>Thanks to <a href="/node/91#comment-2553">Nick</a> and <a href="/node/91#comment-2558">Dirk</a> for their comments on event listeners impact on script performance. Nick points out the fact that JavaScript performance will degrade as more buttons are added to the <a href="http://2tbsp.com/system/files/yui-rollover.html">example rollover menu</a>. The use of a DOM scripting technique called event delegation can greatly reduce performance hits sustained through the assignment of event listeners. </p>
<h2>Improve Performance through Event Delegation and Bubbling</h2>
<p>The current version of the rollover script loops through the menu container and assigns event listeners to each button. Assigning listeners to child elements this way can, and will, have a negative impact on performance. </p>
<div style="float:right; width:223px; text-align:right;">
<img src="http://2tbsp.com/system/files/fig-bubble.png" alt="Illustration of the DOM bubbling effect" /></p>
<div class="caption">credit: <a href="http://www.senocular.com/flash/tutorials/buttoncapturing/">Senocular.com</a></div>
</div>
<p>Let's use event delegation to simplify things. Event delegation leverages an inherit  browser behavior called "event bubbling". By default, when an event happens to an element's descendents, the event "bubbles up" through the DOM to the parent. </p>
<p>This means that we can assign event listeners to the menu rather than every button it contains. In our rollover example we can reduce the number of event listeners from 3 to just 1. Wow! We've just cut the work required to assign listeners by 66%. You can see that the performance savings of event delegation add up quickly.</p>
<p>We'll use the same HTML markup and CSS from the previous example. </p>
<p><div class="geshifilter"><pre class="geshifilter-html4strict"><span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;menu&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span></pre></div></p>
<p>Here's the updated script using the YUI's Event and DOM extensions. The script now uses Event's handy getTarget() method which captures the target of the current event.  </p>
<p><div class="geshifilter"><pre class="geshifilter-javascript">&lt;script type=<span style="color: #3366CC;">&quot;text/javascript&quot;</span>&gt;
<span style="color: #009900; font-style: italic;">// Create the menu object</span>
<span style="color: #003366; font-weight: bold;">var</span> roll = <span style="color: #66cc66;">&#123;</span>
  <span style="color: #009900; font-style: italic;">// The rollover function</span>
  over : <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>e<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #009900; font-style: italic;">// Capture the current target element</span>
    <span style="color: #003366; font-weight: bold;">var</span> elTarget = YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Event</span>.<span style="color: #006600;">getTarget</span><span style="color: #66cc66;">&#40;</span>e<span style="color: #66cc66;">&#41;</span>;
    <span style="color: #009900; font-style: italic;">// Step through this section of the DOM looking for a btn </span>
    <span style="color: #009900; font-style: italic;">// in the target's ancestory, stop at the menu container</span>
    <span style="color: #000066; font-weight: bold;">while</span> <span style="color: #66cc66;">&#40;</span>elTarget.<span style="color: #006600;">id</span> != <span style="color: #3366CC;">'menu'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
      <span style="color: #009900; font-style: italic;">// If we're over a btn, turn it on and stop</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">hasClass</span><span style="color: #66cc66;">&#40;</span>elTarget, <span style="color: #3366CC;">'btn'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> 
        YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">addClass</span><span style="color: #66cc66;">&#40;</span>elTarget, <span style="color: #3366CC;">'btn-over'</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #000066; font-weight: bold;">break</span>;
      <span style="color: #009900; font-style: italic;">// Keep looking one level up</span>
      <span style="color: #66cc66;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #66cc66;">&#123;</span>
        elTarget = elTarget.<span style="color: #006600;">parentNode</span>;
      <span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#125;</span>,
  <span style="color: #009900; font-style: italic;">// Reset menu styles</span>
  out : <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>e<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> btns = YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">getElementsByClassName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'btn'</span>, <span style="color: #3366CC;">'div'</span>, <span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span>;
    YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">removeClass</span><span style="color: #66cc66;">&#40;</span>btns, <span style="color: #3366CC;">'btn-over'</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>;
<span style="color: #009900; font-style: italic;">// Assign event listeners to just the menu</span>
YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Event</span>.<span style="color: #006600;">on</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'menu'</span>, <span style="color: #3366CC;">'mouseover'</span>, roll.<span style="color: #006600;">over</span><span style="color: #66cc66;">&#41;</span>;
YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Event</span>.<span style="color: #006600;">on</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'menu'</span>, <span style="color: #3366CC;">'mouseout'</span>, roll.<span style="color: #006600;">out</span><span style="color: #66cc66;">&#41;</span>;
&lt;/script&gt;</pre></div></p>
<p>Take a look at the <a href="http://2tbsp.com/system/files/yui-rollover2.html">functioning example</a>.</p>
<h2>Allow for Growth</h2>
<p>The updated rollover script gives us a big improvement in performance, but it doesn't scale at all. The script includes hardcoded references to a single menu. What if we want to add additional menus?</p>
<p>First, let's update the stylesheet to use classes, instead of an ID, to target and style rollover menus.</p>
<p><div class="geshifilter"><pre class="geshifilter-css"><span style="color: #6666ff;">.rollover</span> <span style="color: #66cc66;">&#123;</span> 
  <span style="color: #000000; font-weight: bold;">font</span>: <span style="color: #933;"><span style="color: #933;">85</span>%</span> Arial, Helvetica, san-<span style="color: #993333;">serif</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #6666ff;">.rollover</span> <span style="color: #6666ff;">.btn</span>, <span style="color: #6666ff;">.rollover</span> <span style="color: #6666ff;">.btn-over</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">background-color</span>: <span style="color: #cc00cc;">#e7e7e7</span>;
  <span style="color: #000000; font-weight: bold;">border-width</span>: <span style="color: #933;">2px</span>;
  <span style="color: #000000; font-weight: bold;">border-style</span>: <span style="color: #993333;">solid</span>;
  <span style="color: #000000; font-weight: bold;">color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">666</span></span>;
  <span style="color: #000000; font-weight: bold;">float</span>: <span style="color: #000000; font-weight: bold;">left</span>;
  <span style="color: #000000; font-weight: bold;">margin</span>: <span style="color: #933;">0</span> <span style="color: #933;">5px</span>;
  <span style="color: #000000; font-weight: bold;">width</span>: <span style="color: #933;">150px</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #6666ff;">.rollover</span> <span style="color: #6666ff;">.btn</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">border-color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">999</span></span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #6666ff;">.rollover</span> <span style="color: #6666ff;">.btn</span> a, <span style="color: #6666ff;">.rollover</span> <span style="color: #6666ff;">.btn-over</span> a <span style="color: #66cc66;">&#123;</span> 
  <span style="color: #000000; font-weight: bold;">color</span>: <span style="color: #cc00cc;">#fff</span>;
  <span style="color: #000000; font-weight: bold;">background-color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">999</span></span>;
  <span style="color: #000000; font-weight: bold;">display</span>: <span style="color: #993333;">block</span>;
  <span style="color: #000000; font-weight: bold;">padding</span>: <span style="color: #6666ff;"><span style="color: #933;">.3em</span></span> <span style="color: #6666ff;"><span style="color: #933;">.5em</span></span>;
  <span style="color: #000000; font-weight: bold;">text-decoration</span>: <span style="color: #993333;">none</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #6666ff;">.rollover</span> p <span style="color: #66cc66;">&#123;</span> 
  <span style="color: #000000; font-weight: bold;">clear</span>: <span style="color: #993333;">both</span>;
  <span style="color: #000000; font-weight: bold;">padding-top</span>: <span style="color: #933;">1em</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #6666ff;">.btn</span> p <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">padding</span>: <span style="color: #933;">0</span> <span style="color: #6666ff;"><span style="color: #933;">.5em</span></span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* Rollover styles */</span>
<span style="color: #6666ff;">.rollover</span> <span style="color: #6666ff;">.btn-over</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">border-color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">666</span></span>;
  <span style="color: #000000; font-weight: bold;">color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">000</span></span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #6666ff;">.rollover</span> <span style="color: #6666ff;">.btn-over</span> a <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">background-color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">666</span></span>;
<span style="color: #66cc66;">&#125;</span></pre></div></p>
<p>Next, apply the rollover class to a menu, or two.</p>
<p><div class="geshifilter"><pre class="geshifilter-html4strict"><span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;menu1&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;rollover&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Here's a menu.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
&nbsp;
<span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;menu2&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;rollover&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 4<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 4<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Here's another menu.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span></pre></div></p>
<p>The script now needs to include a method for adding event listeners to each of the rollover menus. This task is handled by menu.init() which is run once the page is loaded. The only other change is the use of the rollover class to stop our walk of the DOM.  </p>
<p><div class="geshifilter"><pre class="geshifilter-javascript">&lt;script type=<span style="color: #3366CC;">&quot;text/javascript&quot;</span>&gt;
<span style="color: #009900; font-style: italic;">// Create the menu object</span>
<span style="color: #003366; font-weight: bold;">var</span> roll = <span style="color: #66cc66;">&#123;</span>
  <span style="color: #009900; font-style: italic;">// Assign event listeners to all rollover menus, </span>
  <span style="color: #009900; font-style: italic;">// Isn't getElementsByClassName wonderful?!</span>
  init : <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> menus = YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">getElementsByClassName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'rollover'</span>, <span style="color: #3366CC;">'div'</span><span style="color: #66cc66;">&#41;</span>;
    YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Event</span>.<span style="color: #006600;">on</span><span style="color: #66cc66;">&#40;</span>menus, <span style="color: #3366CC;">'mouseover'</span>, roll.<span style="color: #006600;">over</span><span style="color: #66cc66;">&#41;</span>;    
    YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Event</span>.<span style="color: #006600;">on</span><span style="color: #66cc66;">&#40;</span>menus, <span style="color: #3366CC;">'mouseout'</span>, roll.<span style="color: #006600;">out</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>,
  <span style="color: #009900; font-style: italic;">// The rollover function, only change is using className instead of ID</span>
  over : <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>e<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #009900; font-style: italic;">// Capture the current target element</span>
    <span style="color: #003366; font-weight: bold;">var</span> elTarget = YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Event</span>.<span style="color: #006600;">getTarget</span><span style="color: #66cc66;">&#40;</span>e<span style="color: #66cc66;">&#41;</span>;
    <span style="color: #009900; font-style: italic;">// Step through this section of the DOM looking for a btn </span>
    <span style="color: #009900; font-style: italic;">// in the target's ancestory, stop at the menu container</span>
    <span style="color: #000066; font-weight: bold;">while</span> <span style="color: #66cc66;">&#40;</span>elTarget.<span style="color: #006600;">className</span> != <span style="color: #3366CC;">'rollover'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
      <span style="color: #009900; font-style: italic;">// If we're over a btn, turn it on and stop</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">hasClass</span><span style="color: #66cc66;">&#40;</span>elTarget, <span style="color: #3366CC;">'btn'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> 
        YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">addClass</span><span style="color: #66cc66;">&#40;</span>elTarget, <span style="color: #3366CC;">'btn-over'</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #000066; font-weight: bold;">break</span>;
      <span style="color: #009900; font-style: italic;">// Keep looking one level up</span>
      <span style="color: #66cc66;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #66cc66;">&#123;</span>
        elTarget = elTarget.<span style="color: #006600;">parentNode</span>;
      <span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#125;</span>,
  <span style="color: #009900; font-style: italic;">// Reset menu styles</span>
  out : <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>e<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> btns = YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">getElementsByClassName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'btn'</span>, <span style="color: #3366CC;">'div'</span>, <span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span>;
    YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">removeClass</span><span style="color: #66cc66;">&#40;</span>btns, <span style="color: #3366CC;">'btn-over'</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>;
&nbsp;
<span style="color: #009900; font-style: italic;">// Initialize all rollover menus when the page loads</span>
YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Event</span>.<span style="color: #006600;">on</span><span style="color: #66cc66;">&#40;</span>window, <span style="color: #3366CC;">'load'</span>, roll.<span style="color: #006600;">init</span><span style="color: #66cc66;">&#41;</span>;
&lt;/script&gt;</pre></div></p>
<p>And here's the working example of the <a href="http://2tbsp.com/system/files/yui-rollover-multi.html">rollover script that scales</a>.</p>
<h2>Conclusion</h2>
<p>So there you have it. A few simple examples illustrating how to improve performance and scalability in JavaScript. These are basic examples and hopefully they'll help you refactor your scripts to meet your site's needs. I highly recommend reading Peter-Paul Koch's explanation of mouse events and event order in the DOM and how each browser handles them. They helped me tremendously.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Introduction to Unobtrusive JavaScript, DOM Scripting, and the Yahoo! User Interface (YUI) Library</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/node/91" />
    <id>http://www.2tbsp.com/node/91</id>
    <published>2008-04-24T22:07:15-07:00</published>
    <updated>2008-05-06T16:01:18-07:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="HTML/CSS" />
    <category term="JavaScript" />
    <summary type="html"><![CDATA[<p>If you know JavaScript but have yet to make the leap to unobtrusive JavaScript, read on. I'll demonstrate how to upgrade a traditional DHTML rollover to an unobtrusive script and then to a script that leverages the Yahoo! User Interface Library's (YUI).</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>If you know JavaScript but have yet to make the leap to unobtrusive JavaScript, read on. I'll demonstrate how to upgrade a traditional DHTML rollover to an unobtrusive script and then to a script that leverages the Yahoo! User Interface Library's (YUI).<!--break--></p>
<h2>What is Unobtrusive JavaScript and DOM Scripting?</h2>
<p>Rather than hardcoding event handlers as HTML attributes, unobtrusive JavaScript assigns them using the DOM. Well-structured, valid HTML is a prerequisite to DOM scripting. Documents should declare a DOCTYPE, they should validate against the DOCTYPE, and presentational styles should be applied with CSS (read "should" as "life will be easier for everyone if you do"). Use a few targeted CSS ID and class selectors to define page layout. Don't go overboard on defining selectors, remember, <a href="/content/taking_your_css_skills_next_level">descendent selectors are your friend</a>.</p>
<p>I'll use a simple text-based rollover for demonstration purposes. In a perfect world, with perfect browsers, this effect would be created using the CSS pseudo hover class but, as you've probably guessed, it doesn't work in Internet Explorer 6. Here's a screenshot of what we're building.</p>
<p><img src="http://2tbsp.com/system/files/rollover.png" /></p>
<h2>The Rollover, Obtrusively Old School Style</h2>
<p>First, the style sheet. Nothing wrong here as long as these are stored in an external CSS file.</p>
<p><div class="geshifilter"><pre class="geshifilter-css"><span style="color: #cc00cc;">#menu</span> <span style="color: #66cc66;">&#123;</span> 
  <span style="color: #000000; font-weight: bold;">font</span>: <span style="color: #933;"><span style="color: #933;">85</span>%</span> Arial, Helvetica, san-<span style="color: #993333;">serif</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #cc00cc;">#menu</span> <span style="color: #6666ff;">.btn</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">background-color</span>: <span style="color: #cc00cc;">#e7e7e7</span>;
  <span style="color: #000000; font-weight: bold;">border-color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">999</span></span>;
  <span style="color: #000000; font-weight: bold;">border-style</span>: <span style="color: #993333;">solid</span>;
  <span style="color: #000000; font-weight: bold;">border-width</span>: <span style="color: #933;">2px</span>;
  <span style="color: #000000; font-weight: bold;">color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">666</span></span>;
  <span style="color: #000000; font-weight: bold;">float</span>: <span style="color: #000000; font-weight: bold;">left</span>;
  <span style="color: #000000; font-weight: bold;">margin</span>: <span style="color: #933;">0</span> <span style="color: #933;">5px</span>;
  <span style="color: #000000; font-weight: bold;">width</span>: <span style="color: #933;">150px</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #cc00cc;">#menu</span> <span style="color: #6666ff;">.btn</span> a <span style="color: #66cc66;">&#123;</span> 
  <span style="color: #000000; font-weight: bold;">color</span>: <span style="color: #cc00cc;">#fff</span>;
  <span style="color: #000000; font-weight: bold;">background-color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">999</span></span>;
  <span style="color: #000000; font-weight: bold;">display</span>: <span style="color: #993333;">block</span>;
  <span style="color: #000000; font-weight: bold;">padding</span>: <span style="color: #6666ff;"><span style="color: #933;">.3em</span></span> <span style="color: #6666ff;"><span style="color: #933;">.5em</span></span>;
  <span style="color: #000000; font-weight: bold;">text-decoration</span>: <span style="color: #993333;">none</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #cc00cc;">#menu</span> p <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">padding</span>: <span style="color: #933;">0</span> <span style="color: #6666ff;"><span style="color: #933;">.5em</span></span>;
<span style="color: #66cc66;">&#125;</span></pre></div></p>
<p>Next the markup. The old school technique involves writing the rollover script functions and triggering them from event attributes. More complex actions required more and more stuff muddying up what was a perfectly readable HTML document. </p>
<p><div class="geshifilter"><pre class="geshifilter-html4strict"><span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;menu&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;btn1&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span> <span style="color: #000066;">onmouseover</span>=<span style="color: #ff0000;">&quot;rollOver('btn1')&quot;</span> <span style="color: #000066;">onmouseout</span>=<span style="color: #ff0000;">&quot;rollOut('btn1')&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;btn2&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span> <span style="color: #000066;">onmouseover</span>=<span style="color: #ff0000;">&quot;rollOver('btn2')&quot;</span> <span style="color: #000066;">onmouseout</span>=<span style="color: #ff0000;">&quot;rollOut('btn2')&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;btn3&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span> <span style="color: #000066;">onmouseover</span>=<span style="color: #ff0000;">&quot;rollOver('btn3')&quot;</span> <span style="color: #000066;">onmouseout</span>=<span style="color: #ff0000;">&quot;rollOut('btn3')&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span></pre></div></p>
<p>Finally, the JavaScript. A function to set styles on mouseover and another to restore the original styles on mouseout. If you change a color in the stylesheet, you'll have to change it here too.</p>
<p><div class="geshifilter"><pre class="geshifilter-javascript">&lt;script type=<span style="color: #3366CC;">&quot;text/javascript&quot;</span>&gt;
<span style="color: #009900; font-style: italic;">// Apply rollover styles</span>
<span style="color: #003366; font-weight: bold;">function</span> rollOver<span style="color: #66cc66;">&#40;</span>el<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #009900; font-style: italic;">// Get the elements</span>
  <span style="color: #003366; font-weight: bold;">var</span> thisBtn = document.<span style="color: #006600;">getElementById</span><span style="color: #66cc66;">&#40;</span>el<span style="color: #66cc66;">&#41;</span>;
  <span style="color: #003366; font-weight: bold;">var</span> thisLink = thisBtn.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #009900; font-style: italic;">// Change their styles</span>
  thisLink<span style="color: #66cc66;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">style</span>.<span style="color: #006600;">backgroundColor</span> = <span style="color: #3366CC;">'#666'</span>;
  thisBtn.<span style="color: #006600;">style</span>.<span style="color: #006600;">borderColor</span> = <span style="color: #3366CC;">'#666'</span>;
  thisBtn.<span style="color: #006600;">style</span>.<span style="color: #006600;">color</span> = <span style="color: #3366CC;">'#000'</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #009900; font-style: italic;">// Reset styles</span>
<span style="color: #003366; font-weight: bold;">function</span> rollOut<span style="color: #66cc66;">&#40;</span>el<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #009900; font-style: italic;">// Get the elements</span>
  <span style="color: #003366; font-weight: bold;">var</span> thisBtn = document.<span style="color: #006600;">getElementById</span><span style="color: #66cc66;">&#40;</span>el<span style="color: #66cc66;">&#41;</span>;
  <span style="color: #003366; font-weight: bold;">var</span> thisLink = thisBtn.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #009900; font-style: italic;">// Change their styles back again</span>
  thisLink<span style="color: #66cc66;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">style</span>.<span style="color: #006600;">backgroundColor</span> = <span style="color: #3366CC;">'#999'</span>;
  thisBtn.<span style="color: #006600;">style</span>.<span style="color: #006600;">borderColor</span> = <span style="color: #3366CC;">'#999'</span>;
  thisBtn.<span style="color: #006600;">style</span>.<span style="color: #006600;">color</span> = <span style="color: #3366CC;">'#666'</span>;
<span style="color: #66cc66;">&#125;</span>
&lt;script&gt;</pre></div></p>
<h2>Make the Script Less Obtrusive</h2>
<p>Let's clean things up a bit. Strip those event handlers from the button containers. </p>
<p><div class="geshifilter"><pre class="geshifilter-html4strict"><span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;menu&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
  <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;btn&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;#&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Link 3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>
    <span style="color: #009900;"><a href="http://december.com/html/4/element/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>Description for link 3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span></pre></div></p>
<p>Now, make a few CSS adjustments and additions to define the hover styles where they belong, in the style sheet.</p>
<p><div class="geshifilter"><pre class="geshifilter-css"><span style="color: #cc00cc;">#menu</span> <span style="color: #66cc66;">&#123;</span> 
  <span style="color: #000000; font-weight: bold;">font</span>: <span style="color: #933;"><span style="color: #933;">85</span>%</span> Arial, Helvetica, san-<span style="color: #993333;">serif</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #cc00cc;">#menu</span> <span style="color: #6666ff;">.btn</span>, <span style="color: #cc00cc;">#menu</span> <span style="color: #6666ff;">.btn-over</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">background-color</span>: <span style="color: #cc00cc;">#e7e7e7</span>;
  <span style="color: #000000; font-weight: bold;">border-width</span>: <span style="color: #933;">2px</span>;
  <span style="color: #000000; font-weight: bold;">border-style</span>: <span style="color: #993333;">solid</span>;
  <span style="color: #000000; font-weight: bold;">color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">666</span></span>;
  <span style="color: #000000; font-weight: bold;">float</span>: <span style="color: #000000; font-weight: bold;">left</span>;
  <span style="color: #000000; font-weight: bold;">margin</span>: <span style="color: #933;">0</span> <span style="color: #933;">5px</span>;
  <span style="color: #000000; font-weight: bold;">width</span>: <span style="color: #933;">150px</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #cc00cc;">#menu</span> <span style="color: #6666ff;">.btn</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">border-color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">999</span></span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #cc00cc;">#menu</span> <span style="color: #6666ff;">.btn</span> a, <span style="color: #cc00cc;">#menu</span> <span style="color: #6666ff;">.btn-over</span> a <span style="color: #66cc66;">&#123;</span> 
  <span style="color: #000000; font-weight: bold;">color</span>: <span style="color: #cc00cc;">#fff</span>;
  <span style="color: #000000; font-weight: bold;">background-color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">999</span></span>;
  <span style="color: #000000; font-weight: bold;">display</span>: <span style="color: #993333;">block</span>;
  <span style="color: #000000; font-weight: bold;">padding</span>: <span style="color: #6666ff;"><span style="color: #933;">.3em</span></span> <span style="color: #6666ff;"><span style="color: #933;">.5em</span></span>;
  <span style="color: #000000; font-weight: bold;">text-decoration</span>: <span style="color: #993333;">none</span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #cc00cc;">#menu</span> p <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">padding</span>: <span style="color: #933;">0</span> <span style="color: #6666ff;"><span style="color: #933;">.5em</span></span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* Rollover styles */</span>
<span style="color: #cc00cc;">#menu</span> <span style="color: #6666ff;">.btn-over</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">border-color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">666</span></span>;
  <span style="color: #000000; font-weight: bold;">color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">000</span></span>;
<span style="color: #66cc66;">&#125;</span>
<span style="color: #cc00cc;">#menu</span> <span style="color: #6666ff;">.btn-over</span> a <span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">background-color</span>: <span style="color: #cc00cc;">#<span style="color: #933;">666</span></span>;
<span style="color: #66cc66;">&#125;</span></pre></div></p>
<p>With that done, hook it all up with the script.</p>
<p><div class="geshifilter"><pre class="geshifilter-javascript">&lt;script type=<span style="color: #3366CC;">&quot;text/javascript&quot;</span>&gt;
<span style="color: #009900; font-style: italic;">// Attach event listeners to the buttons</span>
<span style="color: #003366; font-weight: bold;">function</span> findButtons<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> menu, btns, i;
  <span style="color: #009900; font-style: italic;">// Get the menu element to access the btn divs</span>
  menu = document.<span style="color: #006600;">getElementById</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'menu'</span><span style="color: #66cc66;">&#41;</span>;
  btns = menu.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'div'</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span>i=<span style="color: #CC0000;">0</span>; i&lt;btns.<span style="color: #006600;">length</span>; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #009900; font-style: italic;">// Attach event listeners for rollovers to the btns</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0066FF;">/btn/</span>.<span style="color: #006600;">test</span><span style="color: #66cc66;">&#40;</span>btns<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">className</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> 
      btns<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">onmouseover</span> = <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span>roll<span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span>;<span style="color: #66cc66;">&#125;</span>;
      btns<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">onmouseout</span> = <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span>roll<span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span>;<span style="color: #66cc66;">&#125;</span>;
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
<span style="color: #009900; font-style: italic;">// Attached to the buttons and ready to roll</span>
<span style="color: #003366; font-weight: bold;">function</span> roll<span style="color: #66cc66;">&#40;</span>o<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #009900; font-style: italic;">// btn is our off state, so turn it on</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>o.<span style="color: #006600;">className</span> == <span style="color: #3366CC;">'btn'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    o.<span style="color: #006600;">className</span> = <span style="color: #3366CC;">'btn-over'</span>;
  <span style="color: #009900; font-style: italic;">// Otherwise, turn it off</span>
  <span style="color: #66cc66;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #66cc66;">&#123;</span>
    o.<span style="color: #006600;">className</span> = <span style="color: #3366CC;">'btn'</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
<span style="color: #009900; font-style: italic;">// Initialize the rollover</span>
window.<span style="color: #000066;">onload</span> = <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  findButtons<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&lt;/script&gt;</pre></div></p>
<p>Everything is now in its proper place. No more JavaScript in the HTML and styles aren't defined in the JavaScript. This will be much easier to maintain.</p>
<h2>Unobtrusive, the YUI Style</h2>
<p>YUI is one of the many JavaScript libraries that have gained attention in recent years. Some say it's too big and bulky and that may be true in certain cases, like creating a simple rollover. But it's rare in our Web 2.0 world that a site's only JavaScript-powered feature is a rollover. YUI is my current JavaScript framework of choice because along with being feature-rich, it's well documented, tested, and supported.</p>
<p>So here's the rollover script powered by the YUI's Yahoo! Global Object, and DOM and Event extensions. </p>
<p><div class="geshifilter"><pre class="geshifilter-javascript">&lt;script type=<span style="color: #3366CC;">&quot;text/javascript&quot;</span> src=<span style="color: #3366CC;">&quot;http://yui.yahooapis.com/2.5.1/build/yahoo-dom-event/yahoo-dom-event.js&quot;</span>&gt;&lt;/script&gt;
&lt;script type=<span style="color: #3366CC;">&quot;text/javascript&quot;</span>&gt;
<span style="color: #009900; font-style: italic;">// Create a menu object, put everything we need into it</span>
<span style="color: #003366; font-weight: bold;">var</span> menu = <span style="color: #66cc66;">&#123;</span>
  <span style="color: #009900; font-style: italic;">// Initialize the menu rollover</span>
  init : <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #009900; font-style: italic;">// Get the btn elements</span>
    btns = YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">getElementsByClassName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'btn'</span>, <span style="color: #3366CC;">'div'</span>, <span style="color: #3366CC;">'menu'</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #009900; font-style: italic;">// Assign event listeners to the btns</span>
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i=<span style="color: #CC0000;">0</span>; i&lt;btns.<span style="color: #006600;">length</span>; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
      YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Event</span>.<span style="color: #006600;">addListener</span><span style="color: #66cc66;">&#40;</span>btns<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>, <span style="color: #3366CC;">'mouseover'</span>, menu.<span style="color: #006600;">roll</span>, i<span style="color: #66cc66;">&#41;</span>;
      YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Event</span>.<span style="color: #006600;">addListener</span><span style="color: #66cc66;">&#40;</span>btns<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>, <span style="color: #3366CC;">'mouseout'</span>, menu.<span style="color: #006600;">roll</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#125;</span>,
  <span style="color: #009900; font-style: italic;">// First, turn 'em all off, then turn one on</span>
  roll : <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>e, i<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">removeClass</span><span style="color: #66cc66;">&#40;</span>btns, <span style="color: #3366CC;">'btn-over'</span><span style="color: #66cc66;">&#41;</span>;
    YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Dom</span>.<span style="color: #006600;">addClass</span><span style="color: #66cc66;">&#40;</span>btns<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>, <span style="color: #3366CC;">'btn-over'</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>;
<span style="color: #009900; font-style: italic;">// Initialize the menu</span>
YAHOO.<span style="color: #006600;">util</span>.<span style="color: #006600;">Event</span>.<span style="color: #006600;">on</span><span style="color: #66cc66;">&#40;</span>window, <span style="color: #3366CC;">'load'</span>, menu.<span style="color: #006600;">init</span><span style="color: #66cc66;">&#41;</span>;
&lt;/script&gt;</pre></div></p>
<p>The YUI version basically works just like the unobtrusive version. Yahoo! provides hosted versions of all the YUI extensions, just add a link to yahoo-dom-event.js. With the help of the Yahoo! Global Object and DOM and Event extensions, it's easy to grab  button elements and assign event handlers that trigger the roll function. The main difference here is that everything is neatly encapsulated into the menu object. The YUI's <a href="http://developer.yahoo.com/yui/dom/#class">getElementsByClassName and remove/addClass</a> methods make DOM scripting a breeze. </p>
<p>Take a look at the <a href="http://2tbsp.com/system/files/yui-rollover.html">final product</a>.</p>
<h2>Conclusion</h2>
<p>Hopefully these basic examples serve as a kick in the rear for those clinging to those old school ways. Now that you have the basics of event handling down, <a href="/node/92">I'll show you how to improve the scripts performance through event delegation and how to make it scalable to power multiple rollover menus</a>.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Subversion Administration: Separate an SVN Repository into Individual Projects</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/node/88" />
    <id>http://www.2tbsp.com/node/88</id>
    <published>2008-03-20T21:02:15-07:00</published>
    <updated>2008-03-22T08:50:26-07:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="How to" />
    <category term="Subversion" />
    <summary type="html"><![CDATA[<p>
I&#39;ve been using Subversion since the <a href="http://gallery.menalto.com/" title="The Gallery Project">Gallery Project</a>  switched to it from CVS a few years back. I decided to install Subversion to manage my freelance projects last year and am getting up to speed on repository administration. I flip-flopped for a while on whether to keep projects in a single or separate repositories. I initially decided to keep everything in one repository, but later decided to separate them out. Fortunately, the svnadmin and svndumpfilter utilities make it relatively simple to separate repositories into individual projects.
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
I&#39;ve been using Subversion since the <a href="http://gallery.menalto.com/" title="The Gallery Project">Gallery Project</a>  switched to it from CVS a few years back. I decided to install Subversion to manage my freelance projects last year and am getting up to speed on repository administration. I flip-flopped for a while on whether to keep projects in a single or separate repositories. I initially decided to keep everything in one repository, but later decided to separate them out. Fortunately, the svnadmin and svndumpfilter utilities make it relatively simple to separate repositories into individual projects.
</p>
<p><!--break--></p>
<p>
My goal is to create two new projects from folders stored in the trunk of a single repository. My repository&#39;s history isn&#39;t complex—it doesn&#39;t contain tags or branches yet. You&#39;ll need to put a bit more thought into how to deal with existing tags and branches.
</p>
<p>
My current svn root layout is:
</p>
<p><div class="geshifilter"><pre class="geshifilter-bash">/svnroot
    /branches
    /tags
    /trunk
        /project1
        /project2</pre></div></p>
<p>
The desired layout is:
</p>
<p><div class="geshifilter"><pre class="geshifilter-bash">/svnroot
    /project1
        /branches
        /tags
        /trunk
    /project2
        /branches
        /tags
        /trunk</pre></div></p>
<p>
The basic steps to separate these repositories are:
</p>
<ol>
<li>Dump the current repository</li>
<li>Separate folders in the dump to separate files with svndumpfilter</li>
<li>Create new repositories</li>
<li>Load the filtered dump files into the new repositories</li>
<li>Cleanup the new repository layout, move files from trunk/projectN to trunk/</li>
<li>Delete the original branches, tags, and trunk repositories from svnroot</li>
</ol>
<p>
I&#39;ll use tmp as working directory to dump and filter files.
</p>
<h2>Dump the current repository</h2>
<p><div class="geshifilter"><pre class="geshifilter-bash">svnadmin dump /svnroot/originalproject &amp;gt; /tmp/original.dump</pre></div></p>
<h2>Separate folders to separate files with svndumpfilter</h2>
<p><div class="geshifilter"><pre class="geshifilter-bash"><span style="color: #c20cb9; font-weight: bold;">cat</span> /tmp/original.dump | svndumpfilter --drop-empty-revs --renumber-revs include trunk/project1 &amp;gt; /tmp/project1.dump
<span style="color: #c20cb9; font-weight: bold;">cat</span> /tmp/original.dump | svndumpfilter --drop-empty-revs --renumber-revs include trunk/project2 &amp;gt; /tmp/project2.dump</pre></div></p>
<p>
The key here is the include option which targets the project folder(s). There&#39;s also an exclude option that might come in handy if you&#39;re trying to remove one folder from a group of many. The --drop-empty-revs and --renumber-revs options remove commit log messages for other folders and renumber the remaining revision numbers.
</p>
<h2>Create new repositories</h2>
<p><div class="geshifilter"><pre class="geshifilter-bash">svnadmin create /svnroot/project1
svnadmin create /svnroot/project2</pre></div></p>
<h2>Load the filtered dump files into the new repositories</h2>
<p><div class="geshifilter"><pre class="geshifilter-bash">svnadmin load /svnroot/project1 &amp;lt; /tmp/project1.dump 
svnadmin load /svnroot/project2 &amp;lt; /tmp/project2.dump</pre></div></p>
<h2>Cleanup new repository layout, move files from trunk/projectN to trunk/</h2>
<p>
Each repository layout now looks something like:
</p>
<p><div class="geshifilter"><pre class="geshifilter-bash">/svnroot
    /project1
        /branches
        /tags
        /trunk
            /project1
                file1
                ...
                fileX</pre></div></p>
<p>
But they should look like:
</p>
<p><div class="geshifilter"><pre class="geshifilter-bash">/svnroot
    /project1
        /branches
        /tags
        /trunk
            file1
            ...
            fileX</pre></div></p>
<p>
Subversion doesn&#39;t allow wildcard gobling, so it&#39;s impossible to do something like:
</p>
<p><div class="geshifilter"><pre class="geshifilter-bash">svn move trunk/project1/* trunk/</pre></div></p>
<p>
It was possible to edit path information in the project dump files before loading them, but it seemed easier to check out a working copy of each, move things around, and then commit the changes.
</p>
<p><div class="geshifilter"><pre class="geshifilter-bash">svn checkout <span style="color: #c20cb9; font-weight: bold;">file</span> :///svnroot/project1 /tmp/project1
<span style="color: #7a0874; font-weight: bold;">cd</span> /tmp/project1/trunk</pre></div></p>
<p>
Now, a little shell work to move things around. <a href="http://subversion.tigris.org/faq.html#sorry-no-globbing">Thanks Tigris!</a> PLEASE NOTE: Use this at your own risk. Back up your repository before trying the following or be ready to use svn revert.
</p>
<p><div class="geshifilter"><pre class="geshifilter-bash"><span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> /tmp/project1/trunk/project1/*; <span style="color: #000000; font-weight: bold;">do</span> svn <span style="color: #c20cb9; font-weight: bold;">mv</span> <span style="color: #007800;">$i</span> /tmp/project1/trunk; <span style="color: #000000; font-weight: bold;">done</span>
svn commit -m <span style="color: #ff0000;">&quot;Moved all project files to trunk&quot;</span>
svn remove /tmp/project1/trunk/project1
svn commit -m <span style="color: #ff0000;">&quot;Removed obsolete project1 folder after moving its contents to trunk&quot;</span></pre></div></p>
<p>
Lather, rinse, repeat.
</p>
<p>
At some point I&#39;ll probably back track and write a post on installing and configuring Subversion with MacPorts but that&#39;s it, at least for now.
</p>
    ]]></content>
  </entry>
  <entry>
    <title>Notes on Choosing a PHP Framework: A Comparison of CakePHP and the Zend Framework</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/node/87" />
    <id>http://www.2tbsp.com/node/87</id>
    <published>2008-02-15T15:05:17-08:00</published>
    <updated>2008-05-21T13:52:14-07:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="Frameworks" />
    <category term="PHP" />
    <category term="Review" />
    <summary type="html"><![CDATA[<p>
UPDATE:Parlez vous Français? Guillaume Rossolini has created a <a href="http://g-rossolini.developpez.com/comparatifs/php/cake-zf/">French translation of this article</a>.
</p>
<p>
Are you considering using a PHP framework for your next project? If so, this article&#39;s for you. I&#39;ve narrowed down my choices to CakePHP and the Zend Framework and have documented my findings  here.
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
UPDATE:Parlez vous Français? Guillaume Rossolini has created a <a href="http://g-rossolini.developpez.com/comparatifs/php/cake-zf/">French translation of this article</a>.
</p>
<p>
Are you considering using a PHP framework for your next project? If so, this article&#39;s for you. I&#39;ve narrowed down my choices to CakePHP and the Zend Framework and have documented my findings  here.
</p>
<p>
Four or five years ago I began researching PHP application frameworks. At the time, the pickings were very slim, especially when compared to those available to Java developers. On the advice of an ex-Coldfusion developer, I settled on the PHP port of Fusebox, the de facto Coldfusion framework. Fusebox 3 provided a convenient set of loose conventions for structuring applications, organizing code, naming files, and controlling flow. It served my development team well and <a href="http://www.lanl.gov/news/index.php/fuseaction/nr.subject">applications we built with it</a> are still up and running.
</p>
<p>
I took a two-year &quot;break&quot; from development and upon my return I found more PHP frameworks than you can shake a stick at. Now I need to find a solid MVC-based framework and after reading dozens of articles and completing a few tutorials, I&#39;ve narrowed my focus to CakePHP and the Zend Framework.
</p>
<p>
Before going further, let it be known that my point of view is that of someone with plenty of application development experience but without a formal IT or CS degree. I can&#39;t go on  about the merits of one design pattern vs. another. I do, however, understand the need for convention, the advantages of modularity, and the efficiency of easily repeatable processes.
</p>
<p>
Please note that symfony, Prado, Code Ignitor, and many of the other PHP frameworks all look quite capable of meeting most project needs. If you&#39;re a fanboy of another framework, please don&#39;t espouse it&#39;s merits here. I am, however, interested in hearing about your general experience in learning a framework, particularly  in the context of your professional background.
</p>
<p>
Here&#39;s a comparison and a few conclusions after spending a bit of time with both CakePHP and the Zend Framework. Please note that my quality scale range is: poor, fair, good, excellent.
</p>
<table border="1" cellspacing="0" cellpadding="5">
<caption>
	Feature Comparison of CakePHP and the Zend Framework<br />
	</caption>
<tbody>
<tr>
<th scope="col">
<div align="left">
			Feature
			</div>
</th>
<th scope="col">CakePHP</th>
<th scope="col">Zend Framework</th>
<th scope="col">Notes</th>
</tr>
<tr>
<th scope="row">
<div align="left">
			License
			</div>
</th>
<td>
<div align="center">
			<a href="http://en.wikipedia.org/wiki/MIT_License">MIT</a>
			</div>
</td>
<td>
<div align="center">
			<a href="http://en.wikipedia.org/wiki/New_BSD_License">BSD</a>
			</div>
</td>
<td>Each of these licenses is fairly flexible. Carefully consider how your application will be used and distributed. It&#39;s also important to consider compatability with 3rd-party extensions included in your application.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Compatability
			</div>
</th>
<td>
<div align="center">
			4 and 5
			</div>
</td>
<td>
<div align="center">
			5.1.4 or later
			</div>
</td>
<td>I&#39;m curious to know what CakePHP&#39;s PHP 4 support plans are. I would wager that Zend&#39;s focus on PHP 5 provides it with performance advantages.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Documentation
			</div>
</th>
<td>
<div align="center">
			<a href="http://book.cakephp.org/">good</a>
			</div>
</td>
<td>
<div align="center">
			<a href="http://framework.zend.com/manual/">excellent</a>
			</div>
</td>
<td>CakePHP&#39;s documentation is good but Zend&#39;s API documentation is more thorough.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Community
			</div>
</th>
<td>
<div align="center">
			<a href="http://groups.google.com/group/cake-php">Google group</a>,  <br />
			<a href="irc://irc.freenode.net/cakephp">IRC</a>, <a href="http://bakery.cakephp.org/">Articles</a>
			</div>
</td>
<td>
<div align="center">
			<a href="http://framework.zend.com/wiki/display/ZFDEV/Home">Wiki</a>, <br />
			<a href="http://framework.zend.com/wiki/display/ZFDEV/Contributing+to+Zend+Framework#ContributingtoZendFramework-Subscribetotheappropriatemailinglists">Lists</a>, <a href="http://framework.zend.com/support/communitybased/">Chat</a>
			</div>
</td>
<td>Both frameworks have active user communities. In addition to official channels, there are also several 3rd-party community sites easily found through Google. CakePHP has done an excellent job of marketing their framework considering that they don&#39;t have the corporate backing that ZF has. </td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Tutorial/Sample Availability
			</div>
</th>
<td>
<div align="center">
			excellent
			</div>
</td>
<td>
<div align="center">
			fair
			</div>
</td>
<td><a href="http://bakery.cakephp.org/">CakePHP&#39;s Bakery</a>  provides an extensive collection of user-submitted applications and code samples. The <a href="http://www.ibm.com/developerworks/edu/os-dw-os-php-cake1.html">IBM developerWorks CakePHP tutorials and aritcles</a> are excellent. The Zend tutorials I&#39;ve reviewed are good but require a siginifcant amount of MVC design experience. The <a href="http://framework.zend.com/manual/videos">ZF beginner&#39;s videos</a>, however, are very helpful. <a href="http://cakephp.org/screencasts">CakePHP provides screencasts</a> too.
			</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			MVC
			</div>
</th>
<td>
<div align="center">
			strict
			</div>
</td>
<td>
<div align="center">
			optional
			</div>
</td>
<td rowspan="2">These points are the biggest distinctions between these frameworks and probably the most important factors when choosing one over the other. CakePHP has very strict naming and code organization conventions while Zend only enforces conventions when employing its MVC capabilities.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Conventions
			</div>
</th>
<td>
<div align="center">
			strict
			</div>
</td>
<td>
<div align="center">
			flexible
			</div>
</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Configuration
			</div>
</th>
<td>
<div align="center">
			PHP file
			</div>
</td>
<td>
<div align="center">
			PHP Array, XML, or <br />
			INI files
			</div>
</td>
<td>This difference doesn&#39;t seem like a sticking point to me. If you&#39;re a fan of build tools like ANT, you might prefer Zend&#39;s choice of XML.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Database Abstraction
			</div>
</th>
<td>
<div align="center">
			PHP, PEAR, ADODB
			</div>
</td>
<td>
<div align="center">
			<a href="http://framework.zend.com/manual/en/zend.db.html">PHP, PDO</a>
			</div>
</td>
<td>I may be wrong, but I get the impression that  PDO is gaining favor in the PHP community.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Security
			</div>
</th>
<td>
<div align="center">
			<a href="http://book.cakephp.org/view/171/access-control-lists">ACL-based</a>
			</div>
</td>
<td>
<div align="center">
			<a href="http://framework.zend.com/manual/en/zend.acl.html">ACL-based</a>
			</div>
</td>
<td>Both frameworks take security very seriously and provide authentication and ACL-based authorization. Both approach ACLs in a similar fashion and both provide a high degree of flexibility in creating and applying ACLs.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Data <br />
			Handling
			</div>
</th>
<td>
<div align="center">
			good
			</div>
</td>
<td>
<div align="center">
			excellent
			</div>
</td>
<td>Out of the box, both frameworks provide data validation and  sanitization mechanisms. <a href="http://framework.zend.com/manual/en/zend.validate.set.html">Zend provides more validation options</a>, but <a href="http://manual.cakephp.org/chapter/validation">CakePHP&#39;s validation</a> is easily extended via PCRE. CakePHP provides a single data sanitization mechanism where Zend provides various filters to run data through.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Caching
			</div>
</th>
<td>
<div align="center">
			good
			</div>
</td>
<td>
<div align="center">
			excellent
			</div>
</td>
<td>Both provide  file-based caching of pages. Zend supports several cache backends, including APC, SqlLite, and of course, the Zend Platform.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Sessions
			</div>
</th>
<td>
<div align="center">
			excellent
			</div>
</td>
<td>
<div align="center">
			excellent
			</div>
</td>
<td>Both provide robust session handling.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Logging/<br />
			Debugging
			</div>
</th>
<td>
<div align="center">
			good
			</div>
</td>
<td>
<div align="center">
			excellent
			</div>
</td>
<td>Both provide application logging. IMHO, the Zend_Debug class gives ZF the edge in this category.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Templating
			</div>
</th>
<td>
<div align="center">
			PHP-based
			</div>
</td>
<td>
<div align="center">
			PHP-based
			</div>
</td>
<td>Coming from a UI design background, templating is of particular interest to me. If you&#39;ve developed templates for WordPress or Drupal, you&#39;ll feel right at home with CakePHP. The Zend Framework requires a bit more work to get templating up and running (see <a href="http://framework.zend.com/manual/en/zend.view.html">Zend_View</a> and <a href="http://framework.zend.com/manual/en/zend.layout.html">Zend_Layout</a>). It&#39;s possible to integrate 3rd party templating engines, like Smarty, with each framework.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Helpers
			</div>
</th>
<td>
<div align="center">
			good
			</div>
</td>
<td>
<div align="center">
			excellent
			</div>
</td>
<td>
<p>
			Both frameworks provide  basic helpers to  handle AJAX, forms, and time conversions. CakePHP provides a nice HTML helper which is absent in ZF but ZF provides a wider range of   helper classes.
			</p>
</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			JavaScript/Ajax
			</div>
</th>
<td>
<div align="center">
			good
			</div>
</td>
<td>
<div align="center">
			fair
			</div>
</td>
<td>CakePHP comes with built-in support for Prototype and script.aculo.us while the current stable release of the ZF doesn&#39;t support any specific JavaScript framework. ZF does provide JSON support and the 1.5 release adds  AJAX form featues. I&#39;d like to see both provide a wider range of support for 3rd party JavaScript Frameworks, particularly Jquery and YUI. </td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Web Services
			</div>
</th>
<td>
<div align="center">
			good
			</div>
</td>
<td>
<div align="center">
			excellent
			</div>
</td>
<td>
<p>
			Both provide support for REST and XML-RPC as well as basic XML feed parsing. Zend Framework also provides support for several popular web services including OpenID, Reflection, Akismet, Amazon, Audioscrobbler, Delicious, Flickr, Simpy, StrikeIron, Technorati, and Yahoo.
			</p>
</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Localization
			</div>
</th>
<td>
<div align="center">
			good
			</div>
</td>
<td>
<div align="center">
			excellent
			</div>
</td>
<td>Both support localization through stadard means (i18n, l10n). CakePHP is adding/improving support in their upcoming 1.2 release. Zend appears to have better support for localization and translation.</td>
</tr>
<tr>
<th scope="row">
<div align="left">
			Unit Testing
			</div>
</th>
<td>
<div align="center">
			yes
			</div>
</td>
<td>
<div align="center">
			yes
			</div>
</td>
<td>Both frameworks provide support for this feature that far too many of us avoid ;) I have yet to evaluate unit testing support.</td>
</tr>
</tbody>
</table>
<h2>Conclusions and Recommendations</h2>
<p>
I hope to use both of these frameworks soon, but in the short term I&#39;ll most likely base an upcoming CMS  project on CakePHP. I do plan on using the Zend Framework, if for nothing other than expanding my application design skills, PHP 5 OO knowledge, and understanding of MVC.
</p>
<h3>CakePHP: Hit the Ground Running Fast</h3>
<p>
If you are new to MVC, require PHP 4 support, want stricter conventions, or want powerful code generation tools, CakePHP is the choice for you. CakePHP&#39;s Scaffolding, Bake, and ACL  scripts provide definite advantages when the need to quickly build an application  arise.
</p>
<h3>The Zend Framework: A Model of Flexibility</h3>
<p>
If you know MVC, need more control over application design, or want built-in support for popular Web services, the Zend Framework is choice for you. The Zend Framework provides a greater degree of flexibility in designing applications that scale effectively in high-performance environments.
</p>
<p>
The bottom line is that both frameworks are rapidly evolving in response to user demands. Gaps in each are being filled and there seems to be no lack of demand for developers with skills in each framework.
</p>
<p>
Feel free to share your experience in learning any framework.
</p>
    ]]></content>
  </entry>
  <entry>
    <title>Database Development in Eclipse with the Data Tools Platform (DTP)</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/node/86" />
    <id>http://www.2tbsp.com/node/86</id>
    <published>2008-02-10T23:07:46-08:00</published>
    <updated>2008-05-05T15:04:51-07:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="Databases" />
    <category term="Eclipse" />
    <summary type="html"><![CDATA[<p><img src="http://2tbsp.com/system/files/eclipse-sm.png" alt="Eclipse logo" align="right" />I&#39;m getting lazier. I mean lazy like looking for 10 minutes for a lost TV remote rather than getting off the couch to change the channel. Sure, it&#39;s not a big deal to switch back and forth between Eclipse and the MySQL Query Browser or phpMyAdmin, but those seconds add up.<br />
In this post I&#39;ll show you how to take advantage of another part of the &quot;I&quot; in the Eclipse &quot;IDE&quot;.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><img src="http://2tbsp.com/system/files/eclipse-sm.png" alt="Eclipse logo" align="right" />I&#39;m getting lazier. I mean lazy like looking for 10 minutes for a lost TV remote rather than getting off the couch to change the channel. Sure, it&#39;s not a big deal to switch back and forth between Eclipse and the MySQL Query Browser or phpMyAdmin, but those seconds add up. </p>
<p>In this post I&#39;ll show you how to take advantage of another part of the &quot;I&quot; in the Eclipse &quot;IDE&quot;. </p>
<p>The Eclipse Data Tools Platform (DTP) is a standard Eclipse plugin that you can use to perform most database development and query functions. The DTP plugin supports several database platforms via JDBC, including Derby, Oracle, MS SQL, Postgres, Sybase ASA, Flat Files, XML Data, Web Services, and more. This post covers connecting to MySQL and basic DTP features. </p>
<h2>Requirements</h2>
<p>I&#39;ll assume that you&#39;re comfortable <a href="http://2tbsp.com/node/40" title="Getting Started with Eclipse PDT">installing Eclipse and Eclipse plugins</a> . I&#39;m also assuming that you&#39;ve used Eclipse for a bit and have at least one project defined. Here&#39;s what you&#39;ll need before we get started.</p>
<ul>
<li>Eclipse with the DTP plugin, I&#39;m running Eclipse 3.3 which came bundled with DTP version 1.5.0.</li>
<li>MySQL JDBC Driver, I&#39;m using Connect/J 5.1.</li>
<li>MySQL Server version 4 or 5 running on localhost or a remote host that allows remote connections.</li>
<li>MySQL user account with a database or privileges to create databases.
	</li>
</ul>
<h2>Install a JDBC Driver</h2>
<p>Installing Eclipse and DTP does not install JDBC drivers. You must install the appropriate driver for the database server you&#39;re using. You can usually get drivers from the vendor. I downloaded the MySQL Connector/J. </p>
<ol>
<li>Visit <a href="http://dev.mysql.com/downloads/connector/" title="MySQL Connector/J downloads">http://dev.mysql.com/downloads/connector/</a> </li>
<li>Select &#39;Connector/J&#39; in the left menu, then select a version. I used version 5.1.</li>
<li>Download the source and binaries and save somewhere that makes sense for your OS. I dropped mine in /Library/Java/Extensions on my Mac.</li>
</ol>
<h2>Create a Driver Template and Connection Profile</h2>
<p>Next, create a driver template and a connection profile. You&#39;ll be able to reuse this template when creating future connection profiles.</p>
<ol>
<li>Select File &gt; New &gt; Other</li>
<li>Expand Connection Profiles and select Connection Profile, Next &gt;</li>
<li>Select Generic JDBC Connection, Next &gt;<br />
	<img src="http://2tbsp.com/system/files/dtp_profile02.png" alt="New connection profile wizard" />
	</li>
<li>Name the Connection Profile for the host and database to which you&#39;re connecting (i.e. localhost.database), Next &gt;</li>
<li>Click on the ... button to add your JDBC driver to the Select a driver dropdown menu.
<ol>
<li>Select the appropriate folder for your database JDBC driver version, I selected MySQL &gt; 5.1, Click Add...</li>
<li>Expand the Available Driver Templates folders, select &quot;MySQL JDBC Driver&quot;</li>
<li>Add the driver version to the Driver Name, I changed mine to &quot;MySQL JDBC Driver 5.1&quot;
<p>		Note: Don&#39;t be confused by differences in server and driver versions. You can use the 5.1 driver to connect to MySQL 4.x.</li>
<li>Check &quot;Edit New Driver Definition Immediately&quot;, click OK</li>
</ol>
</li>
<li>Eclipse will display an &quot;Unable to locate jar/zip...&quot; message. Tell Eclipse where the JDBC driver is.
<ol>
<li>Select the driver file in the list, click the &quot;Edit Jar/Zip&quot; button</li>
<li>Browse to and open your JDBC driver. I placed mine at /Library/Java/Extensions/mysql-connector-java-5.1.5/mysql-connector-java-5.1.5-bin.jar</li>
<li>Set your Connection URL, Database Name, Password, and User ID in the Properties pane, click OK
<p>		<img src="http://2tbsp.com/system/files/dtp_profile07.png" alt="DTP Driver Profile Details" title="Enlarge image" /></p>
</li>
</ol>
</li>
<li>Your Driver template now appears in the Available Driver Definitions list, select it, click OK</li>
<li>Add Optional Properties to those you just set or check the &quot;Save Password&quot; box if you&#39;d like.</li>
<li>Click the &quot;Test Connection&quot; button, hopefully your Ping succeeded! If not, double check your connection properties.</li>
<li>Click Finish</li>
</ol>
<h2>Open DTP&#39;s Database Development Perspective<br />
</h2>
<p>With a connection template and profile defined, open up the Database Development Perspective, if it isn&#39;t already open.</p>
<ol>
<li>Select Window &gt; Open Perspective &gt; Other...</li>
<li>Select Database Development, click OK<br />
	<img src="http://2tbsp.com/system/files/dtp_basics01.png" alt="Database Development perspective" />
	</li>
</ol>
<p><img src="http://2tbsp.com/system/files/dtp_basics02.png" alt="The Database Development Perspective" /></p>
<h2>
Establish a Database Connection<br />
</h2>
<ol>
<li>In the Data Source Explorer pane, expand the Database folder.</li>
<li>Right-click on the Connection Profile and select Connect</li>
<li>You should now see folders for table, stored procedures, views, and other objects supported by your database platform.</li>
<li>If you have tables in your database, expand to view columns.</li>
</ol>
<h2>Create and Execute SQL Files<br />
</h2>
<p>You can create and modify tables, triggers, stored procedures directly via DTP. Before proceeding, open an existing or create a new Eclipse project. You&#39;ll save SQL files to an existing project which makes it easy to place them under version control with the rest of your application files.</p>
<ol>
<li>Select File &gt; New &gt; SQL File (or File &gt; New &gt; Other &gt; SQL Development &gt; SQL File).
	</li>
<li>Choose the project and folder where you&#39;ll save the file.</li>
<li>Select the Database server type, Connection profile, and Database name. You can skip specifying the database if you&#39;re going to create one with the file.<img src="http://2tbsp.com/system/files/dtp_basics03.png" alt="Create a new SQL file" width="525" height="579" />
	</li>
<li>Click Finish</li>
<li>Type in the SQL you&#39;d like to run.
	</li>
<li>Select all, or a portion, of the SQL to run.</li>
<li>Right-click in the document tab and select either Execute All or Execute Selected Text.<br />
	<img src="http://2tbsp.com/system/files/dtp_basics04.png" alt="Execute SQL" width="691" height="318" />
	</li>
<li>Review the SQL Results at the bottom of the SQL Development Perspective.</li>
</ol>
<p>The buttons in the SQL Results tab allow you to track the status for all SQL executed and provide a handy filter for sifting through results. </p>
<h2>Insert and Edit Data</h2>
<ol>
<li>Expand Databases &gt; Host &gt; YourDatabase &gt; Schemas in the Data Source Explorer<br />
	<img src="http://2tbsp.com/system/files/dtp_basics05.png" alt="Data Source Explorer" width="388" height="390" />
	</li>
<li>Right-click on a table and select Data &gt; Edit</li>
<li>An editor tab appears with the table&#39;s columns, enter one or many records into the rows provided<br />
	<img src="http://2tbsp.com/system/files/dtp_basics06.png" alt="Table editor" width="303" height="99" />
	</li>
<li>Right-click anywhere in the editor panel and select save</li>
</ol>
<p>Easy, isn&#39;t it? You probably noticed other nifty features under the Data menu, including Load and Extract. These options allow you to import and export delimitied data from files.</p>
<h2>Conclusion</h2>
<p>Overall I&#39;m very happy with DTP. It&#39;s been a bit of an adjustment getting used to how things are done, but I no longer have to get off the Eclipse &quot;couch&quot; to take care of SQL development tasks. I&#39;ve covered most of the basics here but I think you&#39;ll find several other useful features. Happy data developing!</p>
    ]]></content>
  </entry>
  <entry>
    <title>Firefox 3 Can&#039;t Come Soon Enough</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/content/firefox_3_performance" />
    <id>http://www.2tbsp.com/content/firefox_3_performance</id>
    <published>2008-02-06T19:04:08-08:00</published>
    <updated>2008-02-06T20:01:43-08:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="Browsers" />
    <category term="OS X" />
    <summary type="html"><![CDATA[<p><img src="/system/files/firefox3b.png" title="Firefox 3 beta" width="250" height="79" align="right" /><br />
I&#39;ve been a Firefox for Mac user for many years, and before that Mozilla and Netscape. I stuck with Mozilla, despite the release of Safari, because I&#39;d using it for email since Netscape Messenger.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p><img src="/system/files/firefox3b.png" title="Firefox 3 beta" width="250" height="79" align="right" /></p>
<p>I&#39;ve been a Firefox for Mac user for many years, and before that Mozilla and Netscape. I stuck with Mozilla, despite the release of Safari, because I&#39;d using it for email since Netscape Messenger.</p>
<p>Even after switching to Apple&#39;s Mail, Firefox remained my primary browser. I must admit that I had become <a href="/node/42" title="My Obligatory Firefox Extensions Post">hooked on several plugins</a> , especially Web Developer and Firebug. Sure, I know that Safari is zippier and offers alternatives to several Firefox plugins, but that didn&#39;t matter. I kept telling myself &quot;You know all the keystrokes, why switch?&quot; I&#39;ve disabled Firebug for mail.google.com and looked for tips to speed things up. Alas there only seem to be Firefox optimization hacks for Windows. </p>
<p>Over the past few months I&#39;ve started to admit that I have a problem. I shouldn&#39;t have to sacrafice features for performance. GMail shouldn&#39;t load at a snails pace and my CPU doesn&#39;t exist to be at Firefox&#39;s beckon call.  </p>
<p>I&#39;ll give Firefox one more chance. The latest Firefox 3 beta is peppier, but Web Developer and Firebug are not yet available to truly test v3. I don&#39;t particularly like the Aqua form controls that are now the norm in version 3. </p>
<p>Leave a comment if you have any Mac Firefox optimization tips or wish to share your FF performance woes.</p>
    ]]></content>
  </entry>
  <entry>
    <title>Time to Get Organized, If Only for a Short While</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/content/time_get_organized_if_only_short_while" />
    <id>http://www.2tbsp.com/content/time_get_organized_if_only_short_while</id>
    <published>2008-02-05T20:24:19-08:00</published>
    <updated>2008-02-05T20:31:05-08:00</updated>
    <author>
      <name>chad</name>
    </author>
    <summary type="html"><![CDATA[<p>One of the things that&#39;s been on my list for a while is to update how I organize the content I create and consume. I&#39;d like to better organize my blog posts, photos, bookmarks, news feeds, and music collection. So I&#39;m taking some time to define a personal taxonomy. I will focus on developing better content tagging habits and hopefully find a few tools to help me do the job.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>One of the things that&#39;s been on my list for a while is to update how I organize the content I create and consume. I&#39;d like to better organize my blog posts, photos, bookmarks, news feeds, and music collection. So I&#39;m taking some time to define a personal taxonomy. I will focus on developing better content tagging habits and hopefully find a few tools to help me do the job.</p>
<p>I expect the fruits of my labor will be:</p>
<ul>
<li>The ability to more quickly browse to and search for content</li>
<li>The ability to mix and match content that I consume, like linking bookmarks to blog posts</li>
<li>To better earmark action items </li>
<li>To prepare for the predicted golden age of <a href="http://en.wikipedia.org/wiki/Recommendation_system" title="Recommendation systems from Wikipedia">recommendation engines</a> </li>
</ul>
<p>My plan is to:</p>
<ul>
<li>Research taxonomy and tagging best practices and processes (see Related Links)</li>
<li>Prioritize the content I&#39;m going to organize</li>
<li>Brainstorm how I want to organize each content type</li>
<li>Finalize and document my personal taxonomy</li>
<li>Find/develop tools to help manage my taxonomy</li>
<li>Apply what I&#39;ve learned to all content from this point forward</li>
<li>Go back and update my data, when possible</li>
</ul>
<h2>Available Tools</h2>
<p>The Mac applications that I&#39;ve come across are geared specifically towards one type of content (i.e. music, bookmarks, desktop documents/email, blog tag management). I&#39;m a bit disappointed by this and hope that something comes out of the Data Portability workgroup or Google&#39;s OpenSocial API.</p>
<h2>Progress So Far</h2>
<p>Last week I created tag bundles for my del.icio.us account. I then proceeded to prune redundant and unused tags and assigned what was left to the bundles. This has already proven useful since I was beginning to question the context of several of my tags. Now I just open up a bundle and I have context. I&#39;ve also taken Marshall Kirkpatrick&#39;s and Ian Beck&#39;s recommendation of cross referencing RSS content and bookmarks by marking them with toread, toshare, and totag.</p>
<p>I&#39;ll add updates as they&#39;re available. Chime in with your tips, tricks, and any tools that make your tagging life easier.</p>
    ]]></content>
  </entry>
  <entry>
    <title>A Call to My Blogging Friends, Publish an RSS Feed for Comments</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/content/call_my_blogging_friends_publish_rss_feed_comments" />
    <id>http://www.2tbsp.com/content/call_my_blogging_friends_publish_rss_feed_comments</id>
    <published>2008-01-25T14:32:48-08:00</published>
    <updated>2008-01-26T15:13:23-08:00</updated>
    <author>
      <name>chad</name>
    </author>
    <summary type="html"><![CDATA[<p>
UPDATE (1/26/08 - 4:08 pm (GMT-7): Look in yonder sidebar! Feed links for posts, site-wide comments, and comments on the current post!
</p>
<p>
Although email notifications of comments are useful, I&#39;d rather monitor comments and replies to comments via RSS.  If you can install a plugin, flip a switch, or just make your existing Commens RSS link more prominent, I&#39;d be much obliged.
</p>
<p>
This request is somewhat hypocritical, as I do not currently offer a comment feed for this site. That will change soon.
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
UPDATE (1/26/08 - 4:08 pm (GMT-7): Look in yonder sidebar! Feed links for posts, site-wide comments, and comments on the current post!
</p>
<p>
Although email notifications of comments are useful, I&#39;d rather monitor comments and replies to comments via RSS.  If you can install a plugin, flip a switch, or just make your existing Commens RSS link more prominent, I&#39;d be much obliged.
</p>
<p>
This request is somewhat hypocritical, as I do not currently offer a comment feed for this site. That will change soon.
</p>
    ]]></content>
  </entry>
  <entry>
    <title>Joining the Fray with new Plaxo and Twitter Accounts</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/content/joining_fray_new_plaxo_and_twitter_accounts" />
    <id>http://www.2tbsp.com/content/joining_fray_new_plaxo_and_twitter_accounts</id>
    <published>2008-01-23T22:14:18-08:00</published>
    <updated>2008-01-23T22:14:18-08:00</updated>
    <author>
      <name>chad</name>
    </author>
    <summary type="html"><![CDATA[<p>With the Social Networking powers that be recently <a href="http://www.techcrunch.com/2008/01/08/this-day-will-be-remembered-facebook-google-and-plaxo-join-the-dataportability-workgroup/" target="_blank">coming together in the same room</a> , I figured that it was time to do more than read and <a href="/node/46">write about social networks</a> . A friend recently invited me to hook up on Plaxo. His invitation along with the recent release of Plaxo&#39;s Mac client pushed me to making the leap.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>With the Social Networking powers that be recently <a href="http://www.techcrunch.com/2008/01/08/this-day-will-be-remembered-facebook-google-and-plaxo-join-the-dataportability-workgroup/" target="_blank">coming together in the same room</a> , I figured that it was time to do more than read and <a href="/node/46">write about social networks</a> . A friend recently invited me to hook up on Plaxo. His invitation along with the recent release of Plaxo&#39;s Mac client pushed me to making the leap. </p>
<p>So far, so good. The <a href="http://www.plaxo.com/products">Plaxo Mac client</a>  made it incredibly easy to upload contacts and make connections quickly. I was also able to reconnect with an old high school classmate that I haven&#39;t heard from in nearly twenty years! I loves the interweb!</p>
<p>After connecting with a few folks on Plaxo I thought, &quot;Why stop here?&quot; I&#39;m not gonna join MySpace, I feel old enough as it is. I&#39;m still resisting Facebook too. But Twitter has had some allure for some time now. </p>
<p>If you&#39;re already a member of either Plaxo or Twitter, or you&#39;re thinking about joining, look me up!</p>
    ]]></content>
  </entry>
  <entry>
    <title>NetNewsWire Now a Free Feed Reader</title>
    <link rel="alternate" type="text/html" href="http://www.2tbsp.com/content/netnewswire_now_free_feed_reader" />
    <id>http://www.2tbsp.com/content/netnewswire_now_free_feed_reader</id>
    <published>2008-01-09T21:49:40-08:00</published>
    <updated>2008-01-16T22:55:56-08:00</updated>
    <author>
      <name>chad</name>
    </author>
    <category term="Applications" />
    <category term="Community/Social Networks" />
    <summary type="html"><![CDATA[<p>In 2007, surveys and bloggers declared <a href="http://www.readwriteweb.com/archives/desktop_rss_readers_are_nearly_dead.php">the impending demise of the desktop feed reader</a>. My switch from <a href="http://infinite-sushi.com/software/endo/">Endo</a> to the online reader service <a href="http://www.rojo.com/">Rojo</a> over a year ago seems to put me in with the shifting mob. But I've wanted to try out NetNewsWire for some time now, and now <a href="http://www.newsgator.com/CompanyInfo/Press/Archive.aspx?post=144">there's nothing to stop me</a>.</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>In 2007, surveys and bloggers declared <a href="http://www.readwriteweb.com/archives/desktop_rss_readers_are_nearly_dead.php">the impending demise of the desktop feed reader</a>. My switch from <a href="http://infinite-sushi.com/software/endo/">Endo</a> to the online reader service <a href="http://www.rojo.com/">Rojo</a> over a year ago seems to put me in with the shifting mob. But I've wanted to try out NetNewsWire for some time now, and now <a href="http://www.newsgator.com/CompanyInfo/Press/Archive.aspx?post=144">there's nothing to stop me</a>.</p>
<p>I had purchased <a href="http://infinite-sushi.com/software/endo/">Endo</a>, a nice desktop feed reader that provides sync capability between Macs. It's simple interface and del.icio.us bookmarking features were okay, but it didn't sync with any of the online feed reading services. After less than 6 months, I rarely used it.</p>
<p>I also tried <a href="http://www.rssowl.org/">RSSOwl</a> for a bit. It's free, and one of the better feed readers IMO. Again, no online reader sync.</p>
<p>So, as I mentioned, I had been using Rojo for over a year, but dropped them in August after <a href="http://www.crn.com/software/201203027">their extended outage</a>. Since then I've been pretty happy with the beta online version of <a href="http://www.newsgator.com">Newsgator</a>. When I read that NNW was now freely available, that goofy geek giddiness overtook me.</p>
<p>My initial experience has been great. I downloaded and installed NNW on my iMac and Powerbook and in no time I had picked up my reading where I had left off online a few hours earlier. NNW has a simple interface, built-in browser, del.icious integration, blog this button, 3-pane interface, and it's fast, much faster than Endo or RSSOwl.</p>
<p>TeeHee!</p>
    ]]></content>
  </entry>
</feed>
