<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>Dave Dash</title>
 <link href="http://davedash.com/tag/usability/atom.xml" rel="self"/>
 <link href="http://davedash.com/tag/usability"/>
 <updated>2010-07-18T15:18:37-07:00</updated>
 <id>http://davedash.com/</id>
 <author>
   <name>Dave Dash</name>
   <email>dd+atom1@davedash.com</email>
 </author>

 
 <entry>
   <title>Removing parental restrictions from the PlayStation 2</title>
   <link href="http://davedash.com/2009/06/27/removing-parental-restrictions-from-the-playstation-2/"/>
   <updated>2009-06-27T00:00:00-07:00</updated>
   <id>http://davedash.com/2009/06/27/removing-parental-restrictions-from-the-playstation-2</id>
   <content type="html">&lt;p&gt;Every time I put in a DVD (House, Bones, almost anything) I'd get the parental control screen that I'd have to temporarily unlock.  While entering 0000 wasn't that difficult, it was annoying to have to do this before I could get through all the FBI warnings and to the DVD menu... and finally to my content.&lt;/p&gt;

&lt;p&gt;Unfortunately it's hard to figure this out and the instructions are buried in the manual.  It's like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Play a DVD&lt;/li&gt;
&lt;li&gt;Stop the DVD&lt;/li&gt;
&lt;li&gt;Enter select to get to the custom menu.&lt;/li&gt;
&lt;li&gt;Enter X on the briefcase icon.&lt;/li&gt;
&lt;li&gt;Select the &quot;lock&quot; by moving right.&lt;/li&gt;
&lt;li&gt;Go down to the parental settings and set the level to 'OFF'&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;It's more complicated than any game cheat I've had to do.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Smarter excerpts: the art of the semi-automatic CMS</title>
   <link href="http://davedash.com/2008/02/28/smarter-excerpts-the-art-of-the-semi-automatic-cms/"/>
   <updated>2008-02-28T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/02/28/smarter-excerpts-the-art-of-the-semi-automatic-cms</id>
   <content type="html">&lt;p&gt;I was browsing the &lt;a href=&quot;http://ted.com/&quot;&gt;TED&lt;/a&gt; site, since it's all up in my blogospheres and ran across this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://spindrop.us/wp-content/uploads/2008/02/picture-1.png&quot; alt=&quot;Picture 1.png&quot; border=&quot;0&quot; width=&quot;689&quot; height=&quot;340&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you look at the excerpts, they are piss poor descriptions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Frans Lanting is one of the greatest nature p...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;Nature p-what?  Nature painter?  Nature preserver?  If you click around enough... the answer is nature photographer.  Many of the excerpts failed at giving me any indication of who these people are or even enticing me to find out.  I am a web 2.0 person, if I have to click on a link and load a new page, then it better be good.  When I'm doing an information binge, I am not going to have that level of patience.&lt;/p&gt;

&lt;p&gt;One day at del.icio.us I decided to test the limits of every profile field... and I learned that every now and then you &lt;em&gt;do&lt;/em&gt; need to truncate user generated content.&lt;/p&gt;

