<?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/yui/atom.xml" rel="self"/>
 <link href="http://davedash.com/tag/yui"/>
 <updated>2012-01-17T21:54:19-08: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;!--more--&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>Building a triangle toggler in YUI</title>
   <link href="http://davedash.com/2008/02/25/building-a-triangle-toggler-in-yui/"/>
   <updated>2008-02-25T00:00:00-08:00</updated>
   <id>http://davedash.com/2008/02/25/building-a-triangle-toggler-in-yui</id>
   <content type="html">&lt;p&gt;If someone knows the more common name for triangle-toggle menu's similar to &lt;a href=&quot;http://developer.yahoo.com/yui/examples/treeview/menu_style.html&quot;&gt;this&lt;/a&gt;.  Let me know.&lt;/p&gt;

&lt;p&gt;There is a widget where an element toggles the display of a secondary set of elements.  The toggle shows an arrow pointing down or right depending on the visibility of the elements.  I wanted to build that in YUI.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;The problem is two-fold:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build a triangle that toggles from right to down.&lt;/li&gt;
&lt;li&gt;Show and hide content.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;However, with some clever CSS we can do this all in a single class change on an element.&lt;/p&gt;

&lt;h3&gt;Build that triangle&lt;/h3&gt;

&lt;p&gt;There's a number of ways to show or hide this triangle.  Because it is flexible, I'm going to opt for using a background image.  Also to save on HTTP requests, I'll use a sprite-d image.  This may get merged with other icons on the system.&lt;/p&gt;

&lt;p&gt;The particular site I'm working on uses a black background with white text, therefore a white triangle toggle seems appropriate.&lt;/p&gt;

&lt;div style=&quot;background:black;text-align:center; padding:1em&quot;&gt;
&lt;img src=&quot;http://spindrop.us/wp-content/uploads/2008/02/sprite.png&quot; alt=&quot;sprite.png&quot; border=&quot;0&quot; width=&quot;11&quot; height=&quot;29&quot; /&gt;
&lt;/div&gt;


&lt;p&gt;This is what I use.  I leave a little space, because the background will only clip horizontally based on the size of the element.&lt;/p&gt;

&lt;h3&gt;Add the HTML/CSS&lt;/h3&gt;

&lt;p&gt;The following HTML:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;html&quot;&gt;
&lt;div id=&quot;area&quot; class=&quot;off&quot;&gt;
  &lt;h3&gt;&lt;span class=&quot;toggle&quot;&gt;Toggle Me&lt;/span&gt;&lt;/h3&gt;
  &lt;ul class=&quot;hide_me&quot;&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;and the following CSS:&lt;/p&gt;

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

.toggle {
    background: url(../images/icons/sprite.png) no-repeat 0px -14px;
    padding: 0 0 0 18px;
}

.off .hide_me {
    display: none;
}

.on .toggle {
    background-position: 0 9px;
}

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


&lt;p&gt;Provide the two states we require for the triangle.  If you are new to sprites, rather than changing the background image entirely we just shift the background image up or down appropriately to show a new background.&lt;/p&gt;

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

&lt;p&gt;The javascript is rather simple, but we put in some magical tricks here and there.&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;js&quot;&gt;
var MA = {}
MA.toggler = 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, 'toggle')) {
                var toggle = target.parentNode.parentNode;
                this.toggle(toggle);
            }
        },
        toggle: function(element) {
            var on  = &quot;on&quot;;
            var off = &quot;off&quot;;
            if (d.hasClass(element, on)){
                d.removeClass(element, on);
                d.addClass(element, off);
            } else {
                d.removeClass(element, off);
                d.addClass(element, on);
            }
        }
    }
}();

MA.toggler.init();
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;If you're unfamiliar with this style of Javascript, here's what's going on.  Everything is done in the &lt;code&gt;MA&lt;/code&gt; namespace as to not conflict with other javascript.&lt;/p&gt;

&lt;p&gt;The toggler is fairly generic and expects a similar HTML structure for &lt;em&gt;any&lt;/em&gt; toggle-able element.  That means this code only needs to be written once, and anytime we use the &lt;code&gt;toggle&lt;/code&gt; class, toggling in this fashion will occur.&lt;/p&gt;

&lt;p&gt;We only run the &lt;code&gt;init&lt;/code&gt; function.  &lt;code&gt;init&lt;/code&gt; says when the &lt;code&gt;DOM&lt;/code&gt; is available then run the &lt;code&gt;setup&lt;/code&gt; function.  &lt;code&gt;setup&lt;/code&gt; adds an event handler to &lt;code&gt;doc4&lt;/code&gt;.  &lt;code&gt;doc4&lt;/code&gt; just happens to be the id we use on our &lt;code&gt;body&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;Note that we're listening for clicks everywhere.  This means we have to define only one event handler, regardless of how many toggle-able items there are.  The event handler checks to make sure we clicked on a relevant element and then applies the &lt;code&gt;toggle&lt;/code&gt; function to the grandparent element (switching the class from &lt;code&gt;off&lt;/code&gt; to &lt;code&gt;on&lt;/code&gt; as appropriate).&lt;/p&gt;

