<?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/javascript/atom.xml" rel="self"/>
 <link href="http://davedash.com/tag/javascript"/>
 <updated>2010-08-29T14:12:50-07:00</updated>
 <id>http://davedash.com/</id>
 <author>
   <name>Dave Dash</name>
   <email>dd+atom1@davedash.com</email>
 </author>

 
 <entry>
   <title>Star Rating using YUI (and Django)</title>
   <link href="http://davedash.com/2008/03/04/star-rating-using-yui-and-django/"/>
   <updated>2008-03-04T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/03/04/star-rating-using-yui-and-django</id>
   <content type="html">&lt;p&gt;I have a very good star rater on &lt;a href=&quot;http://reviewsby.us/&quot;&gt;reviewsby.us&lt;/a&gt;, but it was written using
some sloppy prototype code.  I wanted to redo star raters in a well thought out
manner and I wanted to use &lt;a href=&quot;http://developer.yahoo.com/yui/&quot;&gt;YUI&lt;/a&gt;.  In this particular tutorial I will use
&lt;a href=&quot;http://djangoproject.com/&quot;&gt;Django&lt;/a&gt; although it is not a requirement.&lt;/p&gt;

&lt;p&gt;For some background information on star raters, see this
&lt;a href=&quot;http://developer.yahoo.com/ypatterns/pattern.php?pattern=ratinganobject&quot;&gt;Yahoo! Design Pattern&lt;/a&gt;.  Our pattern is more of a join star rater, similar
to what's found on Netflix: you see an average rating for a restaurant or dish
unless you yourself have rated it.&lt;/p&gt;

&lt;p&gt;This was a thought out design decision for our &lt;a href=&quot;http://reviewsby.us/&quot;&gt;reviewsby.us&lt;/a&gt; redesign.
Our site is primarily a personal utility that answers the question, &quot;What
dishes do I like at a particular restaurant?&quot;  If you haven't rated something
the website can only offer up an average and you can use that as a decision as
to whether you should eat something or not.&lt;/p&gt;

&lt;p&gt;If you have eaten something however, that average rating is irrelevant.  You
don't need fellow meal advisors to tell you that you liked Chicken Makhani, you
already know that for yourself.  Therefore we show only your rating unless you
haven't rated something.&lt;/p&gt;

&lt;h3&gt;Working backwards&lt;/h3&gt;

&lt;p&gt;I like to &quot;work backwards&quot; as it were.  Meaning, I like to just write the code
that I ultimately will use to output a star rater.  From there I will work on
the supporting code that is necessary.  I find by using this strategy, I can
keep my code fairly clean and organized.&lt;/p&gt;

&lt;h3&gt;The template&lt;/h3&gt;

&lt;p&gt;So ultimately I want this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{\% star 'mything' 3 4 '/path/to/script' %}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To show up as this:&lt;/p&gt;

&lt;div style=&quot;text-align:center&quot;&gt;
&lt;img src=&quot;http://spindrop.us/wp-content/uploads/2008/03/starrater.png&quot; alt=&quot;starrater.png&quot; border=&quot;0&quot; width=&quot;105&quot; height=&quot;31&quot; /&gt;
&lt;/div&gt;


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

&lt;p&gt;Unfortunately &lt;a href=&quot;http://www.djangoproject.com/documentation/templates/&quot;&gt;Django templates&lt;/a&gt; doesn't seem to have named attributes for &lt;a href=&quot;http://www.djangoproject.com/documentation/templates_python/&quot;&gt;template tags&lt;/a&gt;, so I'll need to explain my syntax:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;star&lt;/code&gt;: is the template tag which we define below&lt;/li&gt;
&lt;li&gt;&lt;code&gt;'mything'&lt;/code&gt;: is an id string we will use for this rater and its associated objects&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3&lt;/code&gt;: this is the second argument to star, it will be the users current rating, it can also be None&lt;/li&gt;
&lt;li&gt;&lt;code&gt;4.1&lt;/code&gt;: this is the third argument, it will be the average rating, it can also be None&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/path/to/script&lt;/code&gt;: is the form that will process our rating&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;The HTML we want&lt;/h3&gt;

&lt;p&gt;Another developer had a &lt;a href=&quot;http://www.unessa.net/en/hoyci/projects/yui-star-rating/&quot;&gt;good approach for handling star ratings&lt;/a&gt; and for handling Javascript in general.  Create an underlying Javascript-free system, and then let the Javascript make it pretty.  This is way to degrade gracefully.&lt;/p&gt;

