<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PatCavit.com &#187; Demos</title>
	<atom:link href="http://patcavit.com/category/demos/feed/" rel="self" type="application/rss+xml" />
	<link>http://patcavit.com</link>
	<description>I &#60;3 Programming</description>
	<lastBuildDate>Fri, 02 Jul 2010 19:19:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Basic YUI 3 Plugin tutorial</title>
		<link>http://patcavit.com/2010/07/01/simple-yui3-plugin-tutorial/</link>
		<comments>http://patcavit.com/2010/07/01/simple-yui3-plugin-tutorial/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 00:35:33 +0000</pubDate>
		<dc:creator>Pat Cavit</dc:creator>
				<category><![CDATA[Demos]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[YUI]]></category>
		<category><![CDATA[Yahoo!]]></category>

		<guid isPermaLink="false">http://patcavit.com/?p=282</guid>
		<description><![CDATA[Ever since the release of the PR2 version of YUI3 the library has support for writing plugins. Unfortunately, this doesn&#8217;t seem to be taken advantage of all that often &#38; comes up a lot in the IRC channel as something people don&#8217;t understand. So let&#8217;s see if we can&#8217;t clarify the matter a little. At [...]]]></description>
			<content:encoded><![CDATA[<p>Ever since the release of the PR2 version of YUI3 the library has support for writing plugins. Unfortunately, this doesn&#8217;t seem to be taken advantage of all that often &amp; comes up a lot in the IRC channel as something people don&#8217;t understand. So let&#8217;s see if we can&#8217;t clarify the matter a little.</p>
<p>At their core YUI3 Plugins are a way to add new behavior to JS objects. It&#8217;s really just that simple. Going into it a little deeper you can explain the idea behind them as providing a framework-backed way to add new functionality &amp; behaviors to host objects without the host needing to know anything about the plugins. Taking advantage of this means that you can add lots of functionality to your objects without requiring a lot of code. It&#8217;s another example of YUI3&#8242;s great support for modularity of code. Want your widget to accept flaboozulms? Write a plugin! Want your widget to support flaboozulms &amp; flibberdybops? Write a plugin for flibberdybops &amp; then use both the flaboozulms &amp; flibberdybops plugins together. It&#8217;s a really powerful idea.</p>
<p>With the pontificating out of the way, let&#8217;s touch on some code. I&#8217;ll be taking apart a <strong>VERY</strong> basic plugin I&#8217;ve created that listens for clicks on the host &amp; changes the background color. This plugin specifically is targeted towards <a href="http://developer.yahoo.com/yui/3/node/">Node</a> objects since the behavior involves listening for a click event, but the basic concepts could work for any host object. It&#8217;s not a very in-depth example of the power here but it is simple enough to show the basics.</p>
<p><strong><a href="http://tivac.com/yui3/examples/plugin.htm">Basic YUI3 Plugin Example</a></strong></p>
<p>Quick breakdown of what this page contains. It&#8217;s got your standard HTML skeleton to allow us to easily run JS in the browser, a single &lt;div&gt; we&#8217;ll be using to show the interactions, some CSS to style that &lt;div&gt;, and some chunks of JS.</p>
<p>The first bit of JS is including the YUI3 seed file, as well as the loader (because we know for certain we&#8217;ll be using it we can save a HTTP request by getting these together).</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span class="sc2">&lt;<span class="kw2">script</span> <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;http://yui.yahooapis.com/combo?3.1.1/build/yui/yui.js&amp;amp;3.1.1/build/loader/loader.js&quot;</span>&gt;</span><span class="sc-1">&lt;!--mce:0--&gt;</span><span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">script</span>&gt;</span></pre></div></div>

<p>The next piece is declaring the plugin itself. This occurs within a <code><a href="http://developer.yahoo.com/yui/3/api/YUI.html#method_add">YUI.add()</a></code> block that allows us to later specify that we want to use the plugin. You could of course declare the function within the same <code><a href="http://developer.yahoo.com/yui/3/api/YUI.html#method_use">YUI().use()</a></code> section where you use it but that wouldn&#8217;t be very reusable.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">YUI.<span class="me1">add</span><span class="br0">&#40;</span><span class="st0">'basic-plugin'</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>Y<span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="co2">/* Plugin code here */</span>
<span class="br0">&#125;</span><span class="sy0">,</span> <span class="st0">&quot;0.1&quot;</span><span class="sy0">,</span> <span class="br0">&#123;</span> requires <span class="sy0">:</span> <span class="br0">&#91;</span> <span class="st0">&quot;base&quot;</span><span class="sy0">,</span> <span class="st0">&quot;plugin&quot;</span><span class="sy0">,</span> <span class="st0">&quot;node&quot;</span> <span class="br0">&#93;</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>Discussing the syntax for <code><a href="http://developer.yahoo.com/yui/3/api/YUI.html#method_add">YUI.add()</a></code> is a little outside the scope of this but you should note where we declare an array of modules that are required for the plugin to function.</p>
<p>Once inside of the <code><a href="http://developer.yahoo.com/yui/3/api/YUI.html#method_add">YUI.add()</a></code> it&#8217;s time to actually create the plugin object. It&#8217;ll be stuck onto the <code>Y</code> variable so that we&#8217;ve got a place to reference it in other code blocks that request our &#8220;basic-plugin&#8221;. The plugin object&#8217;s creation is handled using <code><a href="http://developer.yahoo.com/yui/3/api/Base.html#method_Base.create">Y.Base.create()</a></code>, a very useful framework function that takes care of inheritance &amp; a few other pieces for you. It&#8217;s a little hand wavey but if you want the nitty-gritty details feel free to ask &amp; I can provide them.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">Y.<span class="kw2">namespace</span><span class="br0">&#40;</span><span class="st0">'Examples'</span><span class="br0">&#41;</span>.<span class="me1">BasicPlugin</span> <span class="sy0">=</span> Y.<span class="me1">Base</span>.<span class="me1">create</span><span class="br0">&#40;</span><span class="st0">&quot;BasicPlugin&quot;</span><span class="sy0">,</span> Y.<span class="me1">Plugin</span>.<span class="me1">Base</span><span class="sy0">,</span> <span class="br0">&#91;</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="br0">&#123;</span> ... <span class="br0">&#125;</span><span class="sy0">,</span> <span class="br0">&#123;</span> ... <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>A quick breakdown of what we&#8217;re doing here, <code>Y.namespace('Examples').BasicPlugin</code> creates nested empty objects for us so everything stays nice and organized without any danger of collisions. Keeping things nested within namespaces like this helps to make sure we can use awesome names like &#8220;BasicPlugin&#8221; instead of stupid names like &#8220;CavitExampleBasicPlugin&#8221;. Nobody likes stupid names.</p>
<p>Next up is the assignment of the object returned by <code><a href="http://developer.yahoo.com/yui/3/api/Base.html#method_Base.create">Y.Base.create()</a></code> to our brand-new namespaced object. <code><a href="http://developer.yahoo.com/yui/3/api/Base.html#method_Base.create">Y.Base.create()</a></code> takes a name for the plugin, an class to inherit from, an array of classes to also optionally inherit from (unnecessary for our example), the prototype properties (more later), and static properties (again, more later). The function takes all of these objects &amp; combines them to allow for easy instantiating of objects later.</p>
<p>Let&#8217;s start with the prototype properties object that we&#8217;re passing to <code><a href="http://developer.yahoo.com/yui/3/api/Base.html#method_Base.create">Y.Base.create()</a></code>. This object is used as the <code><a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Function/prototype">.prototype</a></code> property of the class being created which means that it&#8217;ll be shared by every instance of this class. This is where any functions you want to live as part of the class go, along with any properties for that class instance.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">Y.<span class="me1">Base</span>.<span class="me1">create</span><span class="br0">&#40;</span>...<span class="sy0">,</span> ...<span class="sy0">,</span> <span class="br0">&#91;</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="br0">&#123;</span>
    _handle <span class="sy0">:</span> <span class="kw2">null</span><span class="sy0">,</span>
    initializer <span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> ... <span class="br0">&#125;</span><span class="sy0">,</span>
    destructor <span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> ... <span class="br0">&#125;</span>
<span class="br0">&#125;</span><span class="sy0">,</span> <span class="br0">&#123;</span> ... <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>Since this is a &#8220;basic&#8221; plugin we&#8217;re only providing one property &amp; two functions. The two functions (<code><a href="http://developer.yahoo.com/yui/3/api/Plugin.Base.html#method_initializer">initializer()</a></code> &amp; <code><a href="http://developer.yahoo.com/yui/3/api/Plugin.Base.html#method_destructor">destructor()</a>)</code> are special functions that YUI3 will call every time a new instance of this plugin is plugged or unplugged into a host. Starting with <code><a href="http://developer.yahoo.com/yui/3/api/Plugin.Base.html#method_initializer">initializer()</a></code> we can see that for this basic plugin all it&#8217;s doing is attaching a click event handler to the host (in this case a DOM node) that the plugin was plugged into.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span class="kw1">this</span>._handle <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;host&quot;</span><span class="br0">&#41;</span>.<span class="me1">on</span><span class="br0">&#40;</span><span class="st0">&quot;click&quot;</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw2">var</span> tgt <span class="sy0">=</span> e.<span class="me1">currentTarget</span><span class="sy0">,</span>
        color <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;color&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">this</span>.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;color&quot;</span><span class="sy0">,</span> tgt.<span class="me1">getStyle</span><span class="br0">&#40;</span><span class="st0">&quot;backgroundColor&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    tgt.<span class="me1">setStyle</span><span class="br0">&#40;</span><span class="st0">&quot;background&quot;</span><span class="sy0">,</span> color<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="sy0">,</span> <span class="kw1">this</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>It&#8217;s pretty straightforward YUI3 code but let&#8217;s run through it quickly. We attach an event handler to click events on the host object (<code><a href="http://developer.yahoo.com/yui/3/api/Attribute.html#method_get">this.get("host")</a></code> will get the special host attribute all plugins have) and provide a callback function to that handler. Note that we store a reference to the object returned by the event   attachment, this&#8217;ll be important later. The callback saves the target of the click &amp; the current color attribute&#8217;s value, then updates the color attribute with the target&#8217;s backgroundColor &amp; finally updates the backgroundColor of the target. The only tricky part in here is the use of <code><a href="http://developer.yahoo.com/yui/3/api/Attribute.html#method_get">this.get()</a></code> &amp; <code><a href="http://developer.yahoo.com/yui/3/api/Attribute.html#method_set">this.set()</a></code> which are used to access/update this plugins attributes data. We&#8217;ll talk about attributes in just a bit.</p>
<p>Next up is <code><a href="http://developer.yahoo.com/yui/3/api/Plugin.Base.html#method_destructor">destructor()</a></code> which is invoked whenever the plugin is destroyed (you&#8217;ll see how a little further down).</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">destructor <span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">this</span>._handle.<span class="me1">detach</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">this</span>._handle <span class="sy0">=</span> <span class="kw2">null</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>This clean up function ensures we don&#8217;t leave little bits of code poop all over the place. The event handler is detached &amp; the reference is nulled out to make sure that the garbage collector has no issue getting that little bit of memory back.</p>
<p>So at this point all we&#8217;ve really done is add an object to the <code>Y</code> variable that is accessible at <code>Y.Example.BasicPlugin</code> that when used in conjunction with <code><a href="http://developer.yahoo.com/yui/3/api/Base.html#method_Base.plug">.plug()</a></code> later on will listen for clicks &amp; change some background colors. I said we were making a basic plugin, excitement was never promised.</p>
<p>So if we step back up a bit to look at the next argument to <code><a href="http://developer.yahoo.com/yui/3/api/Base.html#method_Base.create">Y.Base.create()</a></code> we&#8217;ll notice that it is time to talk about the static properties. Here&#8217;s the code.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">Y.<span class="me1">Base</span>.<span class="me1">create</span><span class="br0">&#40;</span>...<span class="sy0">,</span> ...<span class="sy0">,</span> <span class="br0">&#123;</span><span class="br0">&#125;</span><span class="sy0">,</span> <span class="br0">&#123;</span>...<span class="br0">&#125;</span><span class="sy0">,</span> <span class="br0">&#123;</span>
    NS <span class="sy0">:</span> <span class="st0">&quot;sp&quot;</span><span class="sy0">,</span>
    ATTRS <span class="sy0">:</span> <span class="br0">&#123;</span>
        color <span class="sy0">:</span> <span class="br0">&#123;</span> value <span class="sy0">:</span> <span class="st0">&quot;blue&quot;</span> <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>Judging by the amount of code here it&#8217;s tempting to think that not a whole lot is happening. You&#8217;re right. More could be happening here but in the interest of time it&#8217;s been purposely kept very short. All this is doing is declaring two properties. <code><a href="http://developer.yahoo.com/yui/3/api/Plugin.Base.html#property_Plugin.NS">NS</a></code> is used for referencing the plugin object once it has been plugged into a host. The <code><a href="http://developer.yahoo.com/yui/3/api/Base.html#property_Base.ATTRS">ATTRS</a></code> property defines all the attributes that this plugin will support. The totally great thing about this is that it uses the YUI3 Attributes objects as its backend so you get a lot of power &amp; custom events to allow you to validate/get updates/whatever you want when these things are changed. That&#8217;s outside the scope of this article but I could go on about that for a while. This is where the ability to use <code><a href="http://developer.yahoo.com/yui/3/api/Attribute.html#method_get">this.get()</a></code>/<code><a href="http://developer.yahoo.com/yui/3/api/Attribute.html#method_set">this.set()</a></code> comes from as those are brought in automatically to get/set attributes.</p>
<p>So at this point we&#8217;ve got a complete plugin that&#8217;s been registered using <code><a href="http://developer.yahoo.com/yui/3/api/YUI.html#method_add">YUI.add()</a></code>, what do we do with it? Well the whole point of using <code><a href="http://developer.yahoo.com/yui/3/api/YUI.html#method_add">YUI.add()</a></code> was so that anywhere we wanted to on the page we could make the plugin available simply by doing something like the following.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">YUI<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="kw2">use</span><span class="br0">&#40;</span><span class="st0">&quot;node&quot;</span><span class="sy0">,</span> <span class="st0">&quot;basic-plugin&quot;</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>Y<span class="br0">&#41;</span> <span class="br0">&#123;</span> ... <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>And since we made sure to add the plugin to a namespace hung off of the main YUI instance variable (by convention it&#8217;s simply &#8220;Y&#8221;) within the <code><a href="http://developer.yahoo.com/yui/3/api/YUI.html#method_use">YUI().use()</a></code> callback we can now access our plugin at <code>Y.Examples.BasicPlugin</code>. So what to do with it now that it&#8217;s hanging out waiting to be used? I dunno, how about we plug something?</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#wooga&quot;</span><span class="br0">&#41;</span>.<span class="me1">plug</span><span class="br0">&#40;</span>Y.<span class="me1">Examples</span>.<span class="me1">BasicPlugin</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>So we&#8217;ve just taken our plugin and applied it to a host object. In this case the host object is a YUI3 Node object. That <code><a href="http://developer.yahoo.com/yui/3/api/Plugin.Base.html#method_initializer">initializer()</a></code> function we declared as a prototype property inside of <code><a href="http://developer.yahoo.com/yui/3/api/Base.html#method_Base.create">Y.Base.create()</a></code> will now be called &amp; the Node will now respond to clicks by changing its background color.</p>
<p>When you call <code><a href="http://developer.yahoo.com/yui/3/api/Plugin.Host.html#method_Plugin.Host.plug">.plug()</a></code> you can also pass in a configuration object that&#8217;ll define defaults for the plugin, so for the second example we also define the color attribute.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#booga&quot;</span><span class="br0">&#41;</span>.<span class="me1">plug</span><span class="br0">&#40;</span>Y.<span class="me1">Examples</span>.<span class="me1">BasicPlugin</span><span class="sy0">,</span> <span class="br0">&#123;</span> color <span class="sy0">:</span> <span class="st0">&quot;#666&quot;</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>This isn&#8217;t part of the live example but it&#8217;s an important concept, with YUI 3 plugins it&#8217;s just as easy to remove functionality as it is to add it. All you need to do is <code><a href="http://developer.yahoo.com/yui/3/api/Plugin.Host.html#method_unplug">unplug()</a></code> your plugin from the host. The plugin&#8217;s <code><a href="http://developer.yahoo.com/yui/3/api/Plugin.Base.html#method_destructor">destructor()</a></code> method is called and the host object loses whatever functionality was provided.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#wooga&quot;</span><span class="br0">&#41;</span>.<span class="me1">unplug</span><span class="br0">&#40;</span>Y.<span class="me1">Examples</span>.<span class="me1">BasicPlugin</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>One more thing to note, aside from the YUI3 seed file &amp; loader we never had to include any other &lt;script&gt; tags. This is because YUI3 is rad as hell and the Loader is able to determine based on the modules that <code><a href="http://developer.yahoo.com/yui/3/api/YUI.html#method_use">YUI().use()</a></code> asked for &amp; the requires array for the <code><a href="http://developer.yahoo.com/yui/3/api/YUI.html#method_add">YUI.add()</a></code> which files it should automatically load from the Yahoo! CDN. It&#8217;s super-powerful and one of my favorite features in YUI3.</p>
<p>For a better overview, here&#8217;s the complete JS code w/ minimal comments</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span class="co1">//create the module</span>
YUI.<span class="me1">add</span><span class="br0">&#40;</span><span class="st0">'basic-plugin'</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>Y<span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="co1">//create namespaced plugin class</span>
    Y.<span class="kw2">namespace</span><span class="br0">&#40;</span><span class="st0">'Examples'</span><span class="br0">&#41;</span>.<span class="me1">BasicPlugin</span> <span class="sy0">=</span> Y.<span class="me1">Base</span>.<span class="me1">create</span><span class="br0">&#40;</span><span class="st0">&quot;BasicPlugin&quot;</span><span class="sy0">,</span> Y.<span class="me1">Plugin</span>.<span class="me1">Base</span><span class="sy0">,</span> <span class="br0">&#91;</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="br0">&#123;</span>
&nbsp;
        _handle <span class="sy0">:</span> <span class="kw2">null</span><span class="sy0">,</span>
&nbsp;
        <span class="co1">//constructor</span>
        initializer <span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="kw1">this</span>._handle <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;host&quot;</span><span class="br0">&#41;</span>.<span class="me1">on</span><span class="br0">&#40;</span><span class="st0">&quot;click&quot;</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span> <span class="br0">&#123;</span>
                <span class="kw2">var</span> tgt <span class="sy0">=</span> e.<span class="me1">currentTarget</span><span class="sy0">,</span>
                    color <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;color&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
                <span class="kw1">this</span>.<span class="me1">set</span><span class="br0">&#40;</span><span class="st0">&quot;color&quot;</span><span class="sy0">,</span> tgt.<span class="me1">getStyle</span><span class="br0">&#40;</span><span class="st0">&quot;backgroundColor&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
                tgt.<span class="me1">setStyle</span><span class="br0">&#40;</span><span class="st0">&quot;background&quot;</span><span class="sy0">,</span> color<span class="br0">&#41;</span><span class="sy0">;</span>
            <span class="br0">&#125;</span><span class="sy0">,</span> <span class="kw1">this</span><span class="br0">&#41;</span><span class="sy0">;</span>
        <span class="br0">&#125;</span><span class="sy0">,</span>
&nbsp;
        <span class="co1">//clean up on destruction</span>
        destructor <span class="sy0">:</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
            <span class="kw1">this</span>._handle.<span class="me1">detach</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
            <span class="kw1">this</span>._handle <span class="sy0">=</span> <span class="kw2">null</span><span class="sy0">;</span>
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span><span class="sy0">,</span>
    <span class="br0">&#123;</span>
        NS <span class="sy0">:</span> <span class="st0">&quot;bp&quot;</span><span class="sy0">,</span>
        ATTRS <span class="sy0">:</span> <span class="br0">&#123;</span>
            color <span class="sy0">:</span> <span class="br0">&#123;</span> value <span class="sy0">:</span> <span class="st0">&quot;#00F&quot;</span> <span class="br0">&#125;</span>
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="sy0">,</span> <span class="st0">&quot;0.1&quot;</span><span class="sy0">,</span> <span class="br0">&#123;</span> requires <span class="sy0">:</span> <span class="br0">&#91;</span> <span class="st0">&quot;base&quot;</span><span class="sy0">,</span> <span class="st0">&quot;plugin&quot;</span><span class="sy0">,</span> <span class="st0">&quot;node&quot;</span> <span class="br0">&#93;</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
YUI<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="kw2">use</span><span class="br0">&#40;</span><span class="st0">&quot;node&quot;</span><span class="sy0">,</span> <span class="st0">&quot;basic-plugin&quot;</span><span class="sy0">,</span> <span class="kw2">function</span><span class="br0">&#40;</span>Y<span class="br0">&#41;</span> <span class="br0">&#123;</span>
    Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#wooga&quot;</span><span class="br0">&#41;</span>.<span class="me1">plug</span><span class="br0">&#40;</span>Y.<span class="me1">Examples</span>.<span class="me1">BasicPlugin</span><span class="br0">&#41;</span><span class="sy0">;</span>
    Y.<span class="me1">one</span><span class="br0">&#40;</span><span class="st0">&quot;#booga&quot;</span><span class="br0">&#41;</span>.<span class="me1">plug</span><span class="br0">&#40;</span>Y.<span class="me1">Examples</span>.<span class="me1">BasicPlugin</span><span class="sy0">,</span> <span class="br0">&#123;</span> color <span class="sy0">:</span> <span class="st0">&quot;#666&quot;</span> <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

<p>And the entire shebang including all the HTML &amp; CSS is available at the sample link.</p>
<p><strong><a href="http://tivac.com/yui3/examples/plugin.htm">Basic YUI3 Plugin Example</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://patcavit.com/2010/07/01/simple-yui3-plugin-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tweaking the Image Uploader</title>
		<link>http://patcavit.com/2008/07/23/tweaking-the-image-uploader/</link>
		<comments>http://patcavit.com/2008/07/23/tweaking-the-image-uploader/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 03:04:57 +0000</pubDate>
		<dc:creator>Pat Cavit</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Demos]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tivac.com Projects]]></category>
		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://patcavit.com/?p=192</guid>
		<description><![CDATA[For fun I went trolling through the images people have uploaded via the YUI Uploader implementation I wrote a while ago. When it took my browser a solid 30 seconds to even be remotely responsive and start rendering images it struck me that perhaps it was time to paginate the images instead of just dumping [...]]]></description>
			<content:encoded><![CDATA[<p>For fun I went trolling through the images people have uploaded via the <a title="YUI Upload Implementation" href="http://patcavit.com/2008/03/01/yui-uploader-implementation/">YUI Uploader implementation</a> I wrote a while ago. When it took my browser a solid 30 seconds to even be remotely responsive and start rendering images it struck me that perhaps it was time to paginate the images instead of just dumping them all out onto one page.</p>
<p>So I added pagination. It&#8217;s currently super simple which makes for easy explanation. The PHP still collects and sorts every single image in the directory by date. I don&#8217;t think there&#8217;s any other way to do that. Afterwards it checks to see if the &#8220;o&#8221; query param was set and is an integer (thanks for adding <a title="Filter Input PHP Man Page" href="http://www.php.net/manual/en/function.filter-input.php">filter_input</a> to PHP5, PHP devs!). Once there&#8217;s an offset to start from, it slices the array at that point and takes the next 50 images.</p>
<p>After that there&#8217;s just some simple logic around drawing the pagination numbers and figuring out which one is the current page. The numbers are centered and boxed using a variation on Hedger&#8217;s inline-block work (<a href="http://www.hedgerwow.com/360/dhtml/css-inline-block-layout.php">Item List Grid : Practice with display:inline block across browsers</a>) that I worked on for the next VYC release. It solves the problem with a minimum amount of code in a really semantic way that just makes my web developer brain as happy as can be. Granted the CSS is not what I would call &#8220;pretty&#8221; but it works everywhere and is not impossible to understand, so I&#8217;m not too bothered by it.</p>
<p>So here&#8217;s how it turned out. Be forewarned that I don&#8217;t control what is uploaded here, and as such there might be <strong>NSFW</strong> content on this page!</p>
<p><a title="Uploaded Images" href="http://tivac.com/upload/images/">http://tivac.com/upload/images/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://patcavit.com/2008/07/23/tweaking-the-image-uploader/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zune Backgrounds</title>
		<link>http://patcavit.com/2008/03/01/zune-backgrounds/</link>
		<comments>http://patcavit.com/2008/03/01/zune-backgrounds/#comments</comments>
		<pubDate>Sat, 01 Mar 2008 21:03:56 +0000</pubDate>
		<dc:creator>Pat Cavit</dc:creator>
				<category><![CDATA[Demos]]></category>
		<category><![CDATA[Pretty]]></category>
		<category><![CDATA[Tivac.com Projects]]></category>

		<guid isPermaLink="false">http://patcavit.com/2008/03/01/zune-backgrounds/</guid>
		<description><![CDATA[Uploading lots of images with my new image uploader is fun, so I&#8217;m throwing up all of the backgrounds I&#8217;ve collected for my Zune. They&#8217;re mostly cropped versions of my wallpaper collection, with a few I&#8217;ve found around the Internet scattered here and there.]]></description>
			<content:encoded><![CDATA[<p>Uploading lots of images with my new image uploader is fun, so I&#8217;m throwing up all of the backgrounds I&#8217;ve collected for my Zune.  They&#8217;re mostly cropped versions of my wallpaper collection, with a few I&#8217;ve found around the Internet scattered here and there.</p>
<ul class="image_grid">
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pwwZIsw_whiteringszune.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pwwZIsw_whiteringszune.jpg" alt="whiteringszune.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pPCwuqP_ultimate-strands.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pPCwuqP_ultimate-strands.jpg" alt="Ultimate Strands.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pqQ0gnW_lego-r2-d2.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pqQ0gnW_lego-r2-d2.jpg" alt="LEGO R2-D2.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pZZHO3e_lego-boba-fett.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pZZHO3e_lego-boba-fett.jpg" alt="LEGO Boba Fett.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pG4fXWa_moon-to-earth.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pG4fXWa_moon-to-earth.jpg" alt="moon to earth.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pTUCqvl_organica-grey.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pTUCqvl_organica-grey.jpg" alt="Organica Grey.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/psJVgGC_gow-logo.jpg"><img src="http://tivac.com/upload/images/thumbs/th_psJVgGC_gow-logo.jpg" alt="GOW Logo.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pR349ky_organica-green.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pR349ky_organica-green.jpg" alt="Organica Green.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/p2ZcJ16_atmosphere.jpg"><img src="http://tivac.com/upload/images/thumbs/th_p2ZcJ16_atmosphere.jpg" alt="Atmosphere.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pd4gJbk_earth-space.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pd4gJbk_earth-space.jpg" alt="Earth-Space.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/ptfhOqg_flow-red.jpg"><img src="http://tivac.com/upload/images/thumbs/th_ptfhOqg_flow-red.jpg" alt="Flow Red.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pYm5laR_domo.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pYm5laR_domo.jpg" alt="domo.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/prh4NAr_3805_small.jpg"><img src="http://tivac.com/upload/images/thumbs/th_prh4NAr_3805_small.jpg" alt="3805_small.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/p6qWm4d_logogreyzune.jpg"><img src="http://tivac.com/upload/images/thumbs/th_p6qWm4d_logogreyzune.jpg" alt="logogreyzune.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pgZcqQW_lego-rebel-pilot.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pgZcqQW_lego-rebel-pilot.jpg" alt="LEGO Rebel Pilot.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/ptuHYQ5_blackringszune.jpg"><img src="http://tivac.com/upload/images/thumbs/th_ptuHYQ5_blackringszune.jpg" alt="blackringszune.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pChxxyi_i-love-summer.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pChxxyi_i-love-summer.jpg" alt="I Love Summer.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/p9TB9mU_altered-bliss.jpg"><img src="http://tivac.com/upload/images/thumbs/th_p9TB9mU_altered-bliss.jpg" alt="Altered Bliss.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pMuA38X_brigade-damaged.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pMuA38X_brigade-damaged.jpg" alt="Brigade Damaged.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pygj4ri_qqwl.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pygj4ri_qqwl.jpg" alt="qqwl.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pVl2bWq_lego-darth-vader.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pVl2bWq_lego-darth-vader.jpg" alt="LEGO Darth Vader.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/polstSW_gow-lancer.jpg"><img src="http://tivac.com/upload/images/thumbs/th_polstSW_gow-lancer.jpg" alt="GOW Lancer.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/ptOpAum_lego-stormtrooper.jpg"><img src="http://tivac.com/upload/images/thumbs/th_ptOpAum_lego-stormtrooper.jpg" alt="LEGO Stormtrooper.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pwuBtZd_lego-batman.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pwuBtZd_lego-batman.jpg" alt="LEGO Batman.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pdFpdvn_sound-crushing.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pdFpdvn_sound-crushing.jpg" alt="Sound Crushing.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pstnx9T_halo-3-cg-trailer.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pstnx9T_halo-3-cg-trailer.jpg" alt="Halo 3 CG Trailer.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pwqgMdK_flow-green.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pwqgMdK_flow-green.jpg" alt="Flow Green.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pkV9YUm_nemo-gull.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pkV9YUm_nemo-gull.jpg" alt="Nemo Gull.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pUxm0xN_yarr.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pUxm0xN_yarr.jpg" alt="Yarr.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/plEMk6l_gathering-storm.jpg"><img src="http://tivac.com/upload/images/thumbs/th_plEMk6l_gathering-storm.jpg" alt="Gathering Storm.jpg" /></a></p>
</li>
<li>
<p class="bd"><a href="http://tivac.com/upload/images/pczMjuf_blurry-fireworks.jpg"><img src="http://tivac.com/upload/images/thumbs/th_pczMjuf_blurry-fireworks.jpg" alt="Blurry Fireworks.jpg" /></a></p>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://patcavit.com/2008/03/01/zune-backgrounds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>YUI Uploader Implementation</title>
		<link>http://patcavit.com/2008/03/01/yui-uploader-implementation/</link>
		<comments>http://patcavit.com/2008/03/01/yui-uploader-implementation/#comments</comments>
		<pubDate>Sat, 01 Mar 2008 20:26:24 +0000</pubDate>
		<dc:creator>Pat Cavit</dc:creator>
				<category><![CDATA[Demos]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tivac.com Projects]]></category>
		<category><![CDATA[YUI]]></category>
		<category><![CDATA[Yahoo!]]></category>

		<guid isPermaLink="false">http://patcavit.com/2008/03/01/yui-uploader-implementation/</guid>
		<description><![CDATA[Image Uploading using YUI Uploader Widget A few days ago the YUI team released the latest and greatest version of the YUI Library, YUI 2.5.0. Along with the usual round of bugfixes and speed improvements this release came with several new components. I personally was the most excited about the Uploader component, as the technology [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tivac.com/upload/"><strong>Image Uploading using YUI Uploader Widget</strong></a></p>
<p>A few days ago the YUI team released the latest and greatest version of the YUI Library, <a href="http://yuiblog.com/blog/2008/02/20/yui-250-released/">YUI 2.5.0</a>. Along with the usual round of bugfixes and speed improvements this release came with several new components. I personally was the most excited about the <a href="http://developer.yahoo.com/yui/uploader/" title="YUI Uploader Docs" target="_blank">Uploader</a> component, as the technology that powers it also underpins the upload process on <a href="http://video.yahoo.com" title="Yahoo! Video" target="_blank">Yahoo! Video</a>. I didn&#8217;t write the upload pages but I&#8217;m expected to be able to provide bugfixes and enhancements to those pages, so what better way to learn how they work than from the ground up with the Uploader?</p>
<p>Yes, I know there&#8217;s quite a few better ways. This was the most fun sounding way. What can I say, I like 4 day projects in my spare time instead of just reading the existing code. Besides, I wanted a better understanding of it from a lower level than just how the upload code on VYC works.</p>
<p>As mentioned in the YUI Blog posting about 2.5.0, the Uploader is what not only powers <abbr title="video.yahoo.com">VYC</abbr> uploads but Flickr uploads as well. Flickr exposes more of it due to their allowing of multiple files uploaded at once. That&#8217;s not really very easy to do on VYC due to the <strong>much</strong> larger file sizes being used. Still, it&#8217;s there.  I promise.</p>
<p>I&#8217;ve had a free-for-all, open to anyone image uploader chilling out for quite some time at <a href="http://tivac.com/upload/">http://tivac.com/upload/</a>. I wrote it to solve a problem, namely <a href="http://imageshack.us">the</a> other image uploading services available at the time sucked. It was just a quick little thing, with some basic JS that would hide the form element and create a new one so you could upload more than one file at a time.  When you were done it would barf out thumbs of the images along with some common types of link code for forums and the like.  Nothing fancy at all. Well, the new YUI Uploader seemed pretty much tailor-made to work instead of creating new form elements.</p>
<p>Here&#8217;s a good representation of my thought process while I contemplated redoing the image uploader.</p>
<table border="1" cellpadding="2" cellspacing="0" width="700">
<tr>
<th valign="top" width="155">Method</th>
<th valign="top" width="125">Select multiple files from one dialog?</th>
<th valign="top" width="139">Progress feedback available for updating the UI?</th>
<th valign="top" width="139">Smart enough to not totally hose the browser while uploading?</th>
<th valign="top" width="140">Able to dynamically update UI on completion?</th>
</tr>
<tr>
<td valign="top" width="155">Form + JS</td>
<td valign="top" width="125">No</td>
<td valign="top" width="138">No</td>
<td valign="top" width="139">No</td>
<td valign="top" width="141">Sorta</td>
</tr>
<tr>
<td valign="top" width="154">Uploader + JS</td>
<td valign="top" width="125"><strong>Yes</strong></td>
<td valign="top" width="139"><strong>Yes</strong></td>
<td valign="top" width="139"><strong>Yes</strong></td>
<td valign="top" width="142"><strong>Yes</strong></td>
</tr>
</table>
<p>I think that paints a pretty compelling picture of why I&#8217;d go with the YUI lib over the original solution. Aside from requiring Flash 9 and not working on the latest OSX because Adobe and Apple are feuding, there&#8217;s really no downside.  It&#8217;s provably better in every way. Since this is just a junky little personal project and not something important, I don&#8217;t even provide a fallback HTML form any more.  That&#8217;s just how I roll.</p>
<p>Actual implementation was pretty basic. The YUI documentation is excellent as always.  It more or less started life out as a copy of their <a href="http://developer.yahoo.com/yui/examples/uploader/uploader-simple.html">Simple Upload Example</a> and then I hacked the crap out of it. The flow ended up being something along the lines of the following.</p>
<ol>
<li>Browse for image files.<br />
<a href="http://patcavit.com/wp-content/uploads/2008/03/upload-step-1.png"><img src="http://patcavit.com/wp-content/uploads/2008/03/upload-step-1-thumb.png" style="border-width: 0px" alt="upload step 1" border="0" height="71" width="244" /></a></li>
<li>If you selected one you don&#8217;t actually want to upload, clicking it&#8217;s filename will remove it.<br />
<a href="http://patcavit.com/wp-content/uploads/2008/03/upload-step-2.png"><img src="http://patcavit.com/wp-content/uploads/2008/03/upload-step-2-thumb.png" style="border-width: 0px" alt="upload step 2" border="0" height="112" width="244" /></a></li>
<li>Upload the files, watch all the fun progress bars whiz around.<br />
<a href="http://patcavit.com/wp-content/uploads/2008/03/upload-step-3.png"><img src="http://patcavit.com/wp-content/uploads/2008/03/upload-step-3-thumb.png" style="border-width: 0px" alt="upload step 3" border="0" height="100" width="244" /></a></li>
<li>As each file completes, its filename is replaced with a thumbnail and various different pre-filled link codes for HTML and forums.<br />
<a href="http://patcavit.com/wp-content/uploads/2008/03/upload-step-4.png"><img src="http://patcavit.com/wp-content/uploads/2008/03/upload-step-4-thumb.png" style="border-width: 0px" alt="upload step 4" border="0" height="244" width="218" /></a></li>
<li>You can also hit the Export button to just get a list of the URLs of the uploaded images.<br />
<a href="http://patcavit.com/wp-content/uploads/2008/03/upload-step-5.png"><img src="http://patcavit.com/wp-content/uploads/2008/03/upload-step-5-thumb.png" style="border-width: 0px" alt="upload step 5" border="0" height="70" width="244" /></a></li>
</ol>
<p>It sounds complicated because I&#8217;m an engineer and don&#8217;t explain things well.  The cool nerdy thing about this is how very event-driven it is.  For example, take a look at this code chunk.</p>
<p class="csharpcode">&nbsp;</p>
<pre class="alt"><span class="rem">//certain things can only happen once the SWF is ready to rock</span></pre>
<pre><span class="kwrd">this</span>.uploader.addListener(<span class="str">'contentReady'</span>,   <span class="kwrd">this</span>.swfReady);</pre>
<pre class="alt"><span class="rem">//event handlers</span></pre>
<pre><span class="kwrd">this</span>.uploader.addListener(<span class="str">'fileSelect'</span>,         <span class="kwrd">this</span>.onFileSelect);</pre>
<pre class="alt"><span class="kwrd">this</span>.uploader.addListener(<span class="str">'uploadStart'</span>,        <span class="kwrd">this</span>.onUploadStart);</pre>
<pre><span class="kwrd">this</span>.uploader.addListener(<span class="str">'uploadError'</span>,        <span class="kwrd">this</span>.onUploadError);</pre>
<pre class="alt"><span class="kwrd">this</span>.uploader.addListener(<span class="str">'uploadProgress'</span>,     <span class="kwrd">this</span>.onUploadProgress);</pre>
<pre><span class="kwrd">this</span>.uploader.addListener(<span class="str">'uploadCancel'</span>,       <span class="kwrd">this</span>.onUploadCancel);</pre>
<pre class="alt"><span class="kwrd">this</span>.uploader.addListener(<span class="str">'uploadComplete'</span>,     <span class="kwrd">this</span>.onUploadComplete);</pre>
<pre><span class="kwrd">this</span>.uploader.addListener(<span class="str">'uploadCompleteData'</span>, <span class="kwrd">this</span>.onUploadCompleteData);</pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } </style>
<p>There&#8217;s an event fired by the flash object for pretty much everything you could want.  The only event I found myself wishing it supported was a &#8220;allUploadsComplete&#8221; method.  As it was I had to create a cache of all the file ids being uploaded, and in my handler for uploadComplete I would remove each id from the cache.  If there&#8217;s no more files left to upload, hey presto we&#8217;re done! A little roundabout, especially when having to watch out for files that were selected and then removed.</p>
<p>The other fun thing I decided upon was that instead of using innerHTML and getting back big chunks of HTML from the server (wrapped in JSON, of course) I&#8217;d instead use skeleton structures hidden in the DOM.  A quick</p>
<pre class="csharpcode">YUD.get(<span class="str">'upload_skeleton'</span>).cloneNode(<span class="kwrd">true</span>);</pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } </style>
<p>and you&#8217;ve got yourself a nice chunk of HTML just waiting for some delicious data to be inserted.  The actual insertion is pretty boring DOM traversals, but by using a skeleton as the base it avoids heavy node creation/appending or a massive innerHTML dump.  The page&#8217;s DOM is a little heavier because it contains these stubs, but there&#8217;s only two of them and page weight isn&#8217;t a big concern for this project.</p>
<p>The progress meters are basically a total ripoff of Flickr, I feel a little bad about it but I really liked their approach of using a background image and just changing the x offset each time uploadProgress was called. It&#8217;s so simple and to the point that I didn&#8217;t see any reason to make it more complicated.</p>
<p>So that all works fine, but I was worried that if I didn&#8217;t copy the URLs correctly right away the images would be lost forever. That meant that I had to write a little PHP script that would output linked thumbs of all the images that had been uploaded.  Since this is a totally unrestricted image uploader there&#8217;s been a few instances of people uploading porn and the like. I&#8217;d rather not deal with that, so there&#8217;s a little delete script as well. It&#8217;s protected by a .htaccess/.htpasswd basic auth setup.  Nothing fancy, but it keeps other people from being able to delete my images.</p>
<p><a href="http://patcavit.com/wp-content/uploads/2008/03/image-browser.png"><img src="http://patcavit.com/wp-content/uploads/2008/03/image-browser-thumb.png" style="border-width: 0px" alt="image browser" border="0" height="266" width="314" /></a></p>
<p>The images are laid out in a big floating grid using <a href="http://hedgerwow.com">Hedger&#8217;s</a> very awesome work on getting display: inline-block to work across browsers. <a href="http://www.hedgerwow.com/360/dhtml/css-inline-block-layout.php">Item List Grid : Practice with display:inline block across browsers</a>. It&#8217;s a technique we also used extensively on <abbr title="video.yahoo.com">VYC</abbr> so it was the first thing that came to mind when just floating a bunch of images that weren&#8217;t the same height went all crazy.</p>
<p>Oh, right.  All the icons are the insanely awesome work of <a href="http://famfamfam.com/">Mark James</a>, specifically his <a href="http://famfamfam.com/lab/icons/silk/">Silk</a> set of icons. I&#8217;m sure you&#8217;ve seen them used pretty much everywhere.  There&#8217;s a good reason for that, they rock.</p>
<p>I&#8217;ve zipped up the source for anyone who wants it, it&#8217;s all pretty well-commented.  You will have to handle the file permissions yourself though. <strong>UPDATE: </strong><a href="http://sitzmar.com">Sitzmar</a> wanted me to point out that all the paths are hard-coded for my uploader.  He says I should be ashamed, I say he should shut up.  Also I don&#8217;t think I included the .htpasswd (obviously) or the .htaccess.  Those are easily set up, a quick search on the internet will answer all questions.</p>
<p><a href="http://tivac.com/upload/upload.zip">upload.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://patcavit.com/2008/03/01/yui-uploader-implementation/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Senior Project</title>
		<link>http://patcavit.com/2007/04/20/senior-project/</link>
		<comments>http://patcavit.com/2007/04/20/senior-project/#comments</comments>
		<pubDate>Fri, 20 Apr 2007 19:57:20 +0000</pubDate>
		<dc:creator>Pat Cavit</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Demos]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[school]]></category>

		<guid isPermaLink="false">http://patcavit.com/2007/04/20/senior-project/</guid>
		<description><![CDATA[I&#8217;ve tossed a copy of my senior project up at http://patcavit.com/dev/classfinder/, a quick inspection makes it look like it&#8217;s working fine but I can&#8217;t say for sure. For those that don&#8217;t know this is an attempt to make the Classfinder tool at Western Washington University not only easier to use but also cleaner and faster [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve tossed a copy of my senior project up at <a href="http://patcavit.com/dev/classfinder/" title="Classfinder">http://patcavit.com/dev/classfinder/</a>, a quick inspection makes it look like it&#8217;s working fine but I can&#8217;t say for sure.  </p>
<p>For those that don&#8217;t know this is an attempt to make the <a href="https://www.admin.wwu.edu/pls/wwis/wwsktime.SelClass">Classfinder</a> tool at Western Washington University not only easier to use but also cleaner and faster with more emphasis on getting out of the way.  To that end it has a few features that the original Classfinder doesn&#8217;t have, including a freeform search box that will guess what you searched for and dynamic scratchsheet handling.  You can add classes instantly without having to go to a seperate page.  No screenshots for now.</p>
<p>It&#8217;s not the prettiest thing out there but it&#8217;s very functional and tries to take better advantage of screen real-estate than the previous Classfinder.  I&#8217;m pretty happy with how it turned out overall.</p>
]]></content:encoded>
			<wfw:commentRss>http://patcavit.com/2007/04/20/senior-project/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tech Demos</title>
		<link>http://patcavit.com/2006/01/26/tech-demos/</link>
		<comments>http://patcavit.com/2006/01/26/tech-demos/#comments</comments>
		<pubDate>Fri, 27 Jan 2006 02:17:12 +0000</pubDate>
		<dc:creator>Pat Cavit</dc:creator>
				<category><![CDATA[Demos]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://patcavit.com/2006/01/26/tech-demos/</guid>
		<description><![CDATA[I was looking for a better way to show interaction with some of the apps I&#8217;ve built than my old method. The old method consisted of lots of print-screens, ImageReady, and making an animated GIF. It wasn&#8217;t pretty, but it got the job done. In search of a better method I asked a friend of [...]]]></description>
			<content:encoded><![CDATA[<p>I was looking for a better way to show interaction with some of the apps I&#8217;ve built than my old method.  The old method consisted of lots of print-screens, ImageReady, and making an animated GIF.  It wasn&#8217;t pretty, but it got the job done.  In search of a better method I asked a friend of they had any ideas and he pointed me to the excellent <a href="http://www.unixuser.org/~euske/vnc2swf/">vnc2swf</a> package.  A quick trip to go get the required Python libraries and a VNC server, and I was up and running.  Here&#8217;s what I came up with today while experimenting.</p>
<ul>
<li><a href="/dev/demos/answerline_config_flow.html">Answerline Config Demo</a> (Flickr-Style editing)</li>
<li><a href="/dev/demos/answerline_ticket_flow.html">Answerline Ticket Interaction</a></li>
<li><a href="/dev/demos/ipadmin_flow.html">IPAdmin Deleting</a> (Simple but effective)</li>
<li><a href="/dev/demos/surveys_flow.html">Creating a Survey</a></li>
<li><a href="/dev/demos/surveys_results.html">Filling out Existing Survey/Viewing Results</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://patcavit.com/2006/01/26/tech-demos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Saving time with Ajax</title>
		<link>http://patcavit.com/2006/01/13/saving-time-with-ajax/</link>
		<comments>http://patcavit.com/2006/01/13/saving-time-with-ajax/#comments</comments>
		<pubDate>Fri, 13 Jan 2006 22:38:58 +0000</pubDate>
		<dc:creator>Pat Cavit</dc:creator>
				<category><![CDATA[Demos]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://patcavit.com/2006/01/13/saving-time-with-ajax/</guid>
		<description><![CDATA[A simple javascript event handler with a small regex, a short DB-enabled PHP script, and some reasonable error-handling makes it so you don&#8217;t even start filling out the form if a user doesn&#8217;t have proper paperwork on file. It&#8217;s neat and saves lots of time for all involved. (Yes I&#8217;m posting this just because the [...]]]></description>
			<content:encoded><![CDATA[<p>A simple javascript event handler with a small regex, a short DB-enabled PHP script, and some reasonable error-handling makes it so you don&#8217;t even start filling out the form if a user doesn&#8217;t have proper paperwork on file.  It&#8217;s neat and saves lots of time for all involved.</p>
<p>(Yes I&#8217;m posting this just because the planet has been too quiet lately.)</p>
<p><a href='http://patcavit.com/?attachment_id=82'><img src='http://patcavit.com/wp-content/uploads/2006/01/student_check.gif' /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://patcavit.com/2006/01/13/saving-time-with-ajax/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Surveys</title>
		<link>http://patcavit.com/2005/11/20/new-surveys/</link>
		<comments>http://patcavit.com/2005/11/20/new-surveys/#comments</comments>
		<pubDate>Sun, 20 Nov 2005 10:26:10 +0000</pubDate>
		<dc:creator>Pat Cavit</dc:creator>
				<category><![CDATA[Demos]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://patcavit.com/2005/11/20/new-surveys/</guid>
		<description><![CDATA[Much like the rest of the legacy code that still rattles around at ResTek, the old version of Surveys was a beast. Lots of SQL scattered throughout, poorly-implemented OO, invalid HTML, and a truly horrifying series of Javascript form submittal links. It was a scary place to try and bugfix, and not something that we [...]]]></description>
			<content:encoded><![CDATA[<p>Much like the rest of the legacy code that still rattles around at ResTek, the old version of Surveys was a beast.  Lots of SQL scattered throughout, poorly-implemented OO, invalid HTML, and a truly horrifying series of Javascript form submittal links.  It was a scary place to try and bugfix, and not something that we were very thrilled about sharing.  Surveys is pretty unique in that it is far and away our most popular shared application.  We offer up a lot of the code that we&#8217;ve written and even host stuff for other departments on campus.  No other application is used by as many people for as many things as Surveys.</p>
<p>It&#8217;s surprising that old Surveys survived as long as it did, a testament to the amount of quickfixes that we&#8217;d been able to shove into it to keep things moving along.  As is my way from time to time I had become sick of it.  Finishing up Answerline (as seen in <a href="http://patcavit.com/2005/08/12/done-done-done/">&#8220;Done Done Done&#8221;</a>, <a href="http://patcavit.com/2005/08/11/so-close-to-done/">&#8220;So Close To Done&#8221;</a>, <a href="http://patcavit.com/2005/08/08/more-new-answerline-ui/">&#8220;More New Answerline UI&#8221;</a>, and <a href="http://patcavit.com/2005/07/26/rethinking-answerline/">&#8220;Rethinking Answerline&#8221;</a>) gave me the ability to pick a new project.  First in my crosshairs, Surveys.</p>
<p>Getting a handle on how I wanted the new interface for surveys to work wasn&#8217;t easy.  My first choice was to have user-draggable questions that combined the old preview and edit modes into one seamless interface while also adding live updating for all the actions that used to require a page reload.  In Old Surveys the page would reload if you: added a question; removed a question; changed a question&#8217;s type; added an answer; reordered questions, etc.  It was frustrating to try and use, because the responsiveness just wans&#8217;t there.  Feeling good about JavaScript after the Answerline Revamp, I tried to address all of these issues.  The page reloads were simple, I&#8217;d replace them with degradable JavaScript making AJAX calls via my current favorite Library, <a href="http://twilightuniverse.com/resources/code/sack/">SACK</a>.  It&#8217;s lightweight and just does the AJAX transport/receiving stuff.  I&#8217;m a fan of lightweight libraries, the big ones like Prototype and Scriptaculous just don&#8217;t interest me that much.  Too much overhead for what I&#8217;d need.</p>
<p>Back to New Surveys UI design decisions.  My biggest regret about this project is that I was unable to get a flexible and fast enough drag/drop library for the list elements.  Dragging the DOM stuff around was cake thanks to Aaron Boodman&#8217;s excellent <a href="http://www.youngpup.net/2001/domdrag">DOM-Drag</a> library.  I found several wrappers for it that took care of limiting motion and shifting list elements around for me.  It was awesome to see, but once I had it up and running the problems started to crop up.  The <a href="http://blog.tool-man.org/toolman-dhtml-02-released/16">ToolMan DHTML</a> library looked like it would do everything I needed, and at first blush it worked flawlessly.  The effect was really very slick and much more intuitive than selecting numbers from a drop down.  Unfortunately, the shortcomings of the library made it impossible to keep.  You couldn&#8217;t drag a question past the bottom or top edges of the screen, a deal-breaker any survey longer than a few questions.  It also tended to apply the drag-drop to list elements within the main list.  This was not particularly undesirable behavior, but proved to be so buggy as to be a liability instead of a feature.  When I couldn&#8217;t get much of a response to my inquiries I had to eventually abandon my drag and drop dreams.  It was a sad day.  Fortunately the rest of my ideas had worked out well, allowing for New Surveys to be much faster when creating a new survey or editing a pre-existing one.</p>
<p>The creation of New Surveys required more attention to ease-of-use considerations than I&#8217;d run into before.  I don&#8217;t recall ever purposefully designing a hard to use webpage, but as someone who is very comfortable with computers it&#8217;s quite easy for me to fall into the trap of designing for myself and not the end user.  I had to pay careful attention to labelling and the organization of elements on the screen in an attempt to guide those who might not be as familiar with the system.  Now that it&#8217;s out there and normal users are getting their hands dirty in it I&#8217;ve come to the realization that even my best UI efforts are not really enough.  I wish I knew a UI expert that I could ask questions and have critique my stuff.  I find the whole thought process behind that really interesting but a lack of real studying means that I mostly make slightly educated guesses.</p>
<p>I&#8217;m sure that everyone is bored to tears now, so I&#8217;ll post an image.  Just one this time, because it took a while to make and I&#8217;m kinda tired at this point.</p>
<p><a id="75" rel="attachment" href="http://patcavit.com/wp-content/uploads/2005/11/Surveys.big.gif" title="New Surveys - Small"><img width="200" height="161" align="middle" src="http://patcavit.com/wp-content/uploads/2005/11/Surveys.small.gif" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://patcavit.com/2005/11/20/new-surveys/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>More new Answerline UI</title>
		<link>http://patcavit.com/2005/08/08/more-new-answerline-ui/</link>
		<comments>http://patcavit.com/2005/08/08/more-new-answerline-ui/#comments</comments>
		<pubDate>Mon, 08 Aug 2005 08:18:23 +0000</pubDate>
		<dc:creator>Pat Cavit</dc:creator>
				<category><![CDATA[Demos]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://patcavit.com/2005/08/08/more-new-answerline-ui/</guid>
		<description><![CDATA[Old style config editing worked ok, this is neater. Idea totally stolen from Flickr. The alignment is a recent CSS bug that I haven&#8217;t gotten around to fixing yet, it&#8217;ll line up better in a bit.]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/editconfig.gif" alt="New config editing method" /></p>
<p>Old style config editing worked ok, this is neater.  Idea totally stolen from Flickr.  The alignment is a recent CSS bug that I haven&#8217;t gotten around to fixing yet, it&#8217;ll line up better in a bit.</p>
]]></content:encoded>
			<wfw:commentRss>http://patcavit.com/2005/08/08/more-new-answerline-ui/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rethinking Answerline</title>
		<link>http://patcavit.com/2005/07/26/rethinking-answerline/</link>
		<comments>http://patcavit.com/2005/07/26/rethinking-answerline/#comments</comments>
		<pubDate>Tue, 26 Jul 2005 09:50:53 +0000</pubDate>
		<dc:creator>Pat Cavit</dc:creator>
				<category><![CDATA[Demos]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Work]]></category>

		<guid isPermaLink="false">http://patcavit.com/2005/07/26/rethinking-answerline/</guid>
		<description><![CDATA[A big (omg huge big) part of this whole Answerline re-writing was coming up with a new, sleeker interface for people to interact with. The old interface was nice to look at and an awesome clean design thanks to gunner&#8217;s mad design skills, but ended up having some usability issues. The small text underneath the [...]]]></description>
			<content:encoded><![CDATA[<p>A big (omg huge big) part of this whole Answerline re-writing was coming up with a new, sleeker interface for people to interact with.  The old interface was nice to look at and an awesome clean design thanks to gunner&#8217;s mad design skills, but ended up having some usability issues.  The small text underneath the student name was tough to read and emphasized the field, not the value.  In an attempt to remedy this, I created a new way of display tickets.  Not only is this display smaller vertically, but it reduces the required number of buttons and makes important information easier to find.</p>
<p>The other big change is the switch from a traditional paged interface where each button click takes you to a new page.  Due to our small user set, we can require certain things.  Javascript is one of those, and that allows for a more interactive and dynamic user interface.  Thanks to the awesomely simple <a href="http://twilightuniverse.com/2005/05/sack-of-ajax/"><strong>S</strong>imple <strong>A</strong>jax <strong>C</strong>ode <strong>K</strong>it</a> (haha sack), integrating AJAX functionality into Answerline has been pretty simple.  I&#8217;ve tried to follow the guidelines of <a href="http://www.onlinetools.org/articles/unobtrusivejavascript/">unobtrusive javascript</a>.  Lots of adding event handlers on page load, etc.  It&#8217;s worked out great, and allows the page to function in a limited capacity even without javascript.</p>
<p>There&#8217;s an animation of a sample workflow down at the bottom of the post.  Assuming the user has javascript the &#8220;Ticket Detail&#8221; button expands the ticket from the compressed first/last display to show all the comments on that ticket.  It also includes two sections at the bottom. On the left is a form for adding a comment, assigning the ticket, changing tier or closing the ticket.  The right side is the old email popup transformed and shrunk down.  Both of these will modify the ticket (emailing adds a comment w/ email body and pertinent details) and then in-place reload the ticket with the new information.  The animation shows adding a comment w/ no actual text.  This isn&#8217;t such a big deal any more, as per Nick&#8217;s idea the safe comments are now much more visible.  You can see the ticket reload itself to display the new comment, what may not be quite so obvious is that it also recalculates its border color and will redraw that depending on certain criteria.</p>
<p>So that begs the question, how does it work if a user has no javascript?  Ignoring the lack of in-place content reloads the answer is &#8220;remarkably similar to the javascript version&#8221;.  Hitting the Ticket Details button takes you to the Ticket Details page, which shows the same view as you see in the js version.  The main difference is you&#8217;ve moved pages and now you only see the one ticket.  Adding a comment will force a page reload, as will sending an email.  That&#8217;s it, this whole unobtrusive javascript thing makes adding failovers for non-js browsers retardedly easy.  As has been pointed out, I love XHTML 1.0 Strict and this page validates entirely.  There is no javascript in the actual page, it&#8217;s all stored in an external .js file, so the code stays clean and lovely.</p>
<table width='100%'>
<tr>
<td>
<h3>Old Answerline</h3>
</td>
<td>
<h3>New Answerline</h3>
</td>
</tr>
<tr>
<td><a href="/wp-content/old.png" style='border: 0;'><img src="/wp-content/thumb-old.png" alt="Old Answerline interface" /></a></td>
<td><a href="/wp-content/1.png" style='border: 0;'><img src="/wp-content/thumb-1.png" alt="New Answerline interface" /></a></td>
</tr>
</table>
<h2>Example of New Answerline Interactivity</h2>
<p><img src="/wp-content/newanswerline.gif" alt="Animated example of new Answerline interface" /></p>
]]></content:encoded>
			<wfw:commentRss>http://patcavit.com/2005/07/26/rethinking-answerline/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