&lt;p&gt;Note that this style of event handling means you need to carefully apply your class names.  Also note, that this code could be optimized a little bit more, I haven't put this code into production, and therefore haven't optimized it for the YUI compressor.&lt;/p&gt;

&lt;p&gt;Try this out if you want, I'm sure it can be trimmed down overtime.  If you have trouble with it, let me know.&lt;/p&gt;

&lt;p&gt;-d&lt;/p&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;!--more--&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>Table based layouts?  In this day in age?  Really?  How about grids?</title>
   <link href="http://davedash.com/2007/10/05/table-based-layouts-in-this-day-in-age-really-how-about-grids/"/>
   <updated>2007-10-05T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/10/05/table-based-layouts-in-this-day-in-age-really-how-about-grids</id>
   <content type="html">&lt;p&gt;[tags]css, yui, grids, table, layout[/tags]&lt;/p&gt;

&lt;p&gt;I think there are three kinds of people:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;People who learned tables for layouts and went to CSS+&lt;code&gt;div&lt;/code&gt;s.&lt;/li&gt;
&lt;li&gt;People who learned tables for layouts and never needed to learn CSS+&lt;code&gt;div&lt;/code&gt;s (or insisted that this was way too complicated)&lt;/li&gt;
&lt;li&gt;People who never learned tables.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;I would argue in some ways the second class of people are right, tables are a lot easier.  Until you run into issues... and until you need to maintain your template code.&lt;/p&gt;

&lt;p&gt;Luckily there's grids.  Grids are easier than tables and easy to maintain and look at.  You can achieve just about anything with &lt;a href=&quot;http://developer.yahoo.com/yui/grids/&quot;&gt;grids&lt;/a&gt;.&lt;/p&gt;

&lt;!--next page--&gt;


&lt;!--more--&gt;


&lt;p&gt;Personally I like using &lt;a href=&quot;http://developer.yahoo.com/yui/&quot;&gt;Yahoo's YUI&lt;/a&gt; to get grid support.  It's a CSS framework in the same way that &lt;a href=&quot;http://jquery.com&quot;&gt;jQuery&lt;/a&gt; is a javascript framework or that &lt;a href=&quot;http://symfony-project.com/&quot;&gt;symfony&lt;/a&gt; is a PHP5 framework.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://developer.yahoo.com/yui/&quot;&gt;YUI&lt;/a&gt; will normalize all your elements and give you a standard way to change the size of text and elements and give you &lt;a href=&quot;http://developer.yahoo.com/yui/grids/&quot;&gt;grids&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So it helps to think of your layout in terms of grids... or columns.  &lt;a href=&quot;http://developer.yahoo.com/yui/grids/&quot;&gt;YUI grids&lt;/a&gt; supports some common combinations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.yui-g&lt;/code&gt; - 2 equal size containers (nest to get 4).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.yui-gb&lt;/code&gt; - 3 equal size containers&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.yui-gc&lt;/code&gt; - 2/3 - 1/3&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.yui-gd&lt;/code&gt; - 1/3 - 2/3&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.yui-ge&lt;/code&gt; - 3/4 - 1/4&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.yui-gf&lt;/code&gt; - 1/4 - 3/4&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Granted, this doesn't cover every scenario, but it's a start, and it's easy to build off of to create your own special sizes.&lt;/p&gt;

&lt;p&gt;So to create some magical columns you do the following:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;html&quot;&gt;
&lt;div class=&quot;yui-g&quot;&gt;
  &lt;div class=&quot;yui-u first&quot;&gt;&lt;/div&gt;
  &lt;div class=&quot;yui-u&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;yui-g&lt;/code&gt; can be substituted for any of the above classes.  &lt;code&gt;yui-u&lt;/code&gt; is your columns or grid cells.  &lt;code&gt;first&lt;/code&gt; indicates the first column since &lt;code&gt;:first&lt;/code&gt; isn't understood by some popular browsers.&lt;/p&gt;

&lt;p&gt;Now you know grids.  It's less complicated than the tabular equivalent:&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;html&quot;&gt;
&lt;table class=&quot;layout&quot;&gt;
  &lt;tr class=&quot;first_row&quot;&gt;
    &lt;td class=&quot;col1&quot;&gt;&lt;/td&gt;
    &lt;td class=&quot;col2&quot;&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;With the framework in place, it's a lot easier to quickly adjust your layouts, and the readability is huge especially as your layouts grow.&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>resetting CSS list items</title>
   <link href="http://davedash.com/2007/09/01/resetting-css-list-items/"/>
   <updated>2007-09-01T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/09/01/resetting-css-list-items</id>
   <content type="html">&lt;p&gt;[tags]css, symfony, blueprint, yui[/tags]&lt;/p&gt;