&lt;p&gt;Ultimately, I had my own approach to this problem, I wanted much of the visual lifting to happen on the CSS layer.  So, we'll use the following code:&lt;/p&gt;

&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;html&quot;&gt;
&lt;span class=&quot;joint_star_rater&quot;&gt;
    &lt;form id=&quot;rater_restaurant&quot; method=&quot;post&quot; action=&quot;/restaurant/pizza-luce/rate/&quot;&gt;
        &lt;fieldset&gt;
            &lt;legend&gt;Rating&lt;/legend&gt;
            &lt;ul&gt;

        &lt;li style=&quot;width: 100px;&quot; title=&quot;5&quot; class=&quot;current meta&quot;&gt;Current Rating: 5&lt;/li&gt;


        &lt;li title=&quot;Poor&quot; class=&quot;star_1 star&quot;&gt;
            &lt;label for=&quot;restaurant_rating_1&quot;&gt;Poor&lt;/label&gt;
            &lt;input type=&quot;radio&quot; name=&quot;rating&quot; value=&quot;1&quot; id=&quot;restaurant_rating_1&quot;/&gt;
        &lt;/li&gt;

        &lt;li title=&quot;Fair&quot; class=&quot;star_2 star&quot;&gt;
            &lt;label for=&quot;restaurant_rating_2&quot;&gt;Fair&lt;/label&gt;
            &lt;input type=&quot;radio&quot; name=&quot;rating&quot; value=&quot;2&quot; id=&quot;restaurant_rating_2&quot;/&gt;
        &lt;/li&gt;

        &lt;li title=&quot;Good&quot; class=&quot;star_3 star&quot;&gt;
            &lt;label for=&quot;restaurant_rating_3&quot;&gt;Good&lt;/label&gt;
            &lt;input type=&quot;radio&quot; name=&quot;rating&quot; value=&quot;3&quot; id=&quot;restaurant_rating_3&quot;/&gt;
        &lt;/li&gt;

        &lt;li title=&quot;Very Good&quot; class=&quot;star_4 star&quot;&gt;
            &lt;label for=&quot;restaurant_rating_4&quot;&gt;Very Good&lt;/label&gt;
            &lt;input type=&quot;radio&quot; name=&quot;rating&quot; value=&quot;4&quot; id=&quot;restaurant_rating_4&quot;/&gt;
        &lt;/li&gt;

        &lt;li title=&quot;Excellent&quot; class=&quot;star_5 star&quot;&gt;
            &lt;label for=&quot;restaurant_rating_5&quot;&gt;Excellent&lt;/label&gt;
            &lt;input type=&quot;radio&quot; name=&quot;rating&quot; value=&quot;5&quot; id=&quot;restaurant_rating_5&quot;/&gt;
        &lt;/li&gt;

            &lt;/ul&gt;
        &lt;/fieldset&gt;
        &lt;input type=&quot;submit&quot; name=&quot;rate&quot; value=&quot;rate it&quot; class=&quot;submit&quot;/&gt;
    &lt;/form&gt;
&lt;/span&gt;

&lt;/textarea&gt;&lt;/p&gt;


&lt;p&gt;A couple things to note in our HTML.  Our unique string is &lt;code&gt;restaurant&lt;/code&gt;.  It's got an ID that is as unique as you want: &lt;code&gt;rater_restaurant&lt;/code&gt; where &lt;code&gt;restaurant&lt;/code&gt; was the first argument to our template tag.  We use &lt;code&gt;restaurant&lt;/code&gt; to create some other unique IDs as well.&lt;/p&gt;

&lt;p&gt;Also, this rating form makes a lot of sense semantically.  While this form in its current state is a far cry from some ajaxy goodness, it makes clear sense as to what is going on.&lt;/p&gt;

&lt;h3&gt;The template tag&lt;/h3&gt;

&lt;p&gt;Well we know what we want from the HTML side, so let's start coding our &lt;code&gt;star&lt;/code&gt; tag:&lt;/p&gt;