&lt;p&gt;This page however, is trusted users who have edited structured content (to borrow &lt;a href=&quot;http://www.djangobook.com/en/1.0/chapter17/&quot;&gt;a term from the Django Book&lt;/a&gt;).  That means, that someone had to enter in a description for this person.  Someone who is trusted at TED.  Chances are the page was rendered to trim the excerpt at 46 characters.&lt;/p&gt;

&lt;p&gt;There's two easy solutions to this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;DHTML&lt;/p&gt;

&lt;p&gt; This remaining excerpt could have been hidden away, and a button that said &quot;show all&quot; or &quot;expand&quot; (or whatever is the usable phrase/icon) could show the full except.  This prevents me from having to jump around.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Semi-Automatic excerpts&lt;/p&gt;

&lt;p&gt; We are talking about &quot;trusted users&quot; meaning, we can trust them to do things that humans do better than machines (there's my del.icio.us humans-do-some-things-better mentality).  When they enter the description for a person, their administration interface should be able to suggest an excerpt and they, the &quot;trusted user&quot; should be able to make adjustments or tweaks.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;The former solution is far easier, but if you're scanning a site, especially one as extensive as &lt;a href=&quot;http://www.ted.com/index.php/speakers&quot;&gt;TED's speakers listing&lt;/a&gt;, the last thing you want to do is click &quot;expand&quot; buttons everywhere to read everything.  The latter solution is smarter.  Of course, the problem could also be solved by upping the 46 character limit, but not everything should be fully automated.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Thoughts on Skype</title>
   <link href="http://davedash.com/2007/09/23/thoughts-on-skype/"/>
   <updated>2007-09-23T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/09/23/thoughts-on-skype</id>
   <content type="html">&lt;p&gt;[tags]skype, usability[/tags]&lt;/p&gt;

&lt;p&gt;So I've been thinking more and more about Skype lately.  Especially now that I have a cordless Skype phone from Philips.&lt;/p&gt;

&lt;h3&gt;Some easy UI Changes&lt;/h3&gt;

&lt;p&gt;The best UI change to Skype would be listing the time for everyone in your list and maybe an icon to indicate day or night.  I, like many of you, have people from US/Central, Holland, Japan, New Zealand and California.  It's really confusing... New Zealand is near the International Date Line!  I have to do a lot of mental math before I know it's okay or not to call them.&lt;/p&gt;

&lt;h3&gt;SkypeOut/Domestic calls&lt;/h3&gt;

&lt;p&gt;A few years ago, I would have thought that using Skype was a great idea.  Less than 3 cents a minute for calls?  Awesome.  Now I just use my cellphone for all my calls.  It's cheap.  A good portion of my friends also use T-mobile so those calls are free.  My wife and I share a family plan with a friend so those calls are free.  I've used 281/1000 shared minutes.  I think I'll stick with my cell phone for now.&lt;/p&gt;

&lt;p&gt;Even when Skype in the US was free, it wasn't worth using the service, so the current $3/month unlimited plans aren't really worth it.&lt;/p&gt;

&lt;h3&gt;International calls&lt;/h3&gt;

&lt;p&gt;International calls are cool, but honestly I don't talk to people that much domestically.  It is nice to know that I can pick up the phone and for pennies call my relatives in India or my friends in East Asia and Europe.  It's not the cheapest, but the convenience of Skype does win.&lt;/p&gt;

&lt;h3&gt;SkypeIn&lt;/h3&gt;

&lt;p&gt;SkypeIn also sounds really appealing... maybe because I have a new handset that I'd like to ring.  Also the thought of having a number that I can dispose of, use as a business line, forward elsewhere have a new area code, etc.&lt;/p&gt;

&lt;p&gt;It'd be nice if I could get an Indian Skype number for my family.&lt;/p&gt;

&lt;p&gt;Man... Skype would have been so awesome 5-10 years ago.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Thoughts on Skype</title>
   <link href="http://davedash.com/2007/09/23/thoughts-on-skype/"/>
   <updated>2007-09-23T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/09/23/thoughts-on-skype</id>
   <content type="html">&lt;p&gt;[tags]skype, usability[/tags]&lt;/p&gt;

&lt;p&gt;So I've been thinking more and more about Skype lately.  Especially now that I have a cordless Skype phone from Philips.&lt;/p&gt;

&lt;h3&gt;Some easy UI Changes&lt;/h3&gt;

&lt;p&gt;The best UI change to Skype would be listing the time for everyone in your list and maybe an icon to indicate day or night.  I, like many of you, have people from US/Central, Holland, Japan, New Zealand and California.  It's really confusing... New Zealand is near the International Date Line!  I have to do a lot of mental math before I know it's okay or not to call them.&lt;/p&gt;

&lt;h3&gt;SkypeOut/Domestic calls&lt;/h3&gt;

&lt;p&gt;A few years ago, I would have thought that using Skype was a great idea.  Less than 3 cents a minute for calls?  Awesome.  Now I just use my cellphone for all my calls.  It's cheap.  A good portion of my friends also use T-mobile so those calls are free.  My wife and I share a family plan with a friend so those calls are free.  I've used 281/1000 shared minutes.  I think I'll stick with my cell phone for now.&lt;/p&gt;

&lt;p&gt;Even when Skype in the US was free, it wasn't worth using the service, so the current $3/month unlimited plans aren't really worth it.&lt;/p&gt;

&lt;h3&gt;International calls&lt;/h3&gt;

&lt;p&gt;International calls are cool, but honestly I don't talk to people that much domestically.  It is nice to know that I can pick up the phone and for pennies call my relatives in India or my friends in East Asia and Europe.  It's not the cheapest, but the convenience of Skype does win.&lt;/p&gt;

&lt;h3&gt;SkypeIn&lt;/h3&gt;

&lt;p&gt;SkypeIn also sounds really appealing... maybe because I have a new handset that I'd like to ring.  Also the thought of having a number that I can dispose of, use as a business line, forward elsewhere have a new area code, etc.&lt;/p&gt;

&lt;p&gt;It'd be nice if I could get an Indian Skype number for my family.&lt;/p&gt;

&lt;p&gt;Man... Skype would have been so awesome 5-10 years ago.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Usability for a limited audience and learnability</title>
   <link href="http://davedash.com/2007/07/19/usability-for-a-limited-audience-and-learnability/"/>
   <updated>2007-07-19T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/07/19/usability-for-a-limited-audience-and-learnability</id>
   <content type="html">&lt;p&gt;[tags]usability, learnability, english[/tags]&lt;/p&gt;

&lt;p&gt;Usability for a limited audience... (for example a web app for one person, or a small team) is far far different than web usability for a public web site.&lt;/p&gt;

&lt;p&gt;In many ways it's easier.  You can think about it in terms of what would Joe, Bob, Sue or whoever is using the site would think.  Usually design constraints are normalized, like screen resolution.&lt;/p&gt;

&lt;p&gt;It gets tricky though when your audience wants an interface that others might not consider usable.  For example, having an optimal resolution of 1920x1200 or having less readable labels for controls, because they are learnable (we'll touch on learn-ability soon).&lt;/p&gt;

&lt;p&gt;Sometimes you got to bite the bullet and actually suppress what you know about designing an easy to use interface and understand the needs of just your audience.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Usability for a limited audience and learnability</title>
   <link href="http://davedash.com/2007/07/19/usability-for-a-limited-audience-and-learnability/"/>
   <updated>2007-07-19T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/07/19/usability-for-a-limited-audience-and-learnability</id>
   <content type="html">&lt;p&gt;[tags]usability, learnability, english[/tags]&lt;/p&gt;

&lt;p&gt;Usability for a limited audience... (for example a web app for one person, or a small team) is far far different than web usability for a public web site.&lt;/p&gt;

&lt;p&gt;In many ways it's easier.  You can think about it in terms of what would Joe, Bob, Sue or whoever is using the site would think.  Usually design constraints are normalized, like screen resolution.&lt;/p&gt;

&lt;p&gt;It gets tricky though when your audience wants an interface that others might not consider usable.  For example, having an optimal resolution of 1920x1200 or having less readable labels for controls, because they are learnable (we'll touch on learn-ability soon).&lt;/p&gt;

&lt;p&gt;Sometimes you got to bite the bullet and actually suppress what you know about designing an easy to use interface and understand the needs of just your audience.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Flash video killed the RealMedia star...</title>
   <link href="http://davedash.com/2007/07/17/flash-video-killed-the-realmedia-star/"/>
   <updated>2007-07-17T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/07/17/flash-video-killed-the-realmedia-star</id>
   <content type="html">&lt;p&gt;[tags]youtube, video, flash, quicktime, windows media, real media, cnn[/tags]&lt;/p&gt;

&lt;p&gt;and Quicktime and Windows Media Player... almost.&lt;/p&gt;

&lt;p&gt;Embedded flash video is great and plays almost universally on peoples web browsers since the plugin is so widely installed.&lt;/p&gt;

&lt;p&gt;Some web sites still insist on supporting plugins for players that just don't work too hot on the web.  CNN still insists on RealMedia or WindowsMedia Player.  It's time to grow up.  RealMedia is dead from an unexperienced enduser's perspective.  WindowsMedia Player doesn't work so great for the Mac.  Flash for the win.&lt;/p&gt;

&lt;p&gt;So wake up CNN to the YouTube'd generation.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Blindly Trusting Locks</title>
   <link href="http://davedash.com/2007/03/20/blindly-trusting-locks/"/>
   <updated>2007-03-20T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/03/20/blindly-trusting-locks</id>
   <content type="html">&lt;p&gt;[tags]design,usability[/tags]&lt;/p&gt;

&lt;p&gt;How many times have you been minding your business, assuming you have total and complete privacy and &lt;strong&gt;BAM&lt;/strong&gt; the privacy is broken for a split second as someone bursts into your private haven that you've made of the public rest room.&lt;/p&gt;

&lt;p&gt;Those locks never seem to work.  I don't like blindly trusting a lock.  If I push a button, how do I &lt;em&gt;know&lt;/em&gt; it works?  I don't.  What I do like is big heavy dead bolts that I know work.  I turn the device and if I can't see it, I can at least feel that it's preventing the door to open.&lt;/p&gt;

&lt;p&gt;Even better are the bolts that actually mark a room as being occupied (like the lavatories on airplanes).&lt;/p&gt;

&lt;p&gt;Then there are the latches and levers that make a vain attempt at locking, but really just don't do what they say they're going to do.&lt;/p&gt;

&lt;p&gt;I thought about this, and it makes for a great design analogy...&lt;/p&gt;

&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We need to make features that people don't need to blindly trust.&lt;/li&gt;
&lt;li&gt;We need to make features that are trustworthy.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;When I hit save, or I hit modify in a web app, I want to know that the save occurred or the modification took place.  I shouldn't have to glue my eyes to the screen and just look for that flash that occurs when a browser refreshes.  With Ajax, things like notification are generally planned out in advance (indicators, etc).  At the same time, they are absolutely necessary.  Features need some sort of feedback to tell you, yes, I did exactly what you wanted.&lt;/p&gt;

&lt;p&gt;We also need things that are trustworthy.  If a feature is enabled or activated and there's a notice, let us know.   But don't lie.  Do whatever sanity checks that need to get done to make sure this really occurred.  Don't be the bathroom stall lock that says it's locked but gets easily unlocked with a gentle nudge.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Blindly Trusting Locks</title>
   <link href="http://davedash.com/2007/03/20/blindly-trusting-locks/"/>
   <updated>2007-03-20T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/03/20/blindly-trusting-locks</id>
   <content type="html">&lt;p&gt;[tags]design,usability[/tags]&lt;/p&gt;

&lt;p&gt;How many times have you been minding your business, assuming you have total and complete privacy and &lt;strong&gt;BAM&lt;/strong&gt; the privacy is broken for a split second as someone bursts into your private haven that you've made of the public rest room.&lt;/p&gt;

&lt;p&gt;Those locks never seem to work.  I don't like blindly trusting a lock.  If I push a button, how do I &lt;em&gt;know&lt;/em&gt; it works?  I don't.  What I do like is big heavy dead bolts that I know work.  I turn the device and if I can't see it, I can at least feel that it's preventing the door to open.&lt;/p&gt;

&lt;p&gt;Even better are the bolts that actually mark a room as being occupied (like the lavatories on airplanes).&lt;/p&gt;

&lt;p&gt;Then there are the latches and levers that make a vain attempt at locking, but really just don't do what they say they're going to do.&lt;/p&gt;

&lt;p&gt;I thought about this, and it makes for a great design analogy...&lt;/p&gt;

&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We need to make features that people don't need to blindly trust.&lt;/li&gt;
&lt;li&gt;We need to make features that are trustworthy.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;When I hit save, or I hit modify in a web app, I want to know that the save occurred or the modification took place.  I shouldn't have to glue my eyes to the screen and just look for that flash that occurs when a browser refreshes.  With Ajax, things like notification are generally planned out in advance (indicators, etc).  At the same time, they are absolutely necessary.  Features need some sort of feedback to tell you, yes, I did exactly what you wanted.&lt;/p&gt;

&lt;p&gt;We also need things that are trustworthy.  If a feature is enabled or activated and there's a notice, let us know.   But don't lie.  Do whatever sanity checks that need to get done to make sure this really occurred.  Don't be the bathroom stall lock that says it's locked but gets easily unlocked with a gentle nudge.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Making anchor links smarter... and sexier</title>
   <link href="http://davedash.com/2007/02/14/making-anchor-links-smarter-and-sexier/"/>
   <updated>2007-02-14T00:00:00-08:00</updated>
   <id>http://davedash.com/2007/02/14/making-anchor-links-smarter-and-sexier</id>
   <content type="html">&lt;p&gt;So I have a small bone to pick with Jacob Nielsen and his &lt;a href=&quot;http://www.useit.com/alertbox/within_page_links.html&quot;&gt;opinion on within-page links&lt;/a&gt; or anchor links&lt;sup id=&quot;fnr1&quot;&gt;.&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;  There clearly is a benefit to not just linking to a specific page, but linking to a specific part of a page.&lt;/p&gt;

&lt;p&gt;With a little help from &lt;a href=&quot;http://script.aculo.us/&quot;&gt;script.aculo.us&lt;/a&gt; we can spice up our anchor links by highlighting them as well as linking to them.&lt;/p&gt;

&lt;p&gt;For this article we'll limit our scope to internal anchors only.&lt;sup&gt;&lt;a href=&quot;#fn2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;  We'll write the code using the symfony framework and in straight up &lt;acronym title=&quot;eXtended HypterText Markup Language&quot;&gt;XHTML&lt;/acronym&gt;.  This is really dirt simple and is more of a design pattern with an example than a tutorial.&lt;/p&gt;

&lt;p&gt;Let's do the &lt;acronym title=&quot;eXtended HypterText Markup Language&quot;&gt;XHTML&lt;/acronym&gt; first:&lt;/p&gt;

&lt;div&gt;
    
    &lt;textarea name=&quot;code&quot; class=&quot;xhtml&quot; rows=&quot;10&quot; cols=&quot;50&quot;&gt;
    &amp;lt;a href=&amp;quot;#test&amp;quot; onclick=&amp;quot;new Effect.Highlight(&amp;apos;test&amp;apos;)&amp;quot;&amp;gt;this is a test&amp;lt;/a&amp;gt;
&lt;/textarea&gt;

&lt;/div&gt;


&lt;p&gt;Yup, that's it... I told you it was dirt simple.  You just need to include the proper &lt;a href=&quot;http://prototypejs.org/&quot;&gt;prototype&lt;/a&gt; and &lt;a href=&quot;http://script.aculo.us/&quot;&gt;script.aculo.us&lt;/a&gt; libraries.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;http://symfony-project.com/&quot;&gt;symfony&lt;/a&gt; we avoid repeating ourselves with a helper function:&lt;/p&gt;

&lt;div&gt;
    
&lt;textarea name=&quot;code&quot; class=&quot;php&quot; rows=&quot;10&quot; cols=&quot;50&quot;&gt;
    function link_to_anchor($text, $target)
    {
        return link_to($text, '#'.$target, 'onclick='.visual_effect('highlight',$target);
    }
&lt;/textarea&gt;

&lt;/div&gt;


&lt;p&gt;and call it by doing:&lt;/p&gt;

&lt;div&gt;
    
    &lt;textarea name=&quot;code&quot; class=&quot;php&quot; rows=&quot;10&quot; cols=&quot;50&quot;&gt;
    echo link_to_anchor('this is a test', 'test');
    &lt;/textarea&gt;

&lt;/div&gt;


&lt;p&gt;That's it.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
    &lt;hr/&gt;
    &lt;ol&gt;
        &lt;li id=&quot;fn1&quot;&gt;Jacob Nielsen is an easy target. &lt;a href=&quot;#fnr1&quot; class=&quot;footnoteBackLink&quot;  title=&quot;Jump back to footnote 1 in the text.&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;
        
        &lt;li id=&quot;fn2&quot;&gt;Anchors on other pages are equally useful.  To implement that, you need to have an event listener to examine the URL for an anchor and appropriately highlight the correct element. &lt;a href=&quot;#fnr2&quot; class=&quot;footnoteBackLink&quot;  title=&quot;Jump back to footnote 2 in the text.&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>Cropping Images using DHTML (Prototype) and symfony</title>
   <link href="http://davedash.com/2006/09/16/cropping-images-using-dhtml-prototype-and-symfony/"/>
   <updated>2006-09-16T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/09/16/cropping-images-using-dhtml-prototype-and-symfony</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://demos.spindrop.us/image_cropper/&quot;&gt;&lt;img src=&quot;http://demos.spindrop.us/image_cropper/images/screenshot.png&quot; style=&quot;float:left;margin-right:1em&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Like many of my tutorials, you don't &lt;em&gt;need&lt;/em&gt; &lt;a href=&quot;http://symfony-project.com/&quot;&gt;symfony&lt;/a&gt;, just &lt;a href=&quot;http://php.net/&quot;&gt;PHP&lt;/a&gt;.  However, I develop in &lt;a href=&quot;http://symfony-project.com/&quot;&gt;symfony&lt;/a&gt; and take advantage of the &lt;acronym title=&quot;Model Viewer Controller&quot;&gt;MVC&lt;/acronym&gt;-support that it offers.&lt;/p&gt;

&lt;p&gt;Years ago when I was working on a photo gallery for &lt;a href=&quot;http://davedash.com/&quot;&gt;davedash.com&lt;/a&gt; I got the art of making tumbnails down fairly well.  It was automated and didn't allow for specifying how the thumbnail should be made.  With dozens of photos (which was a lot back then), when would I find that kind of time.&lt;/p&gt;

&lt;p&gt;Flashback to today, for &lt;a href=&quot;http://workface.com/&quot;&gt;my company&lt;/a&gt;... we want users with avatars... but nothing too large.  Maybe a nice 80x80 picture.  Well the coolest &lt;acronym title=&quot;User Interface&quot;&gt;UI&lt;/acronym&gt; I've seen was Apple's Address Book which let you use this slider mechanism to crop a fixed sized image from a larger image.&lt;/p&gt;

&lt;p&gt;Here's a &lt;a href=&quot;http://demos.spindrop.us/image_cropper/&quot;&gt;demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;

&lt;h3&gt;Overview&lt;/h3&gt;

&lt;p&gt;The front-end &lt;acronym title=&quot;Graphical User Interface&quot;&gt;GUI&lt;/acronym&gt; is based on code from &lt;a href=&quot;http://digg.com/&quot;&gt;digg&lt;/a&gt; which is based on the look and feel (as near as I can tell) from Apple.&lt;/p&gt;

&lt;p&gt;The &lt;acronym title=&quot;Graphical User Interface&quot;&gt;GUI&lt;/acronym&gt; provides a clever visual way of telling the server how to chop the image.  The gist is this, sliding the image around and zooming in and out change a few form values that get passed to another script which uses this data to produce the image.&lt;/p&gt;

&lt;h3&gt;Frontend: What would you like to crop?&lt;/h3&gt;

&lt;p&gt;In this tutorial, we're going to be cropping an 80x80 avatar from an uploaded image.  The front-end requires the correct mix of Javascript, &lt;acronym title=&quot;Cascading Style Sheets&quot;&gt;CSS&lt;/acronym&gt;, &lt;acronym title=&quot;HypterText Markup Languag&quot;&gt;HTML&lt;/acronym&gt; and images.  The Javascript sets up the initial placements of the image and the controls.  The &lt;acronym title=&quot;Cascading Style Sheets&quot;&gt;CSS&lt;/acronym&gt; presents some necessary styling.  The images makeup some of the controls.  The &lt;acronym title=&quot;HyperText Markup Language&quot;&gt;HTML&lt;/acronym&gt; glues everything together.&lt;/p&gt;

&lt;h4&gt;&lt;acronym title=&quot;HyperText Markup Language&quot;&gt;HTML&lt;/acronym&gt;&lt;/h4&gt;

&lt;p&gt;Let's work on our &lt;acronym title=&quot;HyperText Markup Language&quot;&gt;HTML&lt;/acronym&gt; first.  Since I used &lt;a href=&quot;http://symfony-project.com/&quot;&gt;symfony&lt;/a&gt;, I created a &lt;code&gt;crop&lt;/code&gt; action for a &lt;code&gt;userpics&lt;/code&gt; module.  So in our &lt;code&gt;cropSuccess.php&lt;/code&gt; template:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div id=&quot;ava&quot;&amp;gt;
    &amp;lt;?php echo form_tag(&quot;userpics/crop&quot;) ?&amp;gt;
        &amp;lt;div id=&quot;ava_img&quot;&amp;gt;
            &amp;lt;div id=&quot;ava_overlay&quot;&amp;gt;&amp;lt;/div&amp;gt;
            &amp;lt;div id=&quot;ava_drager&quot;&amp;gt;&amp;lt;/div&amp;gt;
            &amp;lt;img src=&quot;&amp;lt;?php echo $image ?&amp;gt;&quot; id=&quot;avatar&quot; /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div id=&quot;ava_slider&quot;&amp;gt;&amp;lt;div id=&quot;ava_handle&quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;input type=&quot;hidden&quot; id=&quot;ava_width&quot; name=&quot;width&quot; value=&quot;80&quot; /&amp;gt;
        &amp;lt;input type=&quot;hidden&quot; id=&quot;ava_x&quot; name=&quot;x&quot; value=&quot;100&quot; /&amp;gt;
        &amp;lt;input type=&quot;hidden&quot; id=&quot;ava_y&quot; name=&quot;y&quot; value=&quot;100&quot; /&amp;gt;
        &amp;lt;input type=&quot;hidden&quot; id=&quot;ava_image&quot; name=&quot;file&quot; value=&quot;&amp;lt;?php echo $image ?&amp;gt;&quot; /&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;input type=&quot;submit&quot; name=&quot;submit&quot; id=&quot;ava_submit&quot; value=&quot;Crop&quot; style=&quot;width: auto; font-size: 105%; font-weight: bold; margin: 1em 0;&quot; /&amp;gt;
    &amp;lt;/form&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Right now a lot of this doesn't quite make sense.  If you attempt to render it, you will just see only the image.  As we add the corresponding &lt;acronym title=&quot;Cascading Style Sheets&quot;&gt;CSS&lt;/acronym&gt; and images it will make some more sense.&lt;/p&gt;

&lt;h4&gt;&lt;acronym title=&quot;Cascading Style Sheets&quot;&gt;CSS&lt;/acronym&gt; and corresponding images&lt;/h4&gt;

&lt;p&gt;We'll go through each style individually and explain what purpose it serves in terms of the &lt;acronym title=&quot;Graphical User Interface&quot;&gt;GUI&lt;/acronym&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#ava&lt;/code&gt; is our container.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#ava {
    border: 1px solid gray;
     width: 200px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;#ava_img&lt;/code&gt; is the area that contains our image.  Our window for editing this image 200x200 pixels.  If we drag out image out of bounds we just want the overflowing image to be clipped.  We also want our position to be relative so any child elements can be positioned absolutely with respect to &lt;code&gt;#ava_img&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#ava_img {
    width: 200px;
    height: 200px;
    overflow: hidden;
    position: relative;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;div style=&quot;float:left;margin: 1em 1em 1em 0&quot;&gt;
    &lt;img src=&quot;http://demos.spindrop.us/image_cropper/images/overlay.png&quot; alt=&quot;overlay&quot; /&gt;
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;#ava_overlay&lt;/code&gt; is a window we use to see what exactly will be our avatar.  If it's in the small 80x80 window in the center of the image, then it's part of the avatar.  If it's in the fuzzy region, then it's getting cropped out.  This overlay of course needs to be positioned absolutely.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#ava_overlay {
    width: 200px;
    height: 200px;
    position: absolute;
    top: 0px;
    left: 0px;
    background: url('/images/overlay.png');
    z-index: 50;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;#ava_drager&lt;/code&gt; is probably the least intuitive element (Heck, I'm not even sure if I've even got it right).  In &lt;a href=&quot;http://demos.spindrop.us/image_cropper/&quot;&gt;our demo&lt;/a&gt; you're not actually dragging the image, because you can drag anywhere within the &lt;code&gt;#ava_img&lt;/code&gt; container and move the image around.  You're using dragging an invisible handle.  It's a 400x400 pixel square that can be dragged all over the container and thusly move the image as needed.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#ava_drager {
    width: 400px;
    height: 400px;
    position: absolute;
    z-index: 100;
    color: #fff;
    cursor: move;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;#avatar&lt;/code&gt; is our image, and since it will be moving all around the window, it requires absolute positioning.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#avatar {
    position: absolute;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;div style=&quot;float:left;margin: 1em 1em 1em 0&quot;&gt;
    &lt;img src=&quot;http://demos.spindrop.us/image_cropper/images/slider_back.png&quot; alt=&quot;overlay&quot; /&gt;
&lt;/div&gt;


&lt;div style=&quot;float:left;margin-left: 1em 1em 1em 0;&quot;&gt;
    &lt;img src=&quot;http://demos.spindrop.us/image_cropper/images/handle.png&quot; alt=&quot;overlay&quot; /&gt;
&lt;/div&gt;


&lt;p&gt;&lt;code&gt;#ava_slider&lt;/code&gt; and &lt;code&gt;#ava_handle&lt;/code&gt; are our slider components.  They should be self-explanatory.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#ava_slider {
    width: 200px;
    height: 27px;
    background: #eee;
    position: relative;
    border-top: 1px solid gray; 
    background: url('/images/slider_back.png');
}
#ava_handle {
    width: 19px;
    height: 20px;
    background: blue;
    position: absolute;
    background: url('/images/handle.png');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h5&gt;Internet Explorer&lt;/h5&gt;

&lt;p&gt;&lt;acronym title=&quot;Portable Network Graphics&quot;&gt;PNG&lt;/acronym&gt; do not work so well in Internet Explorer, but there is a small trick, adding these components into a style sheet that only IE can read will make things work:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#ava_overlay {
  background: none;
  filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/ui/cropper/overlay.png', sizingMethod='crop');
}

#ava_handle {
  background: none;
  filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/images/ui/cropper/handle.png', sizingMethod='crop');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;The Javascript&lt;/h4&gt;

&lt;p&gt;The Javascript is actually not as complicated as you'd expect thanks to the wonder of &lt;a href=&quot;http://prototype.conio.net/&quot;&gt;prototype&lt;/a&gt;.  This framework provides so much so easily.  You'll need to include &lt;a href=&quot;http://prototype.conio.net/&quot;&gt;prototype.js&lt;/a&gt; and &lt;a href=&quot;http://boring.youngpup.net/2001/domdrag/project&quot;&gt;dom-drag.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So let's take a look.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&quot;text/javascript&quot; language=&quot;javascript&quot; charset=&quot;utf-8&quot;&amp;gt;
// &amp;lt;![CDATA[
function setupAva() {
    if ($(&quot;avatar&quot;)) {
        var handle = $(&quot;ava_handle&quot;);
        var avatar = $(&quot;avatar&quot;);
        var drager = $(&quot;ava_drager&quot;);
        var slider = $(&quot;ava_slider&quot;);
        var ava_width = $(&quot;ava_width&quot;);
        var ava_x = $(&quot;ava_x&quot;);
        var ava_y = $(&quot;ava_y&quot;);
        // four numbers are minx, maxx, miny, maxy
        Drag.init(handle, null, 0, 134, 0, 0);
        Drag.init(drager, avatar, -100, 350, -100, 350);
        var start_w = avatar.width;
        var start_h = avatar.height;
        var ratio = (start_h / start_w);
        var new_h;
        var new_w;
        if (ratio &amp;gt; 1) {
            new_w = 80;
            new_h = (80*start_h)/start_w;
        } else {
            new_h = 80;
            new_w = (80*start_w)/start_h;
        }
        // these need to be set after we init
        avatar.style.top = '100px';
        avatar.style.left = '100px';
        avatar.style.width = new_w + 'px';
        avatar.style.height = new_h + 'px';
        avatar.style.margin = '-' + (new_h / 2) + 'px 0 0 -' + (new_w / 2) + 'px';
        handle.style.margin = '3px 0 0 20px';
        avatar.onDrag = function(x, y) {
            ava_x.value = x;
            ava_y.value = y;
        }
        handle.onDrag = function(x, y) {
            var n_width = (new_w + (x * 2));
            var n_height = (new_h + ((x * 2) * ratio));         
            avatar.style.width = n_width + 'px';
            avatar.style.height = n_height+ 'px';
            ava_width.value = n_width;  
            avatar.style.margin = '-' + (n_height / 2) + 'px 0 0 -' + (n_width / 2) + 'px';
        }
    }
}
Event.observe(window,'load',setupAva, false);
// ]]&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If this isn't exactly crystal clear, I can explain.  If you're new to &lt;a href=&quot;http://prototype.conio.net/&quot;&gt;prototype&lt;/a&gt;, &lt;code&gt;$()&lt;/code&gt; is the same as &lt;code&gt;doucment.getElementByID()&lt;/code&gt; (at least for our purposes).&lt;/p&gt;

&lt;p&gt;We need to initialize two draggable elements, one is our slider for zooming and the other is our avatar itself.  We initialize the draggers using &lt;code&gt;Drag.init()&lt;/code&gt;.  We specify what to drag, if another element should be used as a handle and then the range of motion in xy coordinates.  In the second call we use that &lt;code&gt;#dragger&lt;/code&gt; to move around the image in this manner.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Drag.init(handle, null, 0, 134, 0, 0);
Drag.init(drager, avatar, -100, 350, -100, 350);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We want to initialize the the size and placement of the avatar.  We do that using maths.  First we want it in our 80x80 pixel box.  So it should be roughly 80x80.  I've set the math up so that the &lt;em&gt;smallest&lt;/em&gt; side is 80 pixels (there's reasons for doing this the other way around).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    if (ratio &amp;gt; 1) {
        new_w = 80;
        new_h = (80*start_h)/start_w;
    } else {
        new_h = 80;
        new_w = (80*start_w)/start_h;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We then place the avatar element.  We initialize it to be in the center of the screen (&lt;code&gt;top: 100px;left:100px&lt;/code&gt;) and then nudge the image using margins.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    avatar.style.top = '100px';
    avatar.style.left = '100px';
    avatar.style.width = new_w + 'px';
    avatar.style.height = new_h + 'px';
    avatar.style.margin = '-' + (new_h / 2) + 'px 0 0 -' + (new_w / 2) + 'px';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We also use margins to place the handle.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    handle.style.margin = '3px 0 0 20px';
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;#ava_x&lt;/code&gt; and &lt;code&gt;#ava_y&lt;/code&gt; tell us where the center of the avatar is.  So when the avatar is moved we need to set these again:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    avatar.onDrag = function(x, y) {
        ava_x.value = x;
        ava_y.value = y;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That was easy.  Slighly more complicated is the zoomer function.  We are basically adjusting the width and the height proportionately based on roughly where the slider is.  Note that we're still using that &lt;code&gt;ratio&lt;/code&gt; variable that we calculated earlier.  We basically take the new x-coordinate of the handle and allow our image to get just slightly larger than the &lt;code&gt;#ava_image&lt;/code&gt; container.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    handle.onDrag = function(x, y) {
        var n_width = (new_w + (x * 2));
        var n_height = (new_h + ((x * 2) * ratio));         
        avatar.style.width = n_width + 'px';
        avatar.style.height = n_height+ 'px';
        ava_width.value = n_width;  
        avatar.style.margin = '-' + (n_height / 2) + 'px 0 0 -' + (n_width / 2) + 'px';
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We want to load initialize the slider right away when the page loads: &lt;code&gt;Event.observe(window,'load',setupAva, false);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Not terribly hard or complicated.  Once these elements are all in place you have a working functioning slider.  It returns the x and y coordinates of the center of the image with respect to our 200x200 pixel &lt;code&gt;#ava_image&lt;/code&gt;.  It also tells us the new width of our image.  We feed this information into a new script and out should pop a new image which matches &lt;em&gt;exactly&lt;/em&gt; what we see in our &lt;acronym title=&quot;Graphical User Interface&quot;&gt;GUI&lt;/acronym&gt;.&lt;/p&gt;

&lt;p&gt;&lt;!--nextpage--&gt;&lt;/p&gt;

&lt;h3&gt;Processing the crop&lt;/h3&gt;

&lt;p&gt;Initially I was frustrated with the data that was being sent.  I knew the center of the image in relation to this 200x200 pixel canvas and its width... but what could I do with that.  Well I could just recreate what I saw in the &lt;acronym title=&quot;Graphical User Interface&quot;&gt;GUI&lt;/acronym&gt;.  I needed to create a 200x200 pixel image first, place my original avatar resized (and resampled) at the precise coordinates and &lt;em&gt;then&lt;/em&gt; cut out the center most 80x80 pixels to become the final avatar image.&lt;/p&gt;

&lt;p&gt;If you note in our template above for &lt;code&gt;cropSuccess.php&lt;/code&gt; we submit our form back to the &lt;code&gt;crop&lt;/code&gt; action.  Let's look at the action:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public function executeCrop()
{
    if ($this-&amp;gt;getRequestParameter('file')&amp;amp;&amp;amp;$this-&amp;gt;getRequestParameter('width')) {          // we are saving our cropped image
        // Load the original avatar into a GD image so we can manipulate it with GD
        $o_filename = $this-&amp;gt;getRequestParameter('file');  // we'll use this to find the file on our system
        $o_filename = sfConfig::get('sf_root_dir').'/web' . $o_filename;
        $o_im = @imagecreatetruecolor(80, 80) or die(&quot;Cannot Initialize new GD image stream&quot;);
        $o_imagetype = exif_imagetype($o_filename); // is this gif/jpeg/png

        // appropriately create the GD image
        switch ($o_imagetype) {
            case 1: // gif
                $o_im = imagecreatefromgif($o_filename);
                break;
            case 2: // jpeg
                $o_im = imagecreatefromjpeg($o_filename);   
                break;
            case 3: // png
                $o_im = imagecreatefrompng($o_filename);
                break;
        }

        // Let's create our canvas
        $im = @imagecreatetruecolor(200, 200) or die(&quot;Cannot Initialize new GD image stream&quot;);
        imagecolortransparent ( $im, 127 ); // set the transparency color to 127
        imagefilledrectangle( $im, 0, 0, 200, 200, 127 ); // fill the canvas with a transparent rectangle

        // let's get the new dimension for our image

        $new_width = $this-&amp;gt;getRequestParameter('width');
        $o_width = imageSX($o_im);
        $o_height = imageSY($o_im);

        $new_height = $o_height/$o_width * $new_width;

        // we place the image at the xy coordinate and then shift it so that the image is now centered at the xy coordinate
        $x = $this-&amp;gt;getRequestParameter('x') - $new_width/2;
        $y = $this-&amp;gt;getRequestParameter('y') - $new_height/2;

        // copy the original image resized and resampled onto the canvas
        imagecopyresampled($im,$o_im,$x,$y,0,0,$new_width,$new_height,$o_width,$o_height); 
        imagedestroy($o_im);

        // $final will be our final image, we will chop $im and take out the 80x80 center
        $final = @imagecreatetruecolor(80, 80) or die(&quot;Cannot Initialize new GD image stream&quot;);
        imagecolortransparent ( $final, 127 ); // maintain transparency

        //copy the center of our original image and store it here
        imagecopyresampled ( $final, $im, 0, 0, 60, 60, 80, 80, 80, 80 );
        imagedestroy($im);

        //save our new user pic
        $p = new Userpic();
        $p-&amp;gt;setUser($this-&amp;gt;getUser()-&amp;gt;getUser());
        $p-&amp;gt;setGD2($final);
        $p-&amp;gt;save();
        imagedestroy($final);
        $this-&amp;gt;userpic = $p;
        return &quot;Finished&quot;;
    }


    $this-&amp;gt;getResponse()-&amp;gt;addJavascript(&quot;dom-drag&quot;);
    $this-&amp;gt;getResponse()-&amp;gt;addJavascript('/sf/js/prototype/prototype');
    $this-&amp;gt;getResponse()-&amp;gt;addJavascript('/sf/js/prototype/effects');
    $this-&amp;gt;image = '/images/userpics/originals/' . $this-&amp;gt;getRequestParameter('file');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It's doing exactly what the paragraph above explains when the image dimensions are given.  The code is well commented so it should be easy enough to follow.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.php.net/manual/en/ref.image.php&quot;&gt;GD image functions in PHP&lt;/a&gt; are fairly robust and can help you do a lot of tricks with image data.  Note the code to save the image, we'll cover it in detail soon.&lt;/p&gt;

&lt;h3&gt;The Model&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;$p = new Userpic();
$p-&amp;gt;setUser($this-&amp;gt;getUser()-&amp;gt;getUser());
$p-&amp;gt;setGD2($final);
$p-&amp;gt;save();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First some clarification the second line.  &lt;code&gt;myUser::getUser()&lt;/code&gt; gets the &lt;code&gt;User&lt;/code&gt; object associated with the currently logged in user.  The third line, however, is where the magic happens.  Before we look at it, let's have a quick look at our model:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;userpic:
 _attributes: { phpName: Userpic }
 id:
 user_id:
 image: blob
 thumb: blob
 created_at:
 updated_at:
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We have an &lt;code&gt;image&lt;/code&gt; attribute and a &lt;code&gt;thumb&lt;/code&gt; property to our &lt;code&gt;Userpic&lt;/code&gt; object.  This is where we store &lt;acronym title=&quot;Portable Network Graphics&quot;&gt;PNG&lt;/acronym&gt; versions of each icon and their 16x16 thumbnails respectively.  We do this in &lt;code&gt;Userpic::setGD2()&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public function setGD2($gd2_image)
{
    //convert to PNG
    ob_start();
    imagepng($gd2_image);
    $png = ob_get_clean();
    //save 16x16
    $gd2_tn = @imagecreatetruecolor(16, 16) or die(&quot;Cannot Initialize new GD image stream&quot;);
    imagealphablending( $gd2_tn, true );
    imagecolortransparent ( $gd2_tn, 127 );

    imagecopyresampled ( $gd2_tn, $gd2_image, 0, 0, 0, 0, 16, 16, 80, 80 );
    ob_start();
    imagepng($gd2_tn);
    $tn = ob_get_clean();

    $this-&amp;gt;setImage($png);
    $this-&amp;gt;setThumb($tn);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We capture the output of the full size &lt;acronym title=&quot;Portable Network Graphics&quot;&gt;PNG&lt;/acronym&gt;, then we scale it again and capture the output of the thumbnail and set them.&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;When it comes to web apps, having a relatively simple &lt;acronym title=&quot;Graphical User Interface&quot;&gt;GUI&lt;/acronym&gt; for people to resize images can go a long way in terms of adoption rate of avatars and custom user pictures by non technical users.&lt;/p&gt;

&lt;p&gt;Enjoy, and if you found this useful (or better implemented it) let me know.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Slick Designs and Bad Usability: Translucent Text</title>
   <link href="http://davedash.com/2006/08/01/slick-designs-and-bad-usability-translucent-text/"/>
   <updated>2006-08-01T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/08/01/slick-designs-and-bad-usability-translucent-text</id>
   <content type="html">&lt;div style=&quot;float:left; margin-right: 1em;&quot;&gt;
&lt;img src=&quot;http://static.flickr.com/45/180202469_b98fcaf836_m.jpg&quot; alt=&quot;Minneapolis Central Library&quot; /&gt;
&lt;/div&gt;


&lt;p&gt;Not to pick on the &lt;a href=&quot;http://www.mpls.lib.mn.us/newcentrallib.asp&quot; title=&quot;Central Library of the Minneapolis Public Library System&quot;&gt;Minneapolis Public Library&lt;/a&gt; &lt;em&gt;again&lt;/em&gt;... but they are really good at featuring &lt;a href=&quot;http://spindrop.us/2006/07/31/untuitive-interfaces-a-look-at-mpls-automatic-doors/&quot;&gt;usability flaws&lt;/a&gt;.  This one is also related to doors, and can very easily be related to web and software usability (if you can't tell, web and software usability are the exact same things as the usability of everyday things).&lt;/p&gt;

&lt;p&gt;Unfortunately I didn't have my digital camera, but the Emergency Exit doors at the &lt;a href=&quot;http://www.mpls.lib.mn.us/newcentrallib.asp&quot; title=&quot;Central Library of the Minneapolis Public Library System&quot;&gt;Minneapolis Public Library&lt;/a&gt; feature a translucent stenciling that says, &quot;Emergency Exit&quot; or &quot;Emergency Exit Only.&quot;  Of course, it was very easy to gloss over this important note attached to the door, after all, the door looked fairly ordinary, and opening it would seemingly bridge access from one area of the building to another, therefore inviting one and all to open it.  The cautionary notice about it being for Emergencies is easily dismissible.&lt;/p&gt;

&lt;p&gt;As a matter of fact, you know the nice translucent sign was failing to notify people when a laser-printed notice was taped to each and every emergency exit as a label.&lt;/p&gt;

&lt;p&gt;Obviously the designers were going for aesthetic.  &quot;Sure, we need an Emergency Exit, but it doesn't have to stick out.&quot;  In the real world, it seems people preferred having no aesthetics (laser printed sheets of paper are temporary, right) and usability over aesthetics and fire-alarms.&lt;/p&gt;

&lt;p&gt;The closest thing I can think of in the electronic world is the &quot;close&quot; feature of an application or a pop-up window.  If it says close, you know what it means.  If it's an &quot;X&quot; you know what it means.  If it's in &quot;red&quot; and &quot;red&quot; isn't part of the design, you know to maybe read what you're doing first.  But if we decide to have the close button look really pretty and part of that design means not labeling it or coloring it different from ... oh let's say the &quot;maximize window&quot; button.  It's easy to see how much user-frustration you can cause.&lt;/p&gt;

&lt;p&gt;I really wish I was there to see just how many times that Emergency Door was pushed before some library staff decided to whip open Microsoft Word and type in the largest font possible &quot;Emergency Exit Only&quot; and Scotch tape it on that door.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Untuitive Interfaces: A look at MPL's Automatic Doors</title>
   <link href="http://davedash.com/2006/07/31/untuitive-interfaces-a-look-at-mpls-automatic-doors/"/>
   <updated>2006-07-31T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/07/31/untuitive-interfaces-a-look-at-mpls-automatic-doors</id>
   <content type="html">&lt;div style=&quot;float:left; margin-right: 1em;&quot;&gt;

&lt;img src=&quot;http://static.flickr.com/74/154857391_19b99679ff_m.jpg&quot; alt=&quot;Minneapolis Central Library&quot; /&gt;
&lt;/div&gt;


&lt;p&gt;Every now and again, there's a tried and tested way of doing something and it gets enhanced somehow.  Sometimes these enhancements are pure genius and sometimes they are half-baked.  Today, we'll look at the half-baked automated doors at the new &lt;a href=&quot;http://www.mpls.lib.mn.us/newcentrallib.asp&quot; title=&quot;Central Library of the Minneapolis Public Library System&quot;&gt;Minneapols Public Library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Automated doors are all fairly standard.  There's either a platform that opens when weight is applied (a la grocery stores), or there are large buttons with an engraved handycapped****** symbol placed at wheelchair height.  Usually automated doors only work well when they are moved by the motor, and give quite a bit of resistance to manual operation.&lt;/p&gt;

&lt;p&gt;These aren't the most perfect designs in the world, in fact, there's plenty of room for change, for better or worse.  &lt;a href=&quot;http://www.mpls.lib.mn.us/newcentrallib.asp&quot; title=&quot;Central Library of the Minneapolis Public Library System&quot;&gt;MPL&lt;/a&gt;'s design involves making the entire door the button.  You push the door slightly, and then it opens (and somehow knows which direction to open, as to not smack you in the face).  &lt;em&gt;Pure Genius&lt;/em&gt;... almost.  While logically this makes sense, the flaw is in the execution.  When I approached the door, I pushed it, like it beckoned, and then pushed it again... and again, and then eventually it started opening.  Since it's motorized, you can't easily push it manually.  This 5-second frustration was more than just me, it was everyone wanting to get in.&lt;/p&gt;

&lt;p&gt;Fortunately it's not a bad design, it's just unresponsive.  If I pushed it, and the actuator took over immediately in a single smooth motion, this would be perfect.  Wheel chairs would gently run into the door and the door would open up.  People would attempt to push open the doors and &quot;voila!&quot; it'd give you a helping hand.&lt;/p&gt;

&lt;p&gt;This really isn't so much a rant about automated doors, so much as its a look at what I'd call as &quot;untuitiveness.&quot;  You have something which people do intuitively (e.g. push a door open) and then you break it.  In our example pushing a door to open it is now broken, because although pushing the door &lt;em&gt;slightly&lt;/em&gt; triggers the actuator, this is a lot different than what people expect.  Plus the added wait time results in more confusion.&lt;/p&gt;

&lt;p&gt;This can apply to web sites.  For example, let's take scroll bars.  A web site that doesn't fit in a browser window will often have horizontal and/or vertical scroll bars so that you can view the entire page.  We can easily change the interface for a scroll bar.  Maybe it's a thumbnail in the corner that shows a view finder (a la Photoshop ) and we use that to navigate and disable the scroll bars.  It's arguably a better interface, but it's going to cause problems for the end user ultimately since they 1. aren't used to it, and 2. there &lt;em&gt;might&lt;/em&gt; be some lag-time (assuming it's implemented with Flash or DHTML).&lt;/p&gt;

&lt;p&gt;This isn't to say we shouldn't come up with creative new ways of doing things -- we should -- but, some care needs to be taken toward usability.  After all, your site is just one site on the Internet, even if you have a high ranking web site, you're risking huge user-frustration if you try to do things too different -- to &quot;untuitive.&quot;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Usability for Nerds: Traversing URLs</title>
   <link href="http://davedash.com/2006/07/30/usability-for-nerds-traversing-urls/"/>
   <updated>2006-07-30T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/07/30/usability-for-nerds-traversing-urls</id>
   <content type="html">&lt;p&gt;A recent peeve of mine is &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt;s that you can't manually traverse.  Let me explain.  Let's say you visit &lt;code&gt;http://reviewsby.us/restaurant/cheesecake-factory&lt;/code&gt;.  You should manually be able to remove &lt;code&gt;cheesecake-factory&lt;/code&gt; and see an index page of restaurants at &lt;code&gt;http://reviewsby.us/restaurant/&lt;/code&gt;.  It makes logical sense for that page to be something that would enable you to find more restaurants.&lt;/p&gt;

&lt;p&gt;This is a throwback to static web sites, that consisted of directories and files.  If you accessed a file by its name, you would see the contents of the file (possibly filtered by the server).  If you accessed a directory, you would see an index of files.  In the world of web apps, however, &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt;s are made up.&lt;br/&gt;
&lt;!--more--&gt;
Web apps where these gaps are missing can be especially frustrating when you use your browser's history.  Often I reference the &lt;a href=&quot;http://www.symfony-project.com/api/symfony.html&quot;&gt;symfony api&lt;/a&gt;.  The &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt; is &lt;code&gt;http://www.symfony-project.com/api/symfony.html&lt;/code&gt;.  All the other &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt;s in the &lt;acronym title=&quot;Application Programing Interface&quot;&gt;API&lt;/acronym&gt; listing begin with &lt;code&gt;http://www.symfony-project.com/api/&lt;/code&gt;, so you could assume that &lt;code&gt;http://www.symfony-project.com/api/&lt;/code&gt; is an index page.&lt;/p&gt;

&lt;div style=&quot;&quot;&gt;
&lt;img src=&quot;http://static.flickr.com/60/200898792_9de3c68eb1.jpg&quot; width=&quot;500&quot; height=&quot;101&quot; alt=&quot;URL autocomplete&quot; /&gt;
&lt;/div&gt;


&lt;p&gt;It's not the index page (&lt;code&gt;http://symfony-project.com/api/symfony.html&lt;/code&gt; is).  If you googled for &lt;code&gt;sfConfig&lt;/code&gt; and got to &lt;code&gt;http://symfony-project.com/api/symfony/config/sfConfig.html&lt;/code&gt; and didn't feel like figuring out the navigation structure... or let's say at a later date you're using your browser's &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt; auto-complete feature, you will get a 404 Error&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Web applications can try to mirror directory indexes with pretty &lt;acronym title=&quot;URL&quot;&gt;URL&lt;/acronym&gt;s, but often have a few gaps as every &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt; (or level of &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt;) needs to be designated in the app.  Its a good idea to fill those in as it is another way to navigate a web site.&lt;/p&gt;

&lt;div id=&quot;footnotes&quot;&gt;
    &lt;hr/&gt;
    &lt;ol&gt;
        &lt;li id=&quot;fn1&quot;&gt;Not to pick on the wonderful symfony development team, but I truly do see this a lot on their site.  I'm sure they'll setup a redirect or something to fix this.  Or probably call me out on the fact that many of my sites violate this principle. &lt;a href=&quot;#fnr1&quot; class=&quot;footnoteBackLink&quot;  title=&quot;Jump back to footnote 1 in the text.&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>Do you like see-food?  See?  Food.</title>
   <link href="http://davedash.com/2006/07/29/do-you-like-see-food-see-food/"/>
   <updated>2006-07-29T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/07/29/do-you-like-see-food-see-food</id>
   <content type="html">&lt;div style=&quot;float:right&quot;&gt;
&lt;img src=&quot;http://reviewsby.us/menuitem_image/ed100b3be2d453a6574463bf63f3533d&quot; alt=&quot;Brownie Sundae&quot; /&gt;
&lt;/div&gt;


&lt;p&gt;The nice thing about some restaurants is they pay extra special attention to presentation.  That way if the food isn't to your taste, maybe it is at least pleasing to your eyes.  We know that just a list of each dish and comments about said dish served at a restaurant isn't going to fly.  But if we spruced it up with member-submitted pictures... well... now our eyes have something to see other than text and rating stars.&lt;/p&gt;

&lt;p&gt;Now, who wants a &lt;a href=&quot;http://reviewsby.us/restaurant/adeles-custard-stand/menu/brownie-sundae&quot;&gt;sundae in a boat&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://reviewsby.us/&quot;&gt;Restaurant Reviews By Us&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to remove file extensions from URLs</title>
   <link href="http://davedash.com/2006/07/26/how-to-remove-file-extensions-from-urls/"/>
   <updated>2006-07-26T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/07/26/how-to-remove-file-extensions-from-urls</id>
   <content type="html">&lt;p&gt;&lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt;s should be treated as prime real estate.  Their primary purpose is to locate resources on the Internet.  So for a web developer, it makes sense to make things as user-friendly as possible.  One effort is to remove the extensions from files.  I don't mean things like &lt;code&gt;.html&lt;/code&gt; or &lt;code&gt;.pdf&lt;/code&gt;, as those give you an idea that you're reading a page of content or a &lt;acronym title=&quot;Portable Document Format&quot;&gt;PDF&lt;/acronym&gt; document.  I meant things like &lt;code&gt;.php&lt;/code&gt; or &lt;code&gt;.asp&lt;/code&gt; or &lt;code&gt;.pl&lt;/code&gt;, etc.  These are unnecessary items that just clutter the location bar on most browsers.&lt;/p&gt;

&lt;p&gt;There are two ways to do this.  The easy way which just looks at a request, if the requested filename doesn't exist, then it looks for the filename with a &lt;code&gt;.php&lt;/code&gt; (or &lt;code&gt;.asp&lt;/code&gt; or whatever) extension.  In an &lt;code&gt;.htaccess&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ $1.php [L,QSA]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now if you go to: &lt;code&gt;http://domain/about&lt;/code&gt; the server will interpret it as if you went to &lt;code&gt;http://domain/about.php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Makes sense, but if we're already breaking the relation between &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt; and filename, we may as well break it intelligently.  &lt;!--next page--&gt;Change that &lt;code&gt;.htaccess&lt;/code&gt; file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now if you go to: &lt;code&gt;http://domain/about&lt;/code&gt; the server will interpret it as if you went to &lt;code&gt;http://domain/index.php?q=about&lt;/code&gt;.  How is this useful?  Well now &lt;code&gt;index.php&lt;/code&gt; is &lt;em&gt;always&lt;/em&gt; called, so it can do anything common to all pages (which might be nothing) and do something based on the &lt;code&gt;$_GET['q']&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require_once('html_functions.php');
switch ($_GET['q']) {
    case 'about':
        echo myhead('about page');
        break;
    default:
        echo myhead('home page')
        break;
}
include($_GET['q'] . '.php');
echo myfoot();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We're loading a hypothetical library &lt;code&gt;html_functions.php&lt;/code&gt; which contains some simple functions (&lt;code&gt;myhead()&lt;/code&gt; and &lt;code&gt;myfoot()&lt;/code&gt;) that print out a simple header or footer for this site.  The &lt;code&gt;switch&lt;/code&gt; statement dynamically sets the &lt;code&gt;&amp;lt;head/&amp;gt;&lt;/code&gt;.  After the &lt;code&gt;switch&lt;/code&gt; we include a file based on the query string.  In our case it will still pull up &lt;code&gt;about.php&lt;/code&gt;.  Granted, this is not what I use personally, but it's the general idea behind how &lt;a href=&quot;http://symfony-project.com/&quot;&gt;symfony&lt;/a&gt; works.&lt;/p&gt;

&lt;h3&gt;Why?&lt;/h3&gt;

&lt;p&gt;So why go through all this nonsense?  Extensions for the most part don't mean much to an end user.  Sure, &lt;code&gt;jpg&lt;/code&gt;, &lt;code&gt;png&lt;/code&gt; or &lt;code&gt;gif&lt;/code&gt; mean images and &lt;code&gt;html&lt;/code&gt; mean web page and &lt;code&gt;pdf&lt;/code&gt; means the file is a &lt;acronym title=&quot;Portable Document Format&quot;&gt;PDF&lt;/acronym&gt; document.  Dynamic pages, however usually come from &lt;code&gt;cgi&lt;/code&gt;, &lt;code&gt;php&lt;/code&gt;, &lt;code&gt;pl&lt;/code&gt; , &lt;code&gt;asp&lt;/code&gt;  pages or some other 3 or 4 letter extension that the server uses as a hint to determine how to parse, but the output is usually &lt;code&gt;html&lt;/code&gt;.  Servers are smart though.  They don't need hints, and the above code eliminates the need to reveal so explicitly just how a page is delivered.  Take our &lt;a href=&quot;http://reviewsby.us/&quot;&gt;restaurant review site&lt;/a&gt;, for the most part you can't tell that it's done in &lt;code&gt;php&lt;/code&gt;.  In fact all the &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt;s are &quot;clean&quot; and somewhat logical.  The benefit of having clean simple &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt;s is if we decide to change from PHP to &lt;acronym title=&quot;Active Server Pages&quot;&gt;ASP&lt;/acronym&gt; for example, we won't need to change our &lt;acronym title=&quot;Universal Resource Locator&quot;&gt;URL&lt;/acronym&gt;s.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Version numbers need dates</title>
   <link href="http://davedash.com/2006/06/28/version-numbers-need-dates/"/>
   <updated>2006-06-28T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/06/28/version-numbers-need-dates</id>
   <content type="html">&lt;p&gt;What is the point of a version number?  For the most part, it's just a &lt;a href=&quot;http://en.wikipedia.org/wiki/Milestone&quot;&gt;milestone&lt;/a&gt;.  The difference between version &lt;code&gt;2.3&lt;/code&gt; and &lt;code&gt;2.4&lt;/code&gt; of a software is a given feature-set.  Between &lt;code&gt;2.3&lt;/code&gt; and &lt;code&gt;2.5&lt;/code&gt; is an even larger feature-set that encompasses our previous feature-set.&lt;/p&gt;

&lt;p&gt;So if I tell you, I have version &lt;code&gt;0.9.6.2&lt;/code&gt; of svnX what does that tell you?  For most, absolutely nothing.  If I told you I was on &lt;a href=&quot;http://en.wikipedia.org/wiki/Interstate_35W&quot;&gt;&lt;acronym title=&quot;Interstate&quot;&gt;I&lt;/acronym&gt;-35W&lt;/a&gt; at marker &lt;a href=&quot;http://maps.yahoo.com/beta/index.php#maxp=location&amp;amp;q2=55420&amp;amp;q1=55408&amp;amp;mvt=m&amp;amp;trf=0&amp;amp;lon=-93.296215&amp;amp;lat=44.836182&amp;amp;mag=1&quot;&gt;7a&lt;/a&gt; you wouldn't have a clue either... unless you looked at the map.&lt;/p&gt;

&lt;p&gt;Version numbers tend to force us to look at &quot;maps.&quot;  If my &lt;code&gt;svn&lt;/code&gt; client acts up, I have to go to the website and see how old it is.  Generally this isn't a big deal.  But some sites don't publish &lt;em&gt;when&lt;/em&gt; they made updates.  Take &lt;a href=&quot;http://www.acquisitionx.com/releasenotes.php&quot;&gt;Acquisition&lt;/a&gt;.  It's great software, but if I told you I was still using 128.3, you would have no clue how out of date I was.&lt;/p&gt;

&lt;p&gt;On the otherhand if version numbers incorporated a date, we'd be set.  If I told you I was using &lt;code&gt;1.0.20050405&lt;/code&gt; of a piece of software and I was experiencing problems, you'd wonder why I hadn't upgraded to something newer.  If something newer didn't exist, you'd question if development has stopped.&lt;/p&gt;

&lt;p&gt;We can address versioning concerns by using this hybrid versioning.  The developer's own style of versioning (e.g. &lt;code&gt;1.0&lt;/code&gt;, &lt;code&gt;2.0&lt;/code&gt;, etc) can be combined with dates: &lt;code&gt;1.1.20060505&lt;/code&gt;.  Now we know this is a &lt;code&gt;1.1&lt;/code&gt; style release.  Generally that means, the developer feels the software is complete enough to consider it at least &lt;code&gt;1.0&lt;/code&gt;, but with some improvements beyond that release.  It tells the rest of the world, at a glance, that it was released in May of 2006.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ReviewsBy.Us bugfixes</title>
   <link href="http://davedash.com/2006/05/30/reviewsbyus-bugfixes/"/>
   <updated>2006-05-30T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/05/30/reviewsbyus-bugfixes</id>
   <content type="html">&lt;p&gt;A lot of bugs have popped up recently.&lt;/p&gt;

&lt;h3&gt;Logins&lt;/h3&gt;

&lt;p&gt;The logins weren't redirecting people to the correct place.  Unfortunately the login system still needs a lot of work.  I am probably going to rewrite it completely.  It doesn't consistantly remember where you are coming from or where you intend to go after logging in.  I'll be jotting down a clean system to log people in propperly.&lt;/p&gt;

&lt;h3&gt;Tags&lt;/h3&gt;

&lt;p&gt;Tags work a bit better.  They follow the flickr style of tagging, which is each word is a tag, unless surrounded in double quotes.  Previously they weren't producing a lot of empty tags.&lt;/p&gt;

&lt;h3&gt;Latitude and Longitude even more precise.&lt;/h3&gt;

&lt;p&gt;A small error in the database definitions resulted in lat/longitudes of restaurants that were greater than 100 (or rather &lt;code&gt;abs(x) &amp;gt; 100&lt;/code&gt; where &lt;code&gt;x&lt;/code&gt; is latitude or longitude were being truncated to &lt;code&gt;100&lt;/code&gt; or &lt;code&gt;-100&lt;/code&gt;.  This was easily fixed so things should look just right on the maps.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Google Analytics</title>
   <link href="http://davedash.com/2006/05/26/google-analytics/"/>
   <updated>2006-05-26T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/05/26/google-analytics</id>
   <content type="html">&lt;div class=&quot;photo right&quot; style=&quot;float: right;&quot;&gt;
&lt;img src=&quot;http://static.flickr.com/51/153678327_1af6ace0c6.jpg&quot; width=&quot;500&quot; height=&quot;223&quot; alt=&quot;Google Analytics Screenshot&quot; /&gt;
&lt;/div&gt;


&lt;p&gt;I've also jumped on the &lt;a href=&quot;http://www.google.com/analytics/&quot;&gt;Google Analytics&lt;/a&gt; bandwagon and added a lot of the sites in &quot;family.&quot;  If you're familiar with Urchin, it has a similar feel to it.  It almost feels a bit lighter feature-wise.  There's a few issues I will take with it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When they list links to your site (e.g. /login) they don't hyperlink it.&lt;/li&gt;
&lt;li&gt;I'd like to drill down to raw data.  I like to make my own correlations.  Heck, I want to drill down to see if I should filter someone from the list.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Other than that, I like the potential that this will offer me.  This combined with &lt;a href=&quot;http://google.com/webmasters/sitemaps/&quot;&gt;Google Sitemaps&lt;/a&gt; will provide powerful analysis of the site.  As it stands, &lt;a href=&quot;http://katiebonn.com/&quot;&gt;Katie&lt;/a&gt; and I should be eating at the &lt;a href=&quot;http://reviewsby.us/restaurant/cheesecake-factory&quot;&gt;Cheesecake Factory&lt;/a&gt; and &lt;a href=&quot;http://reviewsby.us/restaurant/bad-waitress&quot;&gt;non-chain restaurants&lt;/a&gt; as we seem to do well in the ranks and I need to write more &lt;a href=&quot;http://spindrop.us/2006/04/26/easy_yahoo_maps_and_georss_with_symfony&quot;&gt;about maps&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>More usable approach to adding restaurants</title>
   <link href="http://davedash.com/2006/05/25/more-usable-approach-to-adding-restaurants/"/>
   <updated>2006-05-25T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/05/25/more-usable-approach-to-adding-restaurants</id>
   <content type="html">&lt;p&gt;The &quot;lazy&quot; approach to usability is to just use a web site or application yourself and use &lt;a href=&quot;http://www.useit.com/papers/heuristic/heuristic_list.html&quot;&gt;usability heuristics&lt;/a&gt;.  This is what I do, and it's why I have a huge to-do list of things to fix on the site.  Lately to build out the site content, I've been going to a lot of restaurants not listed on &lt;a href=&quot;http://reviewsby.us/&quot;&gt;the site&lt;/a&gt;.  This means I have a multi-step process after I eat:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a new restaurant.&lt;/li&gt;
&lt;li&gt;Add a location.&lt;/li&gt;
&lt;li&gt;Add a review of the restaurant.&lt;/li&gt;
&lt;li&gt;Rate the restaurant&lt;/li&gt;
&lt;li&gt;Add all the menu items I ate.&lt;/li&gt;
&lt;li&gt;Tag the menu items.&lt;/li&gt;
&lt;li&gt;Write a review of the menu items.&lt;/li&gt;
&lt;li&gt;Rate the menu item.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;For everyday users, I don't expect 1 or 2 and only a few of 3-8, but 1 is a requisite and 2 is nice for maps and just being able to get information quickly.  I did want to streamline this process, so I made a combined form that does 1,2 and 3 all in one place.  That's just six steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a new restaurant.&lt;/li&gt;
&lt;li&gt;Rate the restaurant&lt;/li&gt;
&lt;li&gt;Add all the menu items I ate.&lt;/li&gt;
&lt;li&gt;Tag the menu items.&lt;/li&gt;
&lt;li&gt;Write a review of the menu items.&lt;/li&gt;
&lt;li&gt;Rate the menu item.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;For most users it makes sense, since most restaurants just have one location - or if they are adding a restaurant they are only thinking of a specific location.&lt;/p&gt;

&lt;p&gt;I also took the opportunity to do a check on restaurant names.  If you attempt to enter &lt;a href=&quot;http://reviewsby.us/restaurant/green-mill&quot;&gt;Green Mill&lt;/a&gt; twice, you'll be prompted that a restaurant with that name already exists.  It's not a very smart check, but it should serve it's purpose.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Comment Anonymously at ReviewsBy.Us</title>
   <link href="http://davedash.com/2006/05/18/comment-anonymously-at-reviewsbyus/"/>
   <updated>2006-05-18T00:00:00-07:00</updated>
   <id>http://davedash.com/2006/05/18/comment-anonymously-at-reviewsbyus</id>
   <content type="html">&lt;p&gt;I decided to overhaul the comment system on the &lt;a href=&quot;http://reviewsby.us/&quot;&gt;reviewsby.us&lt;/a&gt; site.  I implemented an &lt;acronym title=&quot;Asynchronous Java and XML&quot;&gt;AJAX&lt;/acronym&gt; form and allow anonymous comments.  Anonymous comments is a slippery slope, but reading &lt;a href=&quot;http://www.alistapart.com/articles/flywheelsandfriction&quot;&gt;about friction&lt;/a&gt; and &lt;a href=&quot;http://www.alistapart.com/articles/identitymatters/&quot;&gt;identity&lt;/a&gt; some things need to be taken into account.&lt;/p&gt;

&lt;p&gt;The site is new.  It's going to take a while before it generates a lot of traffic and therefore members and therefore comments.  But it would be nice to keep collecting information and make that collection as painless as possible.  Of course the potential for spam is high, but when/if that happens there are safeguards that can be put in place.  I imagine, until a decent membership base is established, the rules for who can and cannot post will probably change every now and again.&lt;/p&gt;
</content>
 </entry>
 

</feed>