&lt;p&gt;Call me a purist, but I really believe that Blueprint should go the extra step as YUI (note: I'm a YUI CSS user dabbling in Blueprint) does and reset list items as well.  It's all about how you use your elements and what you consider as resetting, but I feel that a bullet added to a list is something that should be removed in a proper reset.css file.&lt;/p&gt;

&lt;p&gt;Different browsers are going to have their own ways of rendering bullets and really the developer should explicitly inform us how they would like their lists rendered.&lt;/p&gt;

&lt;p&gt;Personally, most of my list items are lists of links as in menus, which require no bullets usually.  This is probably the source of my bias.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>sfBlueprintPlugin: Train of thought development</title>
   <link href="http://davedash.com/2007/08/30/sfblueprintplugin-train-of-thought-development/"/>
   <updated>2007-08-30T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/08/30/sfblueprintplugin-train-of-thought-development</id>
   <content type="html">&lt;p&gt;I've been creating some dummy projects for my presentations at &lt;a href=&quot;http://symfonycamp.com/&quot;&gt;SymfonyCamp&lt;/a&gt; and decided now would be a good time to learn using the Blueprint CSS framework.  It's a bit different than YUI which I've been using heavily, but it has some potential.&lt;/p&gt;

&lt;p&gt;Of course, instead of just downloading the framework, I made &lt;a href=&quot;http://trac.symfony-project.com/trac/browser/plugins/sfBlueprintPlugin&quot;&gt;a plugin&lt;/a&gt; for symfony.  It's not much yet, but eventually I'll throw in some helpers.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;

&lt;p&gt;[tags]css, symfony, blueprint, plugins, symfony camp, camp, yui[/tags]&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Textmate Snippets for YUI em calculations</title>
   <link href="http://davedash.com/2007/05/08/textmate-snippets-for-yui-em-calculations/"/>
   <updated>2007-05-08T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/05/08/textmate-snippets-for-yui-em-calculations</id>
   <content type="html">&lt;p&gt;[tags]yui, yahoo, css, snippet, textmate, ems, px[/tags]&lt;/p&gt;

&lt;p&gt;If you use &lt;a href=&quot;http://developer.yahoo.com/yui/grids/&quot;&gt;YUI grid layouts&lt;/a&gt; you'll notice that &lt;code&gt;ems&lt;/code&gt; are the preferred units and for good reason.  But ems don't make sense to people like us who want to be super precise down to the pixel... pixels make sense.&lt;/p&gt;

&lt;p&gt;So type in a number select it and run this &lt;code&gt;ruby&lt;/code&gt; script as a TextMate command (that outputs as a snippet):&lt;/p&gt;

&lt;div&gt;&lt;textarea name=&quot;code&quot; class=&quot;ruby&quot; cols=&quot;100&quot; rows=&quot;15&quot;&gt;
#!/usr/bin/env ruby
#
# This script will do the necessary YUI calculations from px to ems
#
# The result is inserted as a snippet, so it's
# possible to tab through the place holders.

# validate input
input    = ENV['TM_SELECTED_TEXT'].to_i;
width    = input.to_f/13
ie_width = width * 0.9759

print &quot;${1:width}:&quot;+width.to_s+&quot;em;*$1:&quot;+ie_width.to_s+&quot;em;$0&quot;
&lt;/textarea&gt;&lt;/div&gt;


&lt;p&gt;You'll have the proper tab stops to change the newly calculated &lt;code&gt;ems&lt;/code&gt; from &lt;code&gt;width&lt;/code&gt; to &lt;code&gt;margin-left&lt;/code&gt; or &lt;code&gt;margin-right&lt;/code&gt; or whatever it is you desire.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>TextMate + YUI = YUI snippets!</title>
   <link href="http://davedash.com/2007/04/30/textmate-yui-yui-snippets/"/>
   <updated>2007-04-30T00:00:00-07:00</updated>
   <id>http://davedash.com/2007/04/30/textmate-yui-yui-snippets</id>
   <content type="html">&lt;p&gt;I do a lot of &lt;a href=&quot;http://developer.yahoo.com/yui/grids/&quot;&gt;YUI grid layouts&lt;/a&gt; and I love the nestable grids:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;yui-g$1&quot;&amp;gt; 
    &amp;lt;div class=&quot;yui-u first&quot;&amp;gt;
        $2
    &amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;yui-u&quot;&amp;gt;
        $3
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There's a tab stop after &lt;code&gt;yui-g&lt;/code&gt; in case you want to use one of the variants (&lt;code&gt;yui-gb&lt;/code&gt;, &lt;code&gt;yui-gc&lt;/code&gt;, etc).&lt;/p&gt;

&lt;p&gt;I'm working on a site that uses two equal width columns... a lot... so this comes in quite handy.  So long tables.&lt;/p&gt;
</content>
 </entry>
 

</feed>