&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
@register.simple_tag
def star(id_string, current, average, path, spanfree=False):
    meta = None
    if current != None:
        meta = &quot;&quot;&quot;
        &lt;li class=&quot;current meta&quot; title=&quot;%d&quot; style=&quot;width:%dpx&quot;&gt;Current Rating: %d&lt;/li&gt;
        &quot;&quot;&quot; % (int(current), int(current)*20, int(current))
    else:
        meta = &quot;&quot;&quot;
        &lt;li class=&quot;average meta&quot; title=&quot;%.1f&quot; style=&quot;width:%dpx&quot;&gt;Average Rating: %.1f&lt;/li&gt;
        &quot;&quot;&quot; % (average, average*20,average)

    stars   = ''
    ratings = ['Poor', 'Fair', 'Good', 'Very Good', 'Excellent']

    for i in range(1,6):
        stars = stars + &quot;&quot;&quot;
        &lt;li class=&quot;star_%d star&quot; title=&quot;%s&quot;&gt;
            &lt;label for=&quot;%s_rating_%d&quot;&gt;%s&lt;/label&gt;
            &lt;input id=&quot;%s_rating_%d&quot; type=&quot;radio&quot; value=&quot;%d&quot; name=&quot;rating&quot;/&gt;
        &lt;/li&gt;
        &quot;&quot;&quot; % (i, ratings[i-1],id_string, i, ratings[i-1], id_string, i, i)
    html = &quot;&quot;&quot;
    &lt;form action=&quot;%s&quot; method=&quot;post&quot; id=&quot;rater_%s&quot;&gt;
        &lt;fieldset&gt;
            &lt;legend&gt;Rating&lt;/legend&gt;
            &lt;ul&gt;
            %s
            %s
            &lt;/ul&gt;
        &lt;/fieldset&gt;
        &lt;input type=&quot;submit&quot; class=&quot;submit&quot; value=&quot;rate it&quot; name=&quot;rate&quot;/&gt;
    &lt;/form&gt;
    &quot;&quot;&quot; % (path, id_string, meta,stars)
    if spanfree:
        return html
    else:
        return &quot;&quot;&quot;&lt;span class=&quot;joint_star_rater&quot;&gt;%s&lt;/span&gt;&quot;&quot;&quot; % html
    return html

&lt;/textarea&gt;&lt;/p&gt;


&lt;h3&gt;The CSS&lt;/h3&gt;

&lt;p&gt;A lot of work will happen via CSS.  The CSS will remove quite a bit of the textual data that can be interpreted graphically with stars.&lt;/p&gt;

&lt;p&gt;The strategy we use is to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fix the &lt;code&gt;UL&lt;/code&gt; at a certain width with a background of grey stars&lt;/li&gt;
&lt;li&gt;decorate the &lt;code&gt;LI.average&lt;/code&gt; and &lt;code&gt;LI.current&lt;/code&gt; with repeating stars (blue and orange respectively) with a  &lt;code&gt;z-index&lt;/code&gt; of &lt;code&gt;1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;decorate the &lt;code&gt;LI.average:hover&lt;/code&gt; and &lt;code&gt;LI.current:hover&lt;/code&gt; with a transparent background&lt;/li&gt;
&lt;li&gt;decorate &lt;code&gt;LI:hover input&lt;/code&gt; as a colored in star and a &lt;code&gt;z-index&lt;/code&gt; of &lt;code&gt;2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This might not make sense now, until you see the CSS in full action.  Also for the stars we'll use a sprite of 3 stars.  A grey defunct star as the default background, a blue star if it's the average rating for an item and an orange star if it's what the user wants.&lt;/p&gt;

&lt;p&gt;I use the following sprite:&lt;/p&gt;

&lt;div style=&quot;background: #000;text-align:center; padding:1em&quot;&gt;
&lt;img src=&quot;http://spindrop.us/wp-content/uploads/2008/03/stars.png&quot; alt=&quot;stars.png&quot; border=&quot;0&quot; width=&quot;20&quot; height=&quot;60&quot; /&gt;
&lt;/div&gt;


&lt;p&gt;The following CSS will do some magic:&lt;/p&gt;

&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;css&quot;&gt;
.joint_star_rater {display:inline-block;}
.joint_star_rater ul{width:100px;position:relative;height:20px;background:url(../images/icons/stars.png) repeat-x 0 0}
.joint_star_rater li.meta{position:absolute;text-indent:-9999px;display:block;z-index:1;}
.joint_star_rater ul:hover li.meta{display:none;}
.joint_star_rater li.current{background:url(../images/icons/stars.png) repeat-x 0 -40px}
.joint_star_rater li.average{background:url(../images/icons/stars.png) repeat-x 0 -20px}
.joint_star_rater li{height:20px;width:20px;position:absolute;text-indent:-9999px;z-index:3;}
.joint_star_rater li.star_2{left:20px;}
.joint_star_rater li.star_3{left:40px}
.joint_star_rater li.star_4{left:60px}
.joint_star_rater li.star_5{left:80px}
.joint_star_rater li.star_1:hover{width:20px}
.joint_star_rater li.star_2:hover{width:40px}
.joint_star_rater li.star_3:hover{width:60px}
.joint_star_rater li.star_4:hover{width:80px}
.joint_star_rater li.star_5:hover{width:100px}
.joint_star_rater li.star:hover{background:url(../images/icons/stars.png) repeat-x 0 -40px;z-index:2;left:0;}
.joint_star_rater input.submit{display:none;}
&lt;/textarea&gt;&lt;/p&gt;


&lt;p&gt;The &lt;code&gt;inline-block&lt;/code&gt; value for &lt;code&gt;display&lt;/code&gt; is not supported very well.  I recently switched to Firefox 3 Beta and it renders as expected.  Firefox 2 has problems with it.  I may revise the CSS later to accommodate it.&lt;/p&gt;

&lt;h3&gt;The Javascript&lt;/h3&gt;

&lt;p&gt;The fundamental drawback to the design here, is that it really only works well with the Javascript on.  In fact, with the CSS on and Javascript off, this code will not work very well for the end user.  This too will be revised in the future.&lt;/p&gt;

&lt;p&gt;Our Javascript needs to do something very simple:
* extract the star value you clicked on
* send it to the server
* redraw the stars&lt;/p&gt;

&lt;p&gt;It's a very simple operation, but I honestly think other libraries have an advantage to YUI in this regard.&lt;sup id=&quot;#fnr_1&quot;&gt;&lt;a href=&quot;#fn_1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;  Here's some unobtrusive code I came up with:&lt;/p&gt;

&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;js&quot;&gt;
var MA = {}; // MA namespace
MA.e = YAHOO.util.Event;
MA.d = YAHOO.util.Dom;
MA.c = YAHOO.util.Connect;

MA.star_rater = function() {
    var e = YAHOO.util.Event;
    var d = YAHOO.util.Dom;

    return {
        init: function() {
            e.onDOMReady(this.setup,this, true)
        },

        setup: function() {
            e.on(d.get('doc4'),'click',this.handleClick,this,true);
        },

        handleClick: function(ev) {
            var target = e.getTarget(ev);
            if (d.hasClass(target, 'star')
            &amp;&amp; d.hasClass(target.parentNode.parentNode.parentNode.parentNode, 'joint_star_rater')) {
                this.rate(target);
            }
        },

        rate: function(el) {
            if (MA.is_authenticated('Please sign in before rating =)')) {

                root   = el.parentNode.parentNode.parentNode.parentNode;
                action      = el.parentNode.parentNode.parentNode.action;
                input       = MA.d.getFirstChildBy(el, function(d) {return (d.tagName == 'input'||d.tagName=='INPUT')});
                this.value  = input.value;
                postdata    = &quot;value=&quot;+this.value;

                handleSuccess = function(o) { root.innerHTML = o.responseText }
                callback = {
                    success:handleSuccess,
                }


                var request = MA.c.asyncRequest('POST', action, callback, postdata);
                // construct a connection object to this and use it to make a post
                // retrieve the post and then replace it with the original span
            }
        },

    }
}();

MA.star_rater.init();
&lt;/textarea&gt;&lt;/p&gt;


&lt;p&gt;Note: I intentionally left out irrelevant pieces of code, like the function definition of &lt;code&gt;MA.is_authenticated()&lt;/code&gt;, this code isn't meant for cutting and pasting, it's meant for cutting-pasting and then some careful editing.&lt;/p&gt;

&lt;h3&gt;The callback view&lt;/h3&gt;

&lt;p&gt;The callback script is what you specify when you call &lt;code&gt;{\% star ... %}&lt;/code&gt;.  The view I use is as follows:&lt;/p&gt;

&lt;p&gt;&lt;textarea name=&quot;code&quot; class=&quot;python&quot;&gt;
@login_required
def rate(request, slug):
    MyObject = get_my_object()
    value    = request['value']

    MyObject,rate(value);
    return render_to_response(&quot;rating.html&quot;, locals(), context_instance=RequestContext(request))

&lt;/textarea&gt;&lt;/p&gt;


&lt;p&gt;That code is oversimplified... you have to write your own logic as it applies to our site.  The &lt;code&gt;rating.html&lt;/code&gt; is simply the call to your star tag:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{\% load tags %}
{\% star 'mything' restaurant.current_rating restaurant.average_rating restaurant.get_rating_url 1 %}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note the &lt;code&gt;1&lt;/code&gt; at the end.  It's a flag to turn off the outer &lt;code&gt;span&lt;/code&gt; so we can just insert the guts back into the original &lt;code&gt;span&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;Final Thoughts&lt;/h3&gt;

&lt;p&gt;The star-rater is really a large problem that's hard to tackle in one sitting and quite frankly is not documented well anywhere.  The code I've provided is a shadow of the real code I'll be using, but hopefully it's enough to get you started.&lt;/p&gt;

&lt;p&gt;I definitely will update my production code to solve a few outstanding issues, as I mentioned above.  I'll try to update this tutorial at the same time.  If there are questions about the examples given, feel free to ask and I'll attempt to answer.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
&lt;ol&gt;
&lt;li id=&quot;fn_1&quot;&gt;YUI has the &lt;code&gt;Selector&lt;/code&gt; and that might alleviate some problems, but jQuery has very nice selection capabilities.  In this future version I keep promising, I'll use the YUI &lt;code&gt;Selector&lt;/code&gt; &lt;a href=&quot;#fnr_1&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>YUI Autocomplete the easy way</title>
   <link href="http://davedash.com/2008/01/27/yui-autocomplete-the-easy-way/"/>
   <updated>2008-01-27T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/01/27/yui-autocomplete-the-easy-way</id>
   <content type="html">&lt;p&gt;[tags]yui, autocomplete, javascript, jquery, symfony[/tags]&lt;/p&gt;

&lt;p&gt;I'm redoing the UI for &lt;a href=&quot;http://reviewsby.us/&quot;&gt;reviewsby.us&lt;/a&gt; and for the Javascript library I am standardizing on is &lt;a href=&quot;http://developer.yahoo.com/yui/&quot;&gt;YUI&lt;/a&gt;.  The trick with &lt;a href=&quot;http://developer.yahoo.com/yui/&quot;&gt;YUI&lt;/a&gt; is that it's very verbose and very configurable.&lt;/p&gt;

&lt;p&gt;Unfortunately to do simple things you have to write quite a lot.  Which, coming from a jQuery background, is not what I'm used to.  Yahoo provides a lot of useful examples for Auto Complete, I'll provide you with another (built in &lt;a href=&quot;http://symfony-project.com/&quot;&gt;symfony&lt;/a&gt;, but anything in any server-side language will work).  You'll need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A data source&lt;/li&gt;
&lt;li&gt;Some YUI&lt;/li&gt;
&lt;li&gt;Some javascript of your own&lt;/li&gt;
&lt;li&gt;And some HTML&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;We're building a tool to grab random items from our database and put them into our Autocomplete field.  We also want to capture and id of these items and set them in our form.&lt;/p&gt;

&lt;p&gt;Here we go...&lt;/p&gt;

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

&lt;h3&gt;Data Source&lt;/h3&gt;

&lt;p&gt;YUI gives you a lot of options with data sources.  In many cases a remote script that returns JSON will be best.  JSON is nice, compact, human debuggable and machine-readable.&lt;/p&gt;

&lt;p&gt;We can make a &lt;code&gt;searchJSON&lt;/code&gt; method that simply takes your database results and wraps them in to a formatted array and then using PHP's &lt;code&gt;json_encode&lt;/code&gt; we can return a nice JSON object.&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;php&quot;&gt;
    public static function searchJSON($phrase, $exact = false, $offset = 0, $max = 10)
    {
        $rs = self::doSearch($phrase, $exact, $offset, $max);

        // Manage the results
        $restaurants = array();
        while ($rs-&gt;next())
        {
          $r                           = self::retrieveByPK($rs-&gt;getInt(1));
            $objs[] = array('Id'=&gt;$rs-&gt;getInt(1), 'Title'=&gt;$r-&gt;getName());
        }

    return json_encode(array('ResultSet' =&gt; array(&quot;Result&quot; =&gt; $objs)));
    }
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;ResultSet&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt; keys are important as we'll see later.&lt;/p&gt;

&lt;p&gt;We can serve this JSON method very easily in symfony like so:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;php&quot;&gt;
  public function executeAjaxList()
  {
    $q    = $this-&gt;getRequestParameter('query');
    $objs = ObjPeer::searchJSON($q);
    return $this-&gt;renderText($objs);
  }
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;Note that we use &lt;code&gt;renderText&lt;/code&gt; rather than a separate &lt;code&gt;ajaxListSuccess.php&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;YUI&lt;/h3&gt;

&lt;p&gt;There's some &lt;a href=&quot;http://developer.yahoo.com/yui/&quot;&gt;YUI&lt;/a&gt; code that you need.  It's described well in the &lt;a href=&quot;http://developer.yahoo.com/yui/autocomplete/&quot;&gt;Autocomplete documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Add the following to your page:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://yui.yahooapis.com/2.4.1/build/yahoo-dom-event/yahoo-dom-event.js&quot; type=&quot;text/javascript
http://yui.yahooapis.com/2.4.1/build/connection/connection-min.js type=&quot;text/javascript
http://yui.yahooapis.com/2.4.1/build/autocomplete/autocomplete-min.js
http://yui.yahooapis.com/2.4.1/build/autocomplete/assets/skins/sam/autocomplete.css
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These are the bare YUI requirements to get Autocomplete working.&lt;/p&gt;

&lt;h3&gt;Javascript&lt;/h3&gt;

&lt;p&gt;There's a good deal of Javascript that you'll need to provide on your own.  Here's what I wrote:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;javascript&quot;&gt;
    var MA = {};
    MA.autocomplete = function()
    {
      var e = YAHOO.util.Event;
      var w = YAHOO.widget;
  
      return {
        init: function()
        {
           e.onAvailable(&quot;myInput&quot;, this.fnHandler);
        },
        fnHandler: function()
        {
          var rDS = new w.DS_XHR(&quot;/ajax/object/list&quot;, [&quot;ResultSet.Result&quot;,&quot;Title&quot;]);

          rDS.maxCacheEntries    = 60; 
          rDS.queryMatchContains = true;

          var rAC = new w.AutoComplete(&quot;myInput&quot;,&quot;myACContainer&quot;, rDS); 

          rAC.formatResult = function(item, query) 
          {
            return item[1].Title;
          };
      
          rAC.forceSelection           = true; 
          rAC.allowBrowserAutocomplete = false; 
      
          rAC.itemSelectEvent.subscribe(
            function(sType, aArgs) 
            { 
              var data = aArgs[2];
              document.getElementById(&quot;object_id&quot;).value = aArgs[2][1]['Id'];
            }
          ); 
        },
    
      }
    }();

    MA.autocomplete.init();

&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;MA&lt;/code&gt; is my own private namespace.  &lt;code&gt;/ajax/object/list&lt;/code&gt; is the url of our data source we defined earlier.  &lt;code&gt;myInput&lt;/code&gt;, &lt;code&gt;myACContainer&lt;/code&gt; and &lt;code&gt;object_id&lt;/code&gt; are all IDs of elements in our DOM which we'll look at next.&lt;/p&gt;

&lt;h3&gt;HTML&lt;/h3&gt;

&lt;p&gt;Okay I went through this backwards, now we have the HTML.&lt;/p&gt;

&lt;p&gt;This is all you need:&lt;/p&gt;

&lt;div&gt;
&lt;textarea name=&quot;code&quot; class=&quot;html&quot;&gt;
    &lt;div id=&quot;myAutoComplete&quot;&gt;
      &lt;?php echo input_tag('myInput',null,'class=text') ?&gt;
      &lt;div id=&quot;myACContainer&quot;&gt;&lt;/div&gt;
      &lt;?php echo input_hidden_tag('object_id') ?&gt;
    &lt;/div&gt;
&lt;/textarea&gt;
&lt;/div&gt;


&lt;h3&gt;The End&lt;/h3&gt;

&lt;p&gt;That's it.  It might seem like a lot, but &lt;a href=&quot;http://developer.yahoo.com/yui/&quot;&gt;YUI&lt;/a&gt; offers a tested working solution that works and is very customizable.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ddJQueryCalendarPlugin plugin for symfony released</title>
   <link href="http://davedash.com/2007/09/20/ddjquerycalendarplugin-plugin-for-symfony-released/"/>
   <updated>2007-09-20T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/09/20/ddjquerycalendarplugin-plugin-for-symfony-released</id>
   <content type="html">&lt;p&gt;[tags]JQuery, jq, javascript, js, JQuery Calendar, calendar, symfony, plugin[/tags]&lt;/p&gt;

&lt;p&gt;I released a new symfony plugin today for the &lt;a href=&quot;http://marcgrabanski.com/code/jquery-calendar/&quot;&gt;jQuery Calendar&lt;/a&gt; available &lt;a href=&quot;http://svn.symfony-project.com/plugins/ddJQueryCalendar&quot;&gt;via svn&lt;/a&gt;.  Feel free to read about it on &lt;a href=&quot;http://trac.symfony-project.com/trac/wiki/ddJQueryCalendar&quot;&gt;trac&lt;/a&gt;.  This adds a clever calendar widget that can trigger events.  Very handy for viewing an events calendar.&lt;/p&gt;

&lt;p&gt;I'll publish a link to this plugin in action in the following weeks.  Enjoy.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>jQuery shortcut functions and jQuery plugins</title>
   <link href="http://davedash.com/2007/09/15/jquery-shortcut-functions-and-jquery-plugins/"/>
   <updated>2007-09-15T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/09/15/jquery-shortcut-functions-and-jquery-plugins</id>
   <content type="html">&lt;p&gt;[tags]js, javascript, readability, yui, jquery, shortcuts[/tags]&lt;/p&gt;

&lt;p&gt;One of the the things that's kept me away from the YUI javascript libraries is longhand.  Or rather, the appeal to jQuery (and Prototype) was the almight $ shorthand.&lt;/p&gt;

&lt;p&gt;Of course there are times when it pays to write in long hand.  Marc Grabanski has written a fantastic &lt;a href=&quot;http://marcgrabanski.com/code/jquery-calendar/&quot;&gt;calendar plugin&lt;/a&gt; which uses a lot of jQuery shorthand.  &lt;code&gt;$()&lt;/code&gt;, &lt;code&gt;$.extend&lt;/code&gt; and whatnot are great for quick code, but disaster when you need to be in maximum compatibility mode.  For example, use jQuery with some other libraries and you can get disaster.  It's better to opt for the long-hand &lt;code&gt;jQuery&lt;/code&gt; and &lt;code&gt;jQuery.extend&lt;/code&gt; methods.  After some search and replaces, I may have gotten things right, but I think I need to talk to Marc Grabanski and make sure the changes I made make sense.&lt;/p&gt;

&lt;p&gt;So remember, long hand is great when other developers are using stuff and namespace conflicts are afoot ;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Equal height columns with jQuery</title>
   <link href="http://davedash.com/2007/05/22/equal-height-columns-with-jquery/"/>
   <updated>2007-05-22T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/05/22/equal-height-columns-with-jquery</id>
   <content type="html">&lt;p&gt;[tags]css, jQuery, layout, javascript, equal, columns, equal columns[/tags]&lt;/p&gt;

&lt;p&gt;I've seen a few examples of how to equalize column heights using javascript, and none of them seem appealing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tomdeater.com/jquery/equalize_columns/&quot;&gt;jquery.equalizecols.js&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;This required a few other libraries, and I wanted more flexibility (e.g. where the column should grow in order to equalize)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.projectseven.com/tutorials/css/pvii_columns/index.htm&quot;&gt;Project 7&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;The Project 7 approach was the most interesting, but the code seemed a bit messy and not so open source friendly (even thought it might have been).  It would let you specify which element was to grow inside a column.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.html.it/articoli/nifty/index.html&quot;&gt;Nifty Corners&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;I had trouble with the syntax, but I liked how it just created a new element out of thin air...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;So I wrote my own:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$(&quot;#col1, #col2&quot;).equalizeCols();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;will equalize the columns as expected&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$(&quot;#col1, #col2&quot;).equalizeCols(&quot;p,p&quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;will equalize the columns and add the extra space after the &lt;code&gt;p&lt;/code&gt; tag in &lt;code&gt;#col1&lt;/code&gt; or &lt;code&gt;#col2&lt;/code&gt; (whichever is shorter).&lt;/p&gt;

&lt;p&gt;Here's our function:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;js&quot;&gt;

(function($) {
  $.fn.equalizeCols = function(children){
    var child = Array(0);
    if (children) child = children.split(&quot;,&quot;);
    var maxH = 0;
    this.each(
      function(i) 
      {
        if (this.offsetHeight&gt;maxH) maxH = this.offsetHeight;
      }
    ).css(&quot;height&quot;, &quot;auto&quot;).each(
      function(i)
      {
        var gap = maxH-this.offsetHeight;
        if (gap &gt; 0)
        {
          t = document.createElement('div');
          $(t).attr(&quot;class&quot;,&quot;fill&quot;).css(&quot;height&quot;,gap+&quot;px&quot;);
          if (child.length &gt; i)
          {
            $(this).find(child[i]).children(':last-child').after(t);
          } 
          else 
          {
            $(this).children(':last-child').after(t);
          }
        }
      }  
    );
    
  }
})(jQuery);

&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;This requires jQuery of course, and it hasn't been tested much.&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>How to make Prototype Window Class as easy as Lightbox Gone Wild</title>
   <link href="http://davedash.com/2006/11/13/how-to-make-prototype-window-class-as-easy-as-lightbox-gone-wild/"/>
   <updated>2006-11-13T00:00:00-08:00</updated>
   <id>http://davedash.com/2006/11/13/how-to-make-prototype-window-class-as-easy-as-lightbox-gone-wild</id>
   <content type="html">&lt;p&gt;I like the way that &lt;a href=&quot;http://particletree.com/features/lightbox-gone-wild/&quot; title=&quot;Lightbox Gone Wild&quot;&gt;Lightbox Gone Wild&lt;/a&gt; will automatically pickup any links with the &lt;code&gt;class=lbOn&lt;/code&gt;, but I wanted to use (at some point) &lt;a href=&quot;http://prototype-window.xilinus.com/&quot; title=&quot;Prototype Window Class&quot;&gt;Prototype Window Class&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;Luckily &lt;a href=&quot;http://prototype-window.xilinus.com/&quot; title=&quot;Prototype Window Class&quot;&gt;PWC&lt;/a&gt; is built on Prototype which means we've already loaded a helpful library.&lt;/p&gt;

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

&lt;p&gt;In order to take all &lt;code&gt;class=lbOn&lt;/code&gt; objects and run them through &lt;a href=&quot;http://prototype-window.xilinus.com/&quot; title=&quot;Prototype Window Class&quot;&gt;PWC&lt;/a&gt; we just write a simple loop and iterate.&lt;/p&gt;

&lt;p&gt;So here's the low-down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download &lt;a href=&quot;http://prototype-window.xilinus.com/&quot; title=&quot;Prototype Window Class&quot;&gt;PWC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Copy window.js&lt;/li&gt;
&lt;li&gt;Use the included prototype &amp;amp; script.aculo.us if you don't already include it in your page&lt;/li&gt;
&lt;li&gt;copy any themes you wish to use.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;In your page add this bit of JavaScript:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;js&quot;&gt;
    var mylb = Class.create();
    
    mylb.prototype = {
        initialize: function(ctrl) {
            this.content = ctrl.href;
            Event.observe(ctrl, 'click', this.activate.bindAsEventListener(this), false);
            ctrl.onclick = function(){return false;};
            },
    
            // Turn everything on - mainly the IE fixes
            activate: function(){
                var win = new Window('window_id', {className: &quot;alphacube&quot;,title: &quot;Tour&quot;, url: this.content, width:700, height:500});
                win.setDestroyOnClose();
                win.showCenter(true);
            }
        }

        lbox = document.getElementsByClassName('lbOn');
        for(i = 0; i &lt; lbox.length; i++) {
            valid = new mylb(lbox[i]);
        }
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;So, this code simply looks for all the anchor tags with &lt;code&gt;class=lbOn&lt;/code&gt; and then  creates a new &lt;code&gt;mylb&lt;/code&gt; instance for each anchor.  The end.&lt;/p&gt;
</content>
 </entry>
 

</feed>
