<?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>0xDECAFBAD &#187; mozilla</title>
	<atom:link href="http://decafbad.com/blog/tag/mozilla/feed" rel="self" type="application/rss+xml" />
	<link>http://decafbad.com/blog</link>
	<description>It's all spinning wheels and self-doubt until the first pot of coffee.</description>
	<lastBuildDate>Wed, 10 Mar 2010 18:26:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0-alpha</generator>
		<item>
		<title>HTML5 drag and drop in Firefox 3.5</title>
		<link>http://decafbad.com/blog/2009/07/15/html5-drag-and-drop</link>
		<comments>http://decafbad.com/blog/2009/07/15/html5-drag-and-drop#comments</comments>
		<pubDate>Thu, 16 Jul 2009 02:26:40 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[entries]]></category>
		<category><![CDATA[dhtml]]></category>
		<category><![CDATA[draganddrop]]></category>
		<category><![CDATA[eventdelegation]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[outliners]]></category>
		<category><![CDATA[outlining]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1793</guid>
		<description><![CDATA[
Oh hey, look! It&#8217;s another blog post—and this one
is cross-posted on hacks.mozilla.com.
I won&#8217;t say this is the start of a renewed blogging habit, but let&#8217;s see what happens.



dl { margin-left: 2em; }
dd { margin-left: 2em; margin-bottom: 0.25em; }



    
        Drag and drop is one of [...]]]></description>
			<content:encoded><![CDATA[<p><i>
Oh hey, look! It&#8217;s another blog post—and this one
<a href="http://hacks.mozilla.org/2009/07/html5-drag-and-drop/">is cross-posted on hacks.mozilla.com</a>.
I won&#8217;t say this is the start of a renewed blogging habit, but let&#8217;s see what happens.
</i></p>

<p><style type="text/css">
dl { margin-left: 2em; }
dd { margin-left: 2em; margin-bottom: 0.25em; }
</style></p>

<div id="introduction">
    <p>
        Drag and drop is one of the most fundamental interactions
        afforded by graphical user interfaces.  In one gesture, it
        allows users to pair the selection of an object with the
        execution of an action, often including a second object in the
        operation.  It&#8217;s a simple yet powerful UI concept used to
        support copying, list reordering, deletion (ala the Trash / Recycle Bin),
        and even the creation of link relationships.
    </p><p>
        Since it&#8217;s so fundamental, offering drag and drop in web
        applications has been a no-brainer ever since browsers first
        offered mouse events in DHTML.  But, although
        <code>mousedown</code>, <code>mousemove</code>, and
        <code>mouseup</code> made it possible, the implementation has been
        limited to the bounds of the browser window.  Additionally,
        since these events refer only to the object being dragged,
        there&#8217;s a challenge to find the subject of the drop when
        the interaction is completed.
    </p><p>

        Of course, that doesn&#8217;t prevent most modern JavaScript
        frameworks from abstracting away most of the problems and
        throwing in some flourishes while they&#8217;re at it.  But, wouldn&#8217;t
        it be nice if browsers offered first-class support for drag and
        drop, and maybe even extended it beyond the window sandbox?
    </p><p>
        As it turns out, this very wish is answered by the HTML 5 specification 
        <a target="_new" href="http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#dnd">section on new drag-and-drop events</a>, and 
        <a target="_new" href="https://developer.mozilla.org/En/DragDrop/Drag_and_Drop">Firefox 3.5 includes an implementation</a> of those events.
    </p><p>
        If you want to jump straight to the code, I&#8217;ve put together 
        <a target="_new" target="_new" target="_new" href="http://decafbad.com/2009/07/drag-and-drop/api-demos.html">some simple demos</a> 
        of the new events.  
    </p><p>

        I&#8217;ve even scratched an itch of my own and
        built <a target="_new" target="_new" target="_new" href="http://decafbad.com/2009/07/drag-and-drop/outline.html">the beginnings of an outline editor</a>,
        where every draggable element is also a drop target—of which
        there could be dozens to hundreds in a complex document, something
        that gave me some minor hair-tearing moments in the past
        while trying to make do with plain old mouse events.
    </p><p>
        And, all the above can be downloaded or cloned from 
        <a href="http://github.com/lmorchard/fx35-drag-and-drop">a GitHub repository</a>
        I&#8217;ve created especially for this article—which continues after the jump.
    </p>
</div>

<p><span id="more-1793"></span></p>

<div id="events">

    <h2>The New Drag and Drop Events</h2>
    <p>
        So, with no further ado, here are the new drag and drop events,
        in roughly the order you might expect to see them fired:
    </p>
    <dl>
        <dt><code>dragstart</code></dt>
        <dd>
            A drag has been initiated, with the dragged element as the
            event target.
        </dd>

        <dt><code>drag</code></dt>
        <dd>
            The mouse has moved, with the dragged element as the event target.
        </dd>
        <dt><code>dragenter</code></dt>
        <dd>
            The dragged element has been moved into a drop listener,
            with the drop listener element as the event target.
        </dd>
        <dt><code>dragover</code></dt>

        <dd>
            The dragged element has been moved over a drop listener,
            with the drop listener element as the event target.  Since
            the default behavior is to cancel drops, returning
            <code>false</code> or calling <code>preventDefault()</code> in
            the event handler indicates that a drop is allowed here.
        </dd>
        <dt><code>dragleave</code></dt>
        <dd>
            The dragged element has been moved out of a drop listener,
            with the drop listener element as the event target.
        </dd>

        <dt><code>drop</code></dt>
        <dd>
            The dragged element has been successfully dropped on a drop
            listener, with the drop listener element as the event
            target.
        </dd>
        <dt><code>dragend</code></dt>
        <dd>
            A drag has been ended, successfully or not, with the
            dragged element as the event target.
        </dd>
    </dl>

    <p>
        Like the mouse events of yore, listeners can be attached to
        elements using <code>addEventListener()</code> 
        directly or by way of your favorite JS library.  
    </p><p>
        Consider the following example using jQuery, 
        <a target="_new" target="_new" target="_new" href="http://decafbad.com/2009/07/drag-and-drop/api-demos.html#newschool">also available as a live demo</a>:
    </p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">&lt;div id=&quot;newschool&quot;&gt;
    &lt;div class=&quot;dragme&quot;&gt;Drag me!&lt;/div&gt;
    &lt;div class=&quot;drophere&quot;&gt;Drop here!&lt;/div&gt;
&lt;/div&gt;
&nbsp;
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
    $<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#newschool .dragme'</span><span style="color: #009900;">&#41;</span>
            .<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'draggable'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'true'</span><span style="color: #009900;">&#41;</span>
            .<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'dragstart'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ev<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #003366; font-weight: bold;">var</span> dt <span style="color: #339933;">=</span> ev.<span style="color: #660066;">originalEvent</span>.<span style="color: #660066;">dataTransfer</span><span style="color: #339933;">;</span>
                dt.<span style="color: #660066;">setData</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Text&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;Dropped in zone!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
            .<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'dragend'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ev<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#newschool .drophere'</span><span style="color: #009900;">&#41;</span>
            .<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'dragenter'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ev<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                $<span style="color: #009900;">&#40;</span>ev.<span style="color: #660066;">target</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">addClass</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'dragover'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
            .<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'dragleave'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ev<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                $<span style="color: #009900;">&#40;</span>ev.<span style="color: #660066;">target</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">removeClass</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'dragover'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
            .<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'dragover'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ev<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
            .<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'drop'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ev<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #003366; font-weight: bold;">var</span> dt <span style="color: #339933;">=</span> ev.<span style="color: #660066;">originalEvent</span>.<span style="color: #660066;">dataTransfer</span><span style="color: #339933;">;</span>
                <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>dt.<span style="color: #660066;">getData</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Text'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></td></tr></table></div>



    <p>
        Thanks to the new events and jQuery, this example is both short
        and simple—but it packs in a lot of functionality, as the rest
        of this article will explain.  
    </p><p>
        Before moving on, there are at least three things about the above
        code that are worth mentioning:
    </p>
    <ul>
        <li>

            <p>
                Drop targets are enabled by virtue of having
                listeners for drop events.  But, 
                <a target="_new" href="http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#drag-and-drop-processing-model">per the HTML 5 spec</a>,
                draggable elements need an
                attribute of <code>draggable="true"</code>, set either in
                markup or in JavaScript.  
            </p>
            <p>
                Thus, <code>$('#newschool&nbsp;.dragme').attr('draggable', 'true')</code>.
            </p>

        </li>
        <li>
            <p>
                The original DOM event (as opposed to jQuery&#8217;s event
                wrapper) offers a property called <code>dataTransfer</code>.
                Beyond just manipulating elements, the new drag and drop
                events accomodate the transmission of user-definable data
                during the course of the interaction.  
            </p>
        </li>
        <li>
            <p>

                Since these are first-class events, you can apply 
                <a target="_new" href="http://icant.co.uk/sandbox/eventdelegation/">the technique of Event Delegation</a>.
            </p><p>
                What&#8217;s that?  Well, imagine you have a list of 1000
                list items—as part of a deeply-nested outline document,
                for instance.  Rather than needing to attach listeners
                or otherwise fiddle with all 1000 items, simply attach
                a listener to the parent node (eg. the
                <code><ul></ul></code> element) and all events from
                the children will propagate up to the single parent listener.
                As a bonus, all new child elements added after page
                load will enjoy the same benefits.
            </p><p>
                <a target="_new" target="_new" target="_new" href="http://decafbad.com/2009/07/drag-and-drop/api-demos.html#delegated">Check out this demo</a>, 
                and 
                <a target="_new" target="_new" href="http://decafbad.com/2009/07/drag-and-drop/js/drag-delegated.js">the associated JS code</a> 
                to see more about these events and Event Delegation.
            </p>

        </li>
    </ul>
</div>

<div id="datatransfer">
    <h2>Using dataTransfer</h2>
    <p>
        As mentioned in the last section, the new drag and drop events
        let you send data along with a dragged element.  But, it&#8217;s even
        better than that:  Your drop targets can receive data
        transferred by content objects dragged into the window from 
        other browser windows, and even <i>other applications</i>.
    </p><p>

        Since the example is a bit longer,  
        <a target="_new" target="_new" href="http://decafbad.com/2009/07/drag-and-drop/api-demos.html#data_transfer">check out the live demo</a>
        and 
        <a target="_new" href="http://decafbad.com/2009/07/drag-and-drop/js/drag-datatransfer.js">associated code</a>
        to get an idea of what&#8217;s possible with <code>dataTransfer</code>.
    </p><p>
        In a nutshell, the stars of this show are the
        <code>setData()</code> and <code>getData()</code> methods of
        the <code>dataTransfer</code> property exposed by the Event object.
    </p>

    <p>
        The <code>setData()</code> method is typically called in the 
        <code>dragstart</code> listener, loading <code>dataTransfer</code>
        up with one or more strings of content with associated
        <a href="https://developer.mozilla.org/En/DragDrop/Recommended_Drag_Types#link">recommended content types</a>.
    </p>

    <p>
        For illustration, here&#8217;s a quick snippet from the example code:
    </p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> dt <span style="color: #339933;">=</span> ev.<span style="color: #660066;">originalEvent</span>.<span style="color: #660066;">dataTransfer</span><span style="color: #339933;">;</span>    
dt.<span style="color: #660066;">setData</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'text/plain'</span><span style="color: #339933;">,</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#logo'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">parent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
dt.<span style="color: #660066;">setData</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'text/html'</span><span style="color: #339933;">,</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#logo'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">parent</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
dt.<span style="color: #660066;">setData</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'text/uri-list'</span><span style="color: #339933;">,</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#logo'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">src</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>



    <p>
        On the other end, <code>getData()</code> allows you to query
        for content by type (eg. <code>text/html</code> followed by
        <code>text/plain</code>).  This, in turn, allows you to decide
        on acceptable content types at the time of the
        <code>drop</code> event or even during <code>dragover</code>

        to offer feedback for unacceptable types during the drag.
    </p><p>
        Here&#8217;s another example from the receiving end of the example code:
    </p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> dt <span style="color: #339933;">=</span> ev.<span style="color: #660066;">originalEvent</span>.<span style="color: #660066;">dataTransfer</span><span style="color: #339933;">;</span>    
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.content_url .content'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>dt.<span style="color: #660066;">getData</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'text/uri-list'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.content_text .content'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>dt.<span style="color: #660066;">getData</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'text/plain'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.content_html .content'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>dt.<span style="color: #660066;">getData</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'text/html'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>



    <p>
        Where <code>dataTransfer</code> really shines, though, is that
        it allows your drop targets to receive content from 
        sources outside your defined draggable elements and even from
        outside the browser altogether.  Firefox accepts such drags, 
        and attempts to populate <code>dataTransfer</code> with
        appropriate content types extracted from the external object.
    </p><p>

        Thus, you could select some text in a word processor window and
        drop it into one of your elements, and at least expect to find
        it available as <code>text/plain</code> content.  
    </p><p>
        You can also select content in 
        another browser window, and expect to see <code>text/html</code>
        appear in your events.  Check out the 
        <a target="_new" href="http://decafbad.com/2009/07/drag-and-drop/outline.html">outline editing demo</a>
        and see what happens when you try dragging various elements 
        (eg. images, tables, and lists) and highlighted content from
        other windows onto the items there.
    </p>

</div>

<div id="dragfeedback">
    <h2>Using Drag Feedback Images</h2>
    <p>
       An important aspect of the drag and drop interaction is a
       representation of the thing being dragged.  By default in
       Firefox, this is a &#8220;ghost&#8221; image of the dragged element itself.  But,
       the <code>dataTransfer</code> property of the original Event
       object exposes the method <code>setDragImage()</code> for use
       in customizing this representation.
    </p><p>

        There&#8217;s
        <a target="_new" href="http://decafbad.com/2009/07/drag-and-drop/api-demos.html#feedback_image">a live demo</a> of this feature, as well as
        <a target="_new" href="http://decafbad.com/2009/07/drag-and-drop/js/drag-feedback-images.js">associated JS code</a> 
        available.  The gist, however, is sketched out in these code snippets:
    </p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> dt <span style="color: #339933;">=</span> ev.<span style="color: #660066;">originalEvent</span>.<span style="color: #660066;">dataTransfer</span><span style="color: #339933;">;</span>    
&nbsp;
dt.<span style="color: #660066;">setDragImage</span><span style="color: #009900;">&#40;</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#feedback_image h2'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
dt.<span style="color: #660066;">setDragImage</span><span style="color: #009900;">&#40;</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#logo'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">32</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">32</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> canvas <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;canvas&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
canvas.<span style="color: #660066;">width</span> <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">height</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">50</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> ctx <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;2d&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
ctx.<span style="color: #660066;">lineWidth</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">8</span><span style="color: #339933;">;</span>
ctx.<span style="color: #660066;">moveTo</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">25</span><span style="color: #339933;">,</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
ctx.<span style="color: #660066;">lineTo</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">50</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">50</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
ctx.<span style="color: #660066;">lineTo</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">50</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
ctx.<span style="color: #660066;">lineTo</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">25</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
ctx.<span style="color: #660066;">stroke</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
dt.<span style="color: #660066;">setDragImage</span><span style="color: #009900;">&#40;</span>canvas<span style="color: #339933;">,</span> <span style="color: #CC0000;">25</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">25</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>



    <p>
        You can supply a DOM node as the first parameter to 
        <code>setDragImage()</code>, which includes everything from
        text to images to <code>canvas</code> elements.  The
        second two parameters indicate at what left and top offset
        the mouse should appear in the image while dragging.
    </p><p>

        For example, since the <code>#logo</code> image is 64&#215;64,
        the parameters in the second <code>setDragImage()</code>
        method places the mouse right in the center of the image.
        On the other hand, the first call positions the feedback
        image such that the mouse rests in the upper left corner.
    </p><p>
    </p>
</div>

<div id="dragfeedback">

    <h2>Using Drop Effects</h2>
    <p>
        As mentioned at the start of this article, the drag and drop
        interaction has been used to support actions such as copying,
        moving, and linking.  Accordingly, the HTML 5 specification 
        accomodates these operations in the form of the 
        <code>effectAllowed</code> and <code>dropEffect</code>
        properties exposed by the Event object.
    </p>
    <p>

        For a quick fix, check out the
        <a target="_new" href="http://decafbad.com/2009/07/drag-and-drop/api-demos.html#drag_effects">a live demo</a> 
        of this feature, as well as the
        <a target="_new" href="http://decafbad.com/2009/07/drag-and-drop/js/drag-effects.js">associated JS code</a>.
    </p><p>
        The basic idea is that the <code>dragstart</code> event
        listener can set a value for <code>effectAllowed</code> like so:
    </p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> dt <span style="color: #339933;">=</span> ev.<span style="color: #660066;">originalEvent</span>.<span style="color: #660066;">dataTransfer</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">switch</span> <span style="color: #009900;">&#40;</span>ev.<span style="color: #660066;">target</span>.<span style="color: #660066;">id</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'effectdrag0'</span><span style="color: #339933;">:</span> dt.<span style="color: #660066;">effectAllowed</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'copy'</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'effectdrag1'</span><span style="color: #339933;">:</span> dt.<span style="color: #660066;">effectAllowed</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'move'</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'effectdrag2'</span><span style="color: #339933;">:</span> dt.<span style="color: #660066;">effectAllowed</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'link'</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'effectdrag3'</span><span style="color: #339933;">:</span> dt.<span style="color: #660066;">effectAllowed</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'all'</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'effectdrag4'</span><span style="color: #339933;">:</span> dt.<span style="color: #660066;">effectAllowed</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'none'</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



    <p>The choices available for this property include the following:</p>
    <dl> 
        <dt><code>none</code></dt><dd>no operation is permitted </dd>
        <dt><code>copy</code></dt><dd>copy only </dd>

        <dt><code>move</code></dt><dd>move only </dd>
        <dt><code>link</code></dt><dd>link only </dd>
        <dt><code>copyMove</code></dt><dd>copy or move only </dd>
        <dt><code>copyLink</code></dt><dd>copy or link only </dd>
        <dt><code>linkMove</code></dt><dd>link or move only </dd>

        <dt><code>all</code></dt><dd>copy, move, or link </dd>
    </dl>
    <p>
        On the other end, the <code>dragover</code> event listener 
        can set the value of the
        <code>dropEffect</code> property to indicate the expected effect
        invoked on a successful drop.  If the value does
        not match up with <code>effectAllowed</code>, the drop will
        be considered cancelled on completion.
    </p><p>

        In the 
        <a target="_new" href="http://decafbad.com/2009/07/drag-and-drop/api-demos.html#drag_effects">a live demo</a>,
        you should be able to see that only elements with matching
        effects can be dropped into the appropriate drop zones.  This
        is accomplished with code like the following:
    </p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> dt <span style="color: #339933;">=</span> ev.<span style="color: #660066;">originalEvent</span>.<span style="color: #660066;">dataTransfer</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">switch</span> <span style="color: #009900;">&#40;</span>ev.<span style="color: #660066;">target</span>.<span style="color: #660066;">id</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'effectdrop0'</span><span style="color: #339933;">:</span> dt.<span style="color: #660066;">dropEffect</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'copy'</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'effectdrop1'</span><span style="color: #339933;">:</span> dt.<span style="color: #660066;">dropEffect</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'move'</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'effectdrop2'</span><span style="color: #339933;">:</span> dt.<span style="color: #660066;">dropEffect</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'link'</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'effectdrop3'</span><span style="color: #339933;">:</span> dt.<span style="color: #660066;">dropEffect</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'all'</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">case</span> <span style="color: #3366CC;">'effectdrop4'</span><span style="color: #339933;">:</span> dt.<span style="color: #660066;">dropEffect</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'none'</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">break</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>



    <p>
        Although the OS itself can provide some feedback, you 
        can also use these properties to update your own visible 
        feedback, both on the dragged element and on the drop zone
        itself.
    </p>

</div>

<div id="conclusion">
    <h2>Conclusion</h2>
    <p>
        The new first-class drag and drop events in HTML5 and Firefox
        make supporting this form of UI interaction simple, concise,
        and powerful in the browser.  But beyond the new simplicity of
        these events, the ability to transfer content between
        applications opens brand new avenues for web-based applications
        and collaboration with desktop software in general.
    </p><p>
    </p><p>
    </p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2009/07/15/html5-drag-and-drop/feed</wfw:commentRss>
		<slash:comments>62</slash:comments>
		</item>
		<item>
		<title>7 facts about me</title>
		<link>http://decafbad.com/blog/2009/01/23/7-facts-about-me</link>
		<comments>http://decafbad.com/blog/2009/01/23/7-facts-about-me#comments</comments>
		<pubDate>Fri, 23 Jan 2009 16:59:54 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[entries]]></category>
		<category><![CDATA[7things]]></category>
		<category><![CDATA[memes]]></category>
		<category><![CDATA[mozilla]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1699</guid>
		<description><![CDATA[So, it finally happened—I&#8217;ve been tagged by Stephen Donner.  I&#8217;ve not been one to follow memes in this blog, but this one&#8217;s been going around the Mozillasphere for awhile now and has been kind of interesting.  I&#8217;m half-tempted to bookmark and tag all the entries I&#8217;ve caught so far.  Anyway, the rules:


Link [...]]]></description>
			<content:encoded><![CDATA[<p>So, it finally happened—<a href="http://weblogs.mozillazine.org/stephend/archives/2009/01/7_facts_about_s.html">I&#8217;ve been tagged by Stephen Donner</a>.  I&#8217;ve not been one to follow memes in this blog, but this one&#8217;s been going around the <a href="http://planet.mozilla.org/">Mozillasphere</a> for awhile now and has been kind of interesting.  I&#8217;m half-tempted to bookmark and tag all the entries I&#8217;ve caught so far.  Anyway, the rules:</p>

<ol>
<li><a href="http://weblogs.mozillazine.org/stephend/archives/2009/01/7_facts_about_s.html">Link to your original tagger(s)</a> and list these rules in your post.</li>
<li>Share seven facts about yourself in the post.</li>
<li><strike>Tag seven people at the end of your post by leaving their names and the links to their blogs.</strike></li>
<li><strike>Let them know they’ve been tagged.</strike></li>
</ol>

<p>Now, for your random facts, after the jump:</p>

<p><span id="more-1699"></span></p>

<ol>
<li>My wife is a nerd, who tracked me down via a user name shown in the webcam picture I used for my Yahoo! Personals ad, in order to avoid paying to reply.  <a href="http://deus-x.livejournal.com/91013.html" title="An old entry on LiveJournal, only a few dates in with my now-wife.">Dial-up BBSes and DOOR games played a part in our courtship</a>.</li>
<li>We have <a href="http://en.wikipedia.org/wiki/Ocicat">two ocicats</a>, littermates named <a href="http://en.wikipedia.org/wiki/Puck_(mythology)">Puck</a> and <a href="http://en.wikipedia.org/wiki/Inanna">Inanna</a>.  They&#8217;re both <a href="http://www.flickr.com/photos/deusx/60975345/in/set-1316941/" title="Look at these cute kitties.">very cute</a> and are <a href="http://www.flickr.com/photos/deusx/60976282/in/set-1316941/" title="Look at these awesome cats.">more awesome</a> than anyone else&#8217;s cats. </li>
<li>I have <a href="http://www.sleepapnea.org/">sleep apnea</a>, and use <a href="http://en.wikipedia.org/wiki/Positive_airway_pressure">a CPAP machine</a> every night.  <a href="http://decafbad.com/blog/2004/12/03/if-you-snore-get-tested-for-sleep-apnea-now" title="No, really, go get tested for sleep apnea if you snore.">If you snore, go get tested</a>.  Heart disease, <a href="http://decafbad.com/blog/2007/09/25/dad" title="RIP Dad.">of which my snoring father died</a>, is one of many possible consequences of untreated sleep apnea.</li>
<li><a href="http://decafbad.com/blog/2003/06/13/newly-digital" title="I was newly digital in 1983">Although I have been a computer nerd since the age of 7</a>, I had the wild notion in starting college that I wanted to be <a href="http://www.algonac.k12.mi.us/ahs/Newspaper/newspaper1.htm" title="I was production editor of my High School newspaper!">a journalist</a> or a psychologist.  Luckily, the web took off during my freshman year, which let me be a little of all the above.  <a href="http://decafbad.com/blog/colophon#growup" title="An explanation of that image at the bottom of the page.">I&#8217;m not sure why I ever thought I&#8217;d be anything other than a computer nerd</a>.</li>
<li>I&#8217;m <a href="http://www.theatlantic.com/doc/200303/rauch">a complete introvert</a> and though I work hard at being sociable, I need a day or two alone for every half-day or so spent being social.  My main coping mechanism since even before my teenage years was to make friends from behind a keyboard and screen, and the internet has made that even more scalable as I&#8217;ve grown up.  And now, I get to work that way too—HUGE SUCCESS!</li>
<li>In my senior year of High School, I won 2nd place in <a href="http://www.aynrand.org/site/PageServer?pagename=education_contests_tf">the Ayn Rand Institute&#8217;s <em>The Fountainhead</em> essay contest</a>.  This was the culmination of having read every scrap of Ayn Rand&#8217;s writing I could get my hands on throughout High School.  I used the money to take a summer trip to visit a friend who&#8217;d moved to Texas and to buy my <a href="http://decafbad.com/blog/2007/09/21/sadness-for-my-dead-palmtop">well used, now dead palmtop PC</a>.</li>
<li>I like extremely hot spicy food, insanely hop-saturated beer, Irish whiskey, and fresh locally roasted coffee.</li>
</ol>

<p><a href="http://blog.mozilla.com/bhearsum/archives/71">Per Ben Hearsum</a>, I think I&#8217;ll make this a leaf node in the meme spanning the <a href="http://planet.mozilla.org/">Mozillasphere</a>.  In a quick 5 minute search, it looks like most blogging Mozillans have already been tagged, and I&#8217;m not going to spread the contagion outside the organization.  :)</p>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2009/01/23/7-facts-about-me/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Enter the LizardFeeder</title>
		<link>http://decafbad.com/blog/2009/01/05/enter-the-lizardfeeder</link>
		<comments>http://decafbad.com/blog/2009/01/05/enter-the-lizardfeeder#comments</comments>
		<pubDate>Tue, 06 Jan 2009 00:01:54 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[entries]]></category>
		<category><![CDATA[activitystreams]]></category>
		<category><![CDATA[atom]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[lizardfeeder]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1533</guid>
		<description><![CDATA[Behind Firefox is Mozilla, and behind Mozilla is a community.  And the Mozilla community acts a lot like an ecosystem, which can be visualized as a kind of living tree—not to confused with the mozilla-central tree.  Oh yeah, and Mozilla is the name of both a Foundation and a Corporation.

Confused yet?  If [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_1582" class="wp-caption alignright" style="width: 257px"><a href="http://blog.lizardwrangler.com/2008/07/29/the-mozilla-tree/"><img src="http://decafbad.com/blog/wp-content/uploads/2009/01/moz-tree.jpg" alt="The Mozilla Tree" title="moz-tree" width="247" height="191" class="size-full wp-image-1582" /></a><p class="wp-caption-text">The Mozilla Tree</p></div>

<p>Behind Firefox is Mozilla, and behind Mozilla is a community.  And the Mozilla community acts a lot like an ecosystem, which can be visualized <a href="http://blog.lizardwrangler.com/2008/07/29/the-mozilla-tree/">as a kind of living tree</a>—not to confused with the <a href="https://developer.mozilla.org/en/mozilla-central">mozilla-central tree</a>.  Oh yeah, and Mozilla is the name of <a href="http://www.mozilla.org/reorganization/">both a Foundation and a Corporation</a>.</p>

<p>Confused yet?  If not, then we should talk so you can explain it to me, because it all looks pretty tangly and <a href="http://en.wikipedia.org/wiki/Intertwingularity">intertwingled</a> to me.  Nonetheless, it seems to work, and produces a good chunk of my favorite software and technologies.</p>

<p>There are many efforts to track what&#8217;s going on—including <a href="http://planet.mozilla.org/">planets</a> and <a href="http://blog.mozilla.com/about_mozilla/">newsletters</a> and <a href="https://bugzilla.mozilla.org/">bugzillas</a> and <a href="https://wiki.mozilla.org/WeeklyUpdates/2009-01-05">wikis</a> and <a href="http://hg.mozilla.org/">repositories</a> and <a href="http://tinderbox.mozilla.org/showbuilds.cgi?tree=Firefox">tinderboxen</a>.  Some of these resources report on, or are driven by, the activity occurring in the others.  Some are automated, and others are carefully stitched together by hand.  None offer a full picture of what&#8217;s going on in the <a href="http://ascher.ca/blog/2008/06/19/whats-mozillas-scope-what-should-it-be/">Mozilla galaxy</a> in a way that&#8217;s casually comprehensible by a sane human being.</p>

<p>Of course, that&#8217;s not a slight against any of these sites or the people maintaining them—extracting an overview from such an organic phenomenon is neither easy nor straightforward.  But, it might be fun to try.</p>

<p>As an infovore and avid practitioner of <a href="http://decafbad.com/blog/2005/09/23/the-zen-of-firehose-drinking">continuous partial attention</a>, my first impulse is to reach for a firehose and stick my head into the stream.  Relax, defocus, and try to let my pattern recognizers do their thing—sometimes those pattern recognizers are in my head, and <a href="http://decafbad.com/hgwebdir.cgi/hacking_rss_and_atom/file/f7a85b9fd48a/ch15_popular_links.py">sometimes they&#8217;re written in Python</a>.</p>

<div id="attachment_1585" class="wp-caption alignright" style="width: 235px"><a href="http://www.flickr.com/photos/intothefuzz/2571283860/in/set-72157605179678562/"><img src="http://decafbad.com/blog/wp-content/uploads/2009/01/robo-225x300.jpg" alt="Firefox Victory Robot" title="firefox-victory" width="225" height="300" class="size-medium wp-image-1585" /></a><p class="wp-caption-text">Firefox Victory!</p></div>

<p>But, for Mozilla, I couldn&#8217;t find a stream of sufficient volume or completeness to satisfy me or <a href="http://www.digitpress.com/dpsoundz/destroyhimrobots.wav">my robots</a>.  Happily, though, my feeding urge found itself aligned with a project to discover the patterns of contribution in the Mozilla community and to find a way to thank the contributors responsible.</p>

<p>So, while we&#8217;re still working on the thank-you angle, allow me to introduce you to <a href="http://feeds.mozilla.com/">the Lizardfeeder</a>.  The <a href="http://feeds.mozilla.com/">LizardFeeder</a> is a feed aggregator, <a href="https://svn.mozilla.org/projects/lizardfeeder/trunk/">whose source code</a> is built atop <a href="http://www.intertwingly.net/code/venus/">Sam Ruby&#8217;s Planet Venus</a>. The <a href="http://feeds.mozilla.com/">LizardFeeder</a> pulls together and archives activity streams from a wide variety of Mozilla community sources.  Beyond the usual human-readable pages produced by a <a href="http://planet.mozilla.org/">blog-gathering Planet</a>, the <a href="http://feeds.mozilla.com/">LizardFeeder</a> accumulates <a href="http://feeds.mozilla.com/archives/index.json">statistical and historical data</a> meant for consumption and analysis by robots.</p>

<p>At present, the only robot navigating the <a href="http://feeds.mozilla.com/">LizardFeeder</a> archives is an AJAX-ified user interface that animates the firehose as a near real-time or time-lapsed stream of events scrolling by.  </p>

<p>This is just meant as a conversation starter, though.  I&#8217;m hoping to <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=469838">gather feedback and find more sources</a>, as well as to entice creative community members to come up with more sophisticated visualizations of this data.  </p>

<p>So, take a look, <a href="http://feeds.mozilla.com/">check it out</a>, and let me know what you think!</p>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2009/01/05/enter-the-lizardfeeder/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
<enclosure url="http://www.digitpress.com/dpsoundz/destroyhimrobots.wav" length="27236" type="audio/x-wav" />
		</item>
		<item>
		<title>Improving my Delicious command for Ubiquity</title>
		<link>http://decafbad.com/blog/2008/09/07/improving-my-delicious-command-for-ubiquity</link>
		<comments>http://decafbad.com/blog/2008/09/07/improving-my-delicious-command-for-ubiquity#comments</comments>
		<pubDate>Sun, 07 Sep 2008 06:20:20 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[entries]]></category>
		<category><![CDATA[delicious]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[ubiquity]]></category>
		<category><![CDATA[web20]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1380</guid>
		<description><![CDATA[After writing up my first stab at a Delicious command for Ubiquity, I planned to continue revising it based on feedback and to work on exploring more of what Ubiquity enables.  I started looking into writing my own nouns for tag suggestions, as well as playing with page load and browser startup hooks.  [...]]]></description>
			<content:encoded><![CDATA[<p>After writing up my <a href="http://decafbad.com/blog/2008/09/01/writing-a-delicious-command-for-ubiquity">first stab at a Delicious command for Ubiquity</a>, I planned to continue revising it based on feedback and to work on exploring more of what Ubiquity enables.  I started looking into writing my own nouns for tag suggestions, as well as playing with page load and browser startup hooks.  And, I also started poking at a little bit of deeper extension development, which took up most of my time today.</p>

<p>I&#8217;ve <a href="http://decafbad.com/UbiquityCommands/">updated my UbiquityCommands</a> page and checked in my latest revision of <a href="http://decafbad.com/hgwebdir.cgi/UbiquityCommands/file/tip/delicious.ubiq.js">the Delicious command</a>.  </p>

<p>The main new feature is a status bar item reporting bookmarks for the current page:</p>

<p><img style="padding: 0.25em" src="http://decafbad.com/2008/ubiq-del-status.jpg" />&nbsp;<img style="padding: 0.25em" src="http://decafbad.com/2008/ubiq-del-tip.jpg" /></p>

<p>As you can see above, the command now comes with a status bar panel powered by the <a href="http://delicious.com/help/feeds">Delicious URL info JSON feed</a>, providing bookmarking info on every page visited.  It shows a bookmark count, a tooltip with further information, and sends the user to the URL info page on Delicious when clicked.  It mostly works, but it could use some looking at.  This is my first time really cracking open the hood on Firefox and XUL, and so I&#8217;m feeling around in the dark.</p>

<p>Specifically, I&#8217;m using Ubiquity&#8217;s page load hook—but I&#8217;m also trying to augment that by tracking tab selection events, in order to keep the status bar info updated for the active tab.  But then, that leads me to trying to track new windows, to attach the tab selection event handler for every newly opened window.  Or I could just be barking up the wrong tree entirely.  At any rate, the code is probably brain-dead dumb, so I hope someone can clue me into a better way.</p>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2008/09/07/improving-my-delicious-command-for-ubiquity/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Writing a Delicious command for Ubiquity</title>
		<link>http://decafbad.com/blog/2008/09/01/writing-a-delicious-command-for-ubiquity</link>
		<comments>http://decafbad.com/blog/2008/09/01/writing-a-delicious-command-for-ubiquity#comments</comments>
		<pubDate>Mon, 01 Sep 2008 05:37:03 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[entries]]></category>
		<category><![CDATA[delicious]]></category>
		<category><![CDATA[greasemonkey]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[ubiquity]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1310</guid>
		<description><![CDATA[In my last post, I got all fluffy about how cool Ubiquity is but didn&#8217;t share any code to prove the point.  As it happens, I have come up with at least one useful command that I&#8217;m starting to use habitually in posting bookmarks to Delicious.  You can subscribe to my command or [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://decafbad.com/blog/2008/08/31/ubiquity-cracks-open-personal-mashup-tinkering" title="Ubiquity cracks open personal mashup tinkering">last post</a>, I got all fluffy about how cool <a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a> is but didn&#8217;t share any code to prove the point.  As it happens, I have come up with at least one useful command that I&#8217;m starting to use habitually in posting bookmarks to Delicious.  You can <a href="http://decafbad.com/UbiquityCommands/">subscribe to my command</a> or <a href="http://decafbad.com/hg/UbiquityCommands/file/tip/delicious.ubiq.js">check out the full source</a>—this post will serve as a dissection of the thing.  Since this will be fairly lengthy, follow along after the jump.</p>

<p>Oh, and it&#8217;s been awhile since I posted something this in-depth around here, so feel free to let me know how this first draft works.  And, bug reports and patches are of course welcome.</p>

<p><span id="more-1310"></span></p>

<p>To begin, consider the following code starting off the command source code:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
 * share-on-delicious - an Ubiquity command for sharing bookmarks on
 * delicious.com
 *
 * l.m.orchard@pobox.com
 * http://decafbad.com/
 * Share and Enjoy!
 */</span>
<span style="color: #003366; font-weight: bold;">var</span> uext <span style="color: #339933;">=</span> Application.<span style="color: #660066;">extensions</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ubiquity@labs.mozilla.com'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> cookie_mgr <span style="color: #339933;">=</span> Components.<span style="color: #660066;">classes</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;@mozilla.org/cookiemanager;1&quot;</span><span style="color: #009900;">&#93;</span>
    .<span style="color: #660066;">getService</span><span style="color: #009900;">&#40;</span>Components.<span style="color: #660066;">interfaces</span>.<span style="color: #660066;">nsICookieManager</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>


<p>The first thing to note here is that a short header comment introduces the command.  This isn&#8217;t required, but it&#8217;s a good idea.  It&#8217;s also something you can&#8217;t really do with bookmarklets.  On the other hand, Greasemonkey user scripts expect metadata about the script to be provided here, but Ubiquity doesn&#8217;t use this convention.</p>

<p>Second, notice that the code accesses some chrome-level resources.  Again, this is something unavailable to bookmarklets and Greasemonkey user scripts.  Just take a look at the <a href="http://developer.mozilla.org/en/FUEL">FUEL library documentation</a> to get a quick sense of what&#8217;s available using that simplified API, not to mention what&#8217;s available using the lower-level browser APIs.</p>

<p>Now, check out this next chunk of code, which begins the construction of an Ubiquity command:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">CmdUtils.<span style="color: #660066;">CreateCommand</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000066;">name</span><span style="color: #339933;">:</span>        
        <span style="color: #3366CC;">'share-on-delicious'</span><span style="color: #339933;">,</span>
    icon<span style="color: #339933;">:</span>
        <span style="color: #3366CC;">'http://delicious.com/favicon.ico'</span><span style="color: #339933;">,</span>
    description<span style="color: #339933;">:</span> 
        <span style="color: #3366CC;">'Share the current page as a bookmark on delicious.com'</span><span style="color: #339933;">,</span>
    help<span style="color: #339933;">:</span>        
        <span style="color: #3366CC;">'Select text on the page to use as notes, or enter your own '</span> <span style="color: #339933;">+</span> 
        <span style="color: #3366CC;">'text after the command word.  You can also assign tags to the '</span><span style="color: #339933;">+</span> 
        <span style="color: #3366CC;">'bookmark with the &quot;tagged&quot; modifier, and alter the bookmark '</span> <span style="color: #339933;">+</span> 
        <span style="color: #3366CC;">'default page title with the &quot;entitled&quot; modifier.  Note that '</span> <span style="color: #339933;">+</span> 
        <span style="color: #3366CC;">'you must also already be logged in at delicious.com to use '</span> <span style="color: #339933;">+</span>
        <span style="color: #3366CC;">'this command.'</span><span style="color: #339933;">,</span>
&nbsp;
    homepage<span style="color: #339933;">:</span>   
        <span style="color: #3366CC;">'http://decafbad.com'</span><span style="color: #339933;">,</span>
    author<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span> 
        <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'Leslie Michael Orchard'</span><span style="color: #339933;">,</span> 
        email<span style="color: #339933;">:</span> <span style="color: #3366CC;">'l.m.orchard@pobox.com'</span> 
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    license<span style="color: #339933;">:</span>
        <span style="color: #3366CC;">'MPL/GPL/LGPL'</span><span style="color: #339933;">,</span></pre></td></tr></table></div>


<p>Whereas Greasemonkey scripts support metadata in the header comment, the Ubiquity command script API works a little differently.  </p>

<p>The <a href="http://hg.toolness.com/ubiquity-firefox/file/tip/ubiquity/chrome/content/cmdutils.js"><code>CmdUtils</code> module</a> provided by Ubiquity offers a <code>CreateCommand</code> function, which expects an object as a parameter.  The object literal whose construction is begun in the code above serves as a self-contained package for the command, bearing metadata describing the command as well as containing all the code necessary to implement it.</p>

<p>So, in the above code block, you can see the machine-readable description of the command—including a command name, display icon, home page URL, author information, and license.  The command name (<code>share-on-delicious</code>) will be used by the Ubiquity command parser, but the rest of the description will also be used in the list of commands available to the user, invoked by the <code>command-list</code> command, like so:</p>

<p><img src="/2008/ubiq-share-on-delicious-list.jpg" style="border: 1px solid #333; margin: 0.25em; padding: 0.25em" /></p>

<p>Moving along, this next chunk of code introduces the first functional bits of the command:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>37
38
39
40
41
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">    takes<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span> notes<span style="color: #339933;">:</span> noun_arb_text <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    modifiers<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span> 
        tagged<span style="color: #339933;">:</span>  noun_arb_text<span style="color: #339933;">,</span>
        entitled<span style="color: #339933;">:</span> noun_arb_text
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></td></tr></table></div>


<p>Like smart keyword shortcut bookmarks, Ubiquity commands accept user-supplied input.  But, what&#8217;s unique to Ubiquity is that it employs a parser whose goal is to support something approximating natural language.  At present, this results in commands that support a single primary argument—declared above with the <code>takes</code> property—and any number of additional keyword modifiers—declared above by the <code>modifiers</code> property.</p>

<p>For the command under construction here, this establishes a pattern something like the following:</p>

<pre><code>share-on-delicious {notes} [tagged {tags} entitled {title}]
</code></pre>

<p>Content for the <code>{notes}</code> argument can either be typed directly by hand, or it can be supplied by text highlighted on the page.  To use highlighted text, you can either issue the command alone, or use the word <code>this</code> for the <code>{notes}</code> argument before including further modifiers.</p>

<p>The modifiers <code>tagged</code> and <code>entitled</code> are optional, and can be used in any order.  Each of these keywords signifies the start of a different argument—which unfortunately can collide with the literal data supplied for notes, which will hopefully be a rare occurrence.</p>

<p>All of this adds up command invocations including the following:</p>

<pre><code>share-on-delicious
share-on-delicious I really like this page tagged nifty amusing
share-on-delicious this entitled This bookmark has no tags
sh this tagged osx software apple entitled This is good OS X software
</code></pre>

<p>That last example is important—since I have no other commands starting with &#8220;<code>sh</code>&#8220;, I can abbreviate the full command.  Ubiquity only requires enough of a command name to disambiguate it within your collection of commands.</p>

<p>Another thing to note is the use of the constant value <code>noun_arb_text</code>, which declares that these arguments should expect any arbitrary text as input.  </p>

<p>This facility is not exploited for the present command, but Ubiquity defines <a href="http://hg.toolness.com/ubiquity-firefox/file/tip/ubiquity/chrome/content/nlparser/en/nountypes.js">noun types</a>.  These include concepts such as plain text, dates, address book contacts, browser tabs, bookmark tags, and more.  You can define your own noun types, as well as implement suggestion schemes that help guide the user toward constructing useful input values in the command interface.  You can <a href="https://wiki.mozilla.org/Labs/Ubiquity/Ubiquity_0.1_Author_Tutorial#Introduction_to_Noun_Types">read more about this</a> in the official author tutorial.</p>

<p>Next up is a quick bit of command-specific configuration:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>42
43
44
45
46
47
48
49
50
51
52
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #006600; font-style: italic;">/**
     * Command configuration settings.
     */</span>
    _config<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// Base URL for the delicious v1 API</span>
        api_base<span style="color: #339933;">:</span>      <span style="color: #3366CC;">'https://api.del.icio.us'</span><span style="color: #339933;">,</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// Domain and name of the delicious login session cookie.</span>
        cookie_domain<span style="color: #339933;">:</span> <span style="color: #3366CC;">'.delicious.com'</span><span style="color: #339933;">,</span>
        cookie_name<span style="color: #339933;">:</span>   <span style="color: #3366CC;">'_user'</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></td></tr></table></div>


<p>Since this command will be posting to Delicious via the V1 API, it&#8217;s handy to declare the base URL for the API in an easily changed spot.  That way, you could change this value later on to point the command at another implementation of the API.</p>

<p>Additionally, this command will employ a little-known authentication trick supported by the Delicious API that accepts the user&#8217;s login cookie set by the Delicious website—this &#8220;cookie god&#8221; auth is used by the official Delicious addon for Firefox.  It&#8217;s handy for piggybacking on the website login and removing the need to ask the user for their username and password again and possibly storing it in an insecure manner.</p>

<p>In fact, this next chunk of code defines a utility method to rummage through the cookie jar:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>53
54
55
56
57
58
59
60
61
62
63
64
65
66
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #006600; font-style: italic;">/**
     * Dig up the Delicious login session cookie.
     */</span>
    _getUserCookie<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> iter <span style="color: #339933;">=</span> cookie_mgr.<span style="color: #660066;">enumerator</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>iter.<span style="color: #660066;">hasMoreElements</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003366; font-weight: bold;">var</span> cookie <span style="color: #339933;">=</span> iter.<span style="color: #660066;">getNext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> cookie <span style="color: #000066; font-weight: bold;">instanceof</span> Components.<span style="color: #660066;">interfaces</span>.<span style="color: #660066;">nsICookie</span> <span style="color: #339933;">&amp;&amp;</span> 
                cookie.<span style="color: #660066;">host</span>.<span style="color: #660066;">indexOf</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>._config.<span style="color: #660066;">cookie_domain</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span> <span style="color: #339933;">&amp;&amp;</span> 
                cookie.<span style="color: #000066;">name</span> <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">this</span>._config.<span style="color: #660066;">cookie_name</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">return</span> decodeURIComponent<span style="color: #009900;">&#40;</span>cookie.<span style="color: #660066;">value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></td></tr></table></div>


<p>The method defined above, <code>._getUserCookie()</code>, uses the browser&#8217;s cookie manager and the values defined in the previous configuration section to find the login session cookie set for Delicious.  Take note that this is far beyond the allowed capabilities of bookmarklets and Greasemoney user scripts—this is digging straight into the browser itself, skipping past the usual content-space security restrictions.  </p>

<p>In other words: In Ubiquity, <em>the gun is loaded</em> and you should be careful.  </p>

<p>Moving along, consider this next utility method:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #006600; font-style: italic;">/**
     * Given input data and modifiers, attempt to assemble data necessary to
     * post a bookmark.
     */</span>
    _extractBookmarkData<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>input_obj<span style="color: #339933;">,</span> mods<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#123;</span>
            _user<span style="color: #339933;">:</span>
                <span style="color: #000066; font-weight: bold;">this</span>._getUserCookie<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            url<span style="color: #339933;">:</span>
                context.<span style="color: #660066;">focusedWindow</span>.<span style="color: #660066;">location</span><span style="color: #339933;">,</span>
            description<span style="color: #339933;">:</span>
                mods.<span style="color: #660066;">entitled</span>.<span style="color: #660066;">text</span> <span style="color: #339933;">||</span> context.<span style="color: #660066;">focusedWindow</span>.<span style="color: #660066;">document</span>.<span style="color: #660066;">title</span><span style="color: #339933;">,</span>
            extended<span style="color: #339933;">:</span> 
                input_obj.<span style="color: #660066;">text</span><span style="color: #339933;">,</span>
            tags<span style="color: #339933;">:</span>
                mods.<span style="color: #660066;">tagged</span>.<span style="color: #660066;">text</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></td></tr></table></div>


<p>Named <code>._extractBookmarkData()</code>, this utility method accepts the results of Ubiquity&#8217;s parser interpreting the primary argument and modifier arguments supplied by the user.  Using these data structures, it attempts to build a structure representing the fields of a Delicious bookmark.</p>

<p>The <code>_user</code> field is used for authentication via the site login cookie.  The <code>url</code> is set from the location bar of the current page.  The <code>description</code>, or title, field of the bookmark is taken from either the <code>entitled</code> modifier or the title of the current page.  The <code>tags</code>, if any, come from the <code>tagged</code> modifier.  And, finally, the <code>extended</code> notes for the bookmark are taken from the primary input argument of the command.</p>

<p>As you&#8217;ll see shortly, this utility method will be used in both the preview and the execution of the command.</p>

<p>Next, there&#8217;s one more utility method to cover:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>85
86
87
88
89
90
91
92
93
94
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #006600; font-style: italic;">/**
     * Given an object, build a URL query string
     */</span>
    _buildQueryString<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> qs <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>k <span style="color: #000066; font-weight: bold;">in</span> data<span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#91;</span>k<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> 
            qs.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span> encodeURIComponent<span style="color: #009900;">&#40;</span>k<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'='</span> <span style="color: #339933;">+</span> 
                encodeURIComponent<span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#91;</span>k<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> qs.<span style="color: #660066;">join</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&amp;'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></td></tr></table></div>


<p>In anticipation of using the Delicious V1 API, the <code>._buildQueryString()</code> method accepts an object and constructs a URL query string from the encoded properties of the object.  This will be paired with the <code>._extractBookmarkData()</code> method to supply data for API calls.</p>

<p>Moving along, it&#8217;s time to start digging into the meat of this Ubiquity command:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>95
96
97
98
99
100
101
102
103
104
105
106
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #006600; font-style: italic;">/**
     * Present a preview of the bookmark under construction during the course
     * of composing the command.
     */</span>
    preview<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>pblock<span style="color: #339933;">,</span> input_obj<span style="color: #339933;">,</span> mods<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">var</span> bm          <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>._extractBookmarkData<span style="color: #009900;">&#40;</span>input_obj<span style="color: #339933;">,</span> mods<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> user_cookie <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>._getUserCookie<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> user_name   <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>user_cookie<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> user_cookie.<span style="color: #660066;">split</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">' '</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">var</span> ns <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> user_name<span style="color: #339933;">:</span> user_name<span style="color: #339933;">,</span> bm<span style="color: #339933;">:</span> bm <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> tmpl<span style="color: #339933;">;</span></pre></td></tr></table></div>


<p>With this code, the implementation of command method <code>.preview()</code> has begun.  This method is used by Ubiquity to generate a live preview of the command.  Called with a DOM node (<code>pblock</code>) and partially completed command input (<code>input_obj</code> and <code>mods</code>), this method is expected to build a representation of the command&#8217;s results in the DOM node.  As the user types, this method will be called over and over again, ideally offering feedback as the user composes a command.</p>

<p>Continuing on, consider this next chunk of code checking the validity of command input:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>user_name<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// If there's no user name, there's no login, so this command won't work. </span>
            tmpl <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span> 
                <span style="color: #3366CC;">'&lt;p style=&quot;color: #d44&quot;&gt;No active user found - log in at '</span><span style="color: #339933;">,</span> 
                <span style="color: #3366CC;">'&lt;img src=&quot;http://delicious.com/favicon.ico&quot;&gt; '</span><span style="color: #339933;">,</span>
                <span style="color: #3366CC;">'&lt;b&gt;&lt;a style=&quot;color: #3774D0&quot; href=&quot;http://delicious.com&quot;&gt;delicious.com&lt;/a&gt;&lt;/b&gt; '</span><span style="color: #339933;">,</span> 
                <span style="color: #3366CC;">'to use this command.&lt;/p&gt;'</span>
            <span style="color: #009900;">&#93;</span>.<span style="color: #660066;">join</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>bm.<span style="color: #660066;">description</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// If there's no title, then this is an error too.</span>
            tmpl <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span> 
                <span style="color: #3366CC;">'&lt;p style=&quot;color: #d44&quot;&gt;A title is required for bookmarks on '</span><span style="color: #339933;">,</span> 
                <span style="color: #3366CC;">'&lt;img src=&quot;http://delicious.com/favicon.ico&quot;&gt; '</span><span style="color: #339933;">,</span>
                <span style="color: #3366CC;">'&lt;b&gt;&lt;a style=&quot;color: #3774D0&quot; href=&quot;http://delicious.com&quot;&gt;delicious.com&lt;/a&gt;&lt;/b&gt; '</span><span style="color: #339933;">,</span> 
                <span style="color: #3366CC;">'&lt;/p&gt;'</span>
            <span style="color: #009900;">&#93;</span>.<span style="color: #660066;">join</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>


<p>This chunk of code first checks for a user name, which can be extracted from a valid Delicious login cookie, if one was found.  If not found, the command will fail—so the preview built here will instruct the user to login at Delicious before going further.</p>

<p>The second precondition for using the command is that the bookmark has been given a title.  By default, this is the title of the current page—but, some pages don&#8217;t offer titles.  So, an error needs to be flagged if the user hasn&#8217;t manually supplied a title in this case.</p>

<p>Finally, notice in both of these error cases, a string of HTML is composed in the variable <code>tmpl</code>.  This will be used at the end of the method to populate the DOM node passed in as <code>pblock</code>.</p>

<p>Now, assuming that all the command&#8217;s prerequisites have been met, it&#8217;s time to try constructing a proper preview for the results of this command:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">        <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
&nbsp;
            <span style="color: #006600; font-style: italic;">// Attempt to construct a vaguely delicious-esque preview of a bookmark.</span>
            tmpl <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span> 
                <span style="color: #3366CC;">'&lt;style type=&quot;text/css&quot;&gt;'</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">'.preview a { color: #3774D0 }'</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">'.del-bookmark { font: 12px arial; color: #ddd; background: #eee; line-height: 1.25em }'</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">'.del-bookmark a.title { color: #1259C7 }'</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">'.del-bookmark .full-url { color: #396C9B; font-size: 12px; display: block; padding: 0.25em 0 }'</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">'.del-bookmark .notes { color: #4D4D4D }'</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">'.del-bookmark .tags { color: #787878; padding-top: 0.25em; text-align: right }'</span><span style="color: #339933;">,</span>
                <span style="color: #3366CC;">'&lt;/style&gt;'</span><span style="color: #339933;">,</span>
                <span style="color: #3366CC;">'&lt;div class=&quot;preview&quot;&gt;'</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">'&lt;p&gt;Share a bookmark at &lt;img src=&quot;http://delicious.com/favicon.ico&quot;&gt; '</span><span style="color: #339933;">,</span>
                        <span style="color: #3366CC;">'&lt;b&gt;&lt;a href=&quot;http://delicious.com/${user_name}&quot;&gt;delicious.com/${user_name}&lt;/a&gt;&lt;/b&gt;:&lt;/p&gt;'</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">'&lt;div class=&quot;del-bookmark&quot;&gt;'</span><span style="color: #339933;">,</span>
                        <span style="color: #3366CC;">'&lt;div style=&quot;padding: 1em;&quot;&gt;'</span><span style="color: #339933;">,</span>
                        <span style="color: #3366CC;">'&lt;a class=&quot;title&quot; href=&quot;${bm.url}&quot;&gt;${bm.description}&lt;/a&gt;'</span><span style="color: #339933;">,</span>
                        <span style="color: #3366CC;">'&lt;a class=&quot;full-url&quot; href=&quot;${bm.url}&quot;&gt;${bm.url}&lt;/a&gt;'</span><span style="color: #339933;">,</span>
                        bm.<span style="color: #660066;">extended</span> <span style="color: #339933;">?</span> 
                            <span style="color: #3366CC;">'&lt;div class=&quot;notes&quot;&gt;${bm.extended}&lt;/div&gt;'</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">,</span>
                        bm.<span style="color: #660066;">tags</span> <span style="color: #339933;">?</span>
                            <span style="color: #3366CC;">'&lt;div class=&quot;tags&quot;&gt;&lt;span&gt;tags:&lt;/span&gt; ${bm.tags}&lt;/div&gt;'</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">'&lt;/div&gt;'</span><span style="color: #339933;">,</span>
                <span style="color: #3366CC;">'&lt;/div&gt;'</span>
            <span style="color: #009900;">&#93;</span>.<span style="color: #660066;">join</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #009900;">&#125;</span>
&nbsp;
        pblock.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> CmdUtils.<span style="color: #660066;">renderTemplate</span><span style="color: #009900;">&#40;</span>tmpl<span style="color: #339933;">,</span> ns<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></td></tr></table></div>


<p>Building on the notion that previews are built in a DOM node, the code above uses both CSS and HTML to assemble a quick-and-dirty facsimile of a Delicious bookmark—which will be rendered like this:</p>

<p><img src="/2008/ubiq-share-on-delicious-preview.jpg" style="border: 1px solid #333; margin: 0.25em; padding: 0.25em" /></p>

<p>Also note that Ubiquity provides a template engine for use in generating content—namely the <a href="http://code.google.com/p/trimpath/wiki/JavaScriptTemplates">JavaScript Templates</a> engine from the <a href="http://code.google.com/p/trimpath/wiki/TrimPath">TrimPath</a> project.  This engine may eventually be replaced with another, but the notion is that Ubiquity will provide tools to more easily generate previews and more.</p>

<p>The conclusion of the <code>.preview()</code> method uses the template engine with a call to <code>CmdUtils.renderTemplate()</code> to inject content into the preview element by way of the <code>.innerHTML</code> property.</p>

<p>Now that the preview is out of the way, it&#8217;s time to get down to implementing the execution of the command:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #006600; font-style: italic;">/**
     * Attempt to use the delicious v1 API to post a bookmark using the 
     * command input
     */</span>
    execute<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>input_obj<span style="color: #339933;">,</span> mods<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> bm          <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>._extractBookmarkData<span style="color: #009900;">&#40;</span>input_obj<span style="color: #339933;">,</span> mods<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> user_cookie <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>._getUserCookie<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> user_name   <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>user_cookie<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> user_cookie.<span style="color: #660066;">split</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">' '</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>user_name<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #006600; font-style: italic;">// If there's no user name, there's no login, so this command won't work. </span>
            displayMessage<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'No active user found - log in at delicious.com '</span> <span style="color: #339933;">+</span>
                <span style="color: #3366CC;">'to use this command.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>bm.<span style="color: #660066;">description</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #006600; font-style: italic;">// If there's no title, somehow, then this is an error too.</span>
            displayMessage<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;A title is required for bookmarks at delicious.com&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>


<p>Mirroring the <code>.preview()</code> method, the <code>.execute()</code> method first checks for validity of the arguments given by the user.  A missing user name or title result in a notification that the command has failed.</p>

<p>But, if the arguments are all valid, it&#8217;s time to actually issue a request to the Delicious V1 API:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">        <span style="color: #003366; font-weight: bold;">var</span> path <span style="color: #339933;">=</span> <span style="color: #3366CC;">'/v1/posts/add'</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> url  <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>._config.<span style="color: #660066;">api_base</span> <span style="color: #339933;">+</span> path<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">var</span> req <span style="color: #339933;">=</span> Components.<span style="color: #660066;">classes</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;@mozilla.org/xmlextras/xmlhttprequest;1&quot;</span><span style="color: #009900;">&#93;</span>.
            <span style="color: #660066;">createInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        req.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'POST'</span><span style="color: #339933;">,</span> url<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        req.<span style="color: #000066;">onload</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ev<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
            displayMessage<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Bookmark &quot;'</span> <span style="color: #339933;">+</span> bm.<span style="color: #660066;">description</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&quot; '</span> <span style="color: #339933;">+</span> 
                <span style="color: #3366CC;">'shared at delicious.com/'</span> <span style="color: #339933;">+</span> user_name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        req.<span style="color: #000066;">onerror</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>ev<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
            displayMessage<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ERROR: Bookmark &quot;'</span> <span style="color: #339933;">+</span> bm.<span style="color: #660066;">description</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&quot; '</span> <span style="color: #339933;">+</span> 
                <span style="color: #3366CC;">' NOT shared on delicious.com/'</span> <span style="color: #339933;">+</span> user_name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>


<p>Using the base URL for the Delicious API declared earlier in the configuration section, the <code>.execute()</code> method constructs an API URL for the <code>/v1/posts/add</code> method.  Then, it creates an instance of <code>XMLHttpRequest</code> from the browser to be used in sending the API request.  Event handlers are registered with the object to present notifications to the user indicating whether or not the API request was successful.</p>

<p>At long last, it&#8217;s time to wrap up this method and make the API request:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
</pre></td><td class="code"><pre class="javascript" style="font-family:monospace;">        req.<span style="color: #660066;">setRequestHeader</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Authorization'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'Basic Y29va2llOmNvb2tpZQ=='</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// btoa('cookie:cookie')</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">var</span> mediator <span style="color: #339933;">=</span> Components.<span style="color: #660066;">classes</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;@mozilla.org/appshell/window-mediator;1&quot;</span><span style="color: #009900;">&#93;</span>.
            <span style="color: #660066;">getService</span><span style="color: #009900;">&#40;</span>Components.<span style="color: #660066;">interfaces</span>.<span style="color: #660066;">nsIWindowMediator</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> win <span style="color: #339933;">=</span> mediator.<span style="color: #660066;">getMostRecentWindow</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> user_agent <span style="color: #339933;">=</span> win.<span style="color: #660066;">navigator</span>.<span style="color: #660066;">userAgent</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;;Ubiquity-share-on-delicious&quot;</span><span style="color: #339933;">;</span>
&nbsp;
        req.<span style="color: #660066;">setRequestHeader</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;User-Agent&quot;</span><span style="color: #339933;">,</span> user_agent<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>      
&nbsp;
        req.<span style="color: #660066;">setRequestHeader</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Content-Type'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'application/x-www-form-urlencoded'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        req.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>._buildQueryString<span style="color: #009900;">&#40;</span>bm<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
    EOF<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">null</span> <span style="color: #006600; font-style: italic;">// I hate trailing commas</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>


<p>The login cookie authentication supported by the Delicious V1 API is triggered by supplying a user name / password pair of <code>cookie</code>, which is done by setting the <code>Authorization</code> request header.  The login cookie is then expected to be passed in as the POST variable <code>_user</code>, which is done in the <code>._extractBookmarkData()</code> utility method.</p>

<p>Another bit here that shows more access of browser resources is the construction of a unique User-Agent header for this API call based on the browser&#8217;s own User-Agent string, something that&#8217;s suggested in the guidelines for using the Delicious API.</p>

<p>Finally, the <code>.execute()</code> method—and the command itself—is wrapped up with by sending off the bookmark data encoded as POST form variables with the <code>._buildQueryString()</code> utility method.</p>

<p>And, that&#8217;s it—a command-driven Delicious browser extension in a little over 200 lines of code.  There&#8217;s still more to be done to really make this thing full-featured, but I think this shows off the basic features of Ubiquity.  I&#8217;m hoping to dig in deeper and explore further, taking a look at running Greasemonkey-style code at <a href="https://wiki.mozilla.org/Labs/Ubiquity/Ubiquity_0.1_Author_Tutorial#Running_on_page_load_and_startup">browser startup and page load</a>, as well as playing with some more browser chrome features.  </p>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2008/09/01/writing-a-delicious-command-for-ubiquity/feed</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Ubiquity cracks open personal mashup tinkering</title>
		<link>http://decafbad.com/blog/2008/08/31/ubiquity-cracks-open-personal-mashup-tinkering</link>
		<comments>http://decafbad.com/blog/2008/08/31/ubiquity-cracks-open-personal-mashup-tinkering#comments</comments>
		<pubDate>Sun, 31 Aug 2008 05:07:22 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[entries]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mashups]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[ubiquity]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1286</guid>
		<description><![CDATA[When I was a wee hacker, I lived my digital life though a Commodore 64.  I played games on it, did homework, talked to people far away—you know, all the stuff they showed in the pictures on the box.  I also took things apart—both the machine itself and software running on it.  [...]]]></description>
			<content:encoded><![CDATA[<p>When I was a wee hacker, I lived my digital life though a <a href="http://www.virtualsky.net/iadoremyc64/">Commodore 64</a>.  I played games on it, did homework, talked to people far away—you know, all the stuff they showed in the pictures on the box.  I also took things apart—both the machine itself and software running on it.  I grew up learning that my digital environment was ultimately understandable, <a href="http://cbm.csbruce.com/~csbruce/cbm/transactor/">susceptible to tinkering</a>, and open to being bent to my own purposes.</p>

<p>From the Commodore 64, I graduated eventually to terminals and text editors, opening portals mostly onto computers elsewhere via powerful UNIX command shells.  And, of course, over the past decade, this has largely given way to life in a browser.  </p>

<p>Yet, for a little while, particularly in the first few years of browsers, freedom to tinker seemed cramped.  JavaScript had yet to arrive, and was a little messy when it did.  There was no relatively easy addon development.  And, though the portals opened by a browser were richer than those provided by terminals, the paths of navigation defined by links controlled by site owners offered less freedom of movement than UNIX commands.  I could create my own pages, but I couldn&#8217;t do much to others&#8217; pages.</p>

<p>But then, javascript: URLs came around, dots were connected, and <a href="http://en.wikipedia.org/wiki/Bookmarklet">bookmarklets</a> were born.  Suddenly, it was possible to customize <em>my</em> browsing environment with arbitrary JavaScript code having access to the current page—no matter <em>whose</em> page it was.  And, through the various tricks of the AJAX trade, bookmarklets have only gotten more capable throughout the years.</p>

<p><a href="http://www.mozilla.org/docs/end-user/keywords.html">Smart keyword shortcuts</a> came around a little later, allowing quick access to bookmarks via simple keywords typed into the location bar.  The smart part, though, came in the form of bookmarked URLs with placeholders and keywords given arguments to fill the placeholders—allowing not only quick access to bookmarked pages but also search engine forms bookmarked with late-bound fields.</p>

<p>Bookmarklets inherited the benefits of smart keyword shortcuts.  The same placeholder in http: URLs can be inserted into the code of a javascript: URL, thus parameterizing the JavaScript code and incidentally turning the location bar into a kind of primitive command line.  For example, one of my most heavily used &#8220;<a href="http://naeblis.cx/weblog/2004/08/09/DeliciousAddresslets">addresslets</a>&#8221; is based on <a href="http://ejohn.org/blog/super-fast-delicious-bookmarklet/">John Resig&#8217;s original &#8220;Super-Fast Delicious Bookmarklet&#8221;</a>.</p>

<p>Another leap in prying open the browser tinkering space came in the form of <a href="http://www.greasespot.net/">Greasemonkey</a>—an addon-powered environment created explicitly for the purpose of end-user scripting applied to others&#8217; pages.  <a href="http://www.greasespot.net/">Greasemonkey</a> user scripts can do more than bookmarklets, and with a much better development environment to boot.  And, though a user script can&#8217;t do quite as much as a proper browser addon, they&#8217;re much easier to hack on and distribute.</p>

<p>Now, consider one of <a href="http://labs.mozilla.com/">Mozilla Labs</a>&#8216; <a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">newest projects</a>, named <a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a>.  This rough and experimental addon for Firefox combines and improves upon everything I&#8217;ve described so far:</p>

<ul>
<li><a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a> is a hackable command line environment, better than <a href="http://en.wikipedia.org/wiki/Bookmarklet">bookmarklets</a> and smart <a href="http://www.mozilla.org/docs/end-user/keywords.html">keyword shortcuts</a>;</li>
<li><a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a> enables persistent customization of others&#8217; pages, not unlike <a href="http://www.greasespot.net/">Greasemonkey</a>; </li>
<li><a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a> facilitates live in-browser creation and web-based subscription to user commands and scripts;</li>
<li><a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a> gives access to browser chrome resources without a need for frequent restarts;</li>
</ul>

<p>So far, most of the <a href="https://labs.toolness.com/ubiquity-herd/">commands</a> I see popping up since the 0.1 release have not accomplished much more than <a href="http://www.mozilla.org/docs/end-user/keywords.html">smart keyword shortcuts</a> in the location bar could.  But, it&#8217;s early yet, and <a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a> is far from limited to these commands.</p>

<p>Once the basics have been well-explored, I expect to see more people taking a crack at the broader capabilities offered by <a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a>.  <a href="http://en.wikipedia.org/wiki/Bookmarklet">Bookmarklets</a> and <a href="http://www.greasespot.net/">Greasemonkey</a> can&#8217;t access browser chrome—but <a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a> can.  <a href="http://labs.mozilla.com/2008/08/introducing-ubiquity/">Ubiquity</a> also offers a user interface that&#8217;s so much more promising than keyword shortcuts, including command previews and typed parameters with suggestions.</p>

<p>Ubiquity promises web-wide mashups directed by a conversational command interface.  All in all, the potential of this makes me feel like my digital environment—browser and web as a whole—is getting even more intimately, personally hackable.  </p>

<p>It&#8217;ll be very interesting to see where this project goes.</p>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2008/08/31/ubiquity-cracks-open-personal-mashup-tinkering/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Moz08: Rockslides and Blackouts and Bears &#8211; Oh My!</title>
		<link>http://decafbad.com/blog/2008/08/04/moz08-rockslides-and-blackouts-and-bears-oh-my</link>
		<comments>http://decafbad.com/blog/2008/08/04/moz08-rockslides-and-blackouts-and-bears-oh-my#comments</comments>
		<pubDate>Mon, 04 Aug 2008 21:15:23 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[entries]]></category>
		<category><![CDATA[moz08]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[summit]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1270</guid>
		<description><![CDATA[Since the beginning, I&#8217;ve been a Mozilla fanboy.  But, up until very recently, I&#8217;ve only shown that as a user and a verbal supporter, with a shallow understanding or participation in what&#8217;s really done in the Mozilla community.  Sure, I&#8217;ve checked out source code from time to time going back to the first [...]]]></description>
			<content:encoded><![CDATA[<p>Since the beginning, I&#8217;ve been a Mozilla fanboy.  But, up until very recently, I&#8217;ve only shown that as a user and a verbal supporter, with a shallow understanding or participation in what&#8217;s really done in the Mozilla community.  Sure, I&#8217;ve checked out source code from time to time going back to the first code release, built and poked at it, but I&#8217;ve never really contributed back.</p>

<p>But now, I&#8217;m an employee of the Mozilla Corporation, and I feel like I found a little-known cheat code for getting into the place where all the cool stuff happens.  See, I just got back from this thing called the <a href="http://wiki.mozilla.org/Summit2008">Mozilla 2008 Firefox Plus Summit</a>—and if I was overwhelmed by the initial Mozilla Firehose after coming on-board, I&#8217;m entirely gobsmacked now.</p>

<p>The event—having taken place in the <a href="http://www.rumblingedge.com/2008/07/29/bear-with-me-while-you-sleep-at-whistler/">bear-infested</a>, <a href="http://www.cbc.ca/canada/british-columbia/story/2008/07/30/bc-highway-rockslide-whistler.html">rockslide-prone</a>, <a href="http://www.flickr.com/photos/albill/2720171490/">electricity-deficient</a> wilds of Whistler, BC in Canada—was attended by not only employees of the corporation itself, but a selection of invitees from around the Mozilla community.  Throughout the course of the event, I felt humbled by the efforts of everyone and have come away with a feeling that I really need to step up my game.  Somehow, it seems I managed to sneak into the place without having first run the decade-old traditional gauntlet of meritocracy and contribution.</p>

<p>Being a newbie of just a few months, I barely know anyone at Mozilla, so I was quite overwhelmed socially.  That the early-morning power loss also knocked out <a href="http://decafbad.com/blog/2004/12/03/if-you-snore-get-tested-for-sleep-apnea-now">my CPAP</a> and left me sick and surly on the last day didn&#8217;t help my already introverted tendencies.  Nonetheless, I talked to a lot of people, attended a lot of sessions, partied a bit, played some Rock Band, and have a lot that&#8217;s percolating in my brain-meats.  </p>

<p>There&#8217;s plenty coming up to work on in my own assigned sphere of <a href="http://blog.mozilla.com/webdev/">webdev</a>—but I&#8217;m also pretty jazzed about the Mozilla Labs projects <a href="http://wiki.mozilla.org/Prism" title="Site-specific browsing with Gecko">Prism</a>, <a href="http://wiki.mozilla.org/Labs/Ubiquity" title="A language-based interface, verbing the web">Ubiquity</a>, and <a href="http://wiki.mozilla.org/Labs/Weave" title="Cross-browser data sync and secure third-party sharing">Weave</a>.  Not sure what I can do yet, but would like to do <em>something</em> to help out those efforts.  And maybe by the time of the next summit, I&#8217;ll still be in the Mozilla sphere and will have met and helped a few more Mozillans with whom I can connect face-to-face.</p>

<p>There was also a lot of talk about the future and continuing mission of Mozilla, all very inspirational and telling me that this is the center of things where I&#8217;ve always wanted to be.  Now, I just have to work hard to make sure they&#8217;re not sorry they hired me!  I&#8217;m running much slower than I&#8217;d like, since I feel I have a lot to catch up on while in the midst a lot of disruption and change—between the intensity of the last few months (or even the last year) and readjusting to being back in the Mitten with homeownership all anew and many plans having taken unexpected turns.  </p>

<p>But, things are shaping up in a sort of too-good-to-be-true configuration, and I suspect I&#8217;ll be just fine if I sharpen up a bit and roll with the changes.</p>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2008/08/04/moz08-rockslides-and-blackouts-and-bears-oh-my/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Putting the Sexy into Firefox Theme Browsing</title>
		<link>http://decafbad.com/blog/2008/06/16/putting-the-sexy-into-firefox-theme-browsing</link>
		<comments>http://decafbad.com/blog/2008/06/16/putting-the-sexy-into-firefox-theme-browsing#comments</comments>
		<pubDate>Mon, 16 Jun 2008 20:07:46 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[asides]]></category>
		<category><![CDATA[amo]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[mozilla]]></category>
		<category><![CDATA[themes]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1159</guid>
		<description><![CDATA[As mentioned back in week 3, I&#8217;d started work on bug 419647 to &#8220;add a sexy theme browser&#8221; to addons.mozilla.org.  

Well, I&#8217;m not sure about my success in imbuing it with the required sexiness, but it&#8217;s at least been noticed by someone. :)
]]></description>
			<content:encoded><![CDATA[<p>As mentioned back in <a href="http://decafbad.com/blog/2008/05/22/week-3-at-mozilla">week 3</a>, I&#8217;d started work on <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=419647">bug 419647</a> to &#8220;add a sexy theme browser&#8221; to <a href="https://addons.mozilla.org/">addons.mozilla.org</a>.  </p>

<p>Well, I&#8217;m not sure about my success in imbuing it with the required sexiness, but it&#8217;s at least <a href="http://www.ghacks.net/2008/06/15/firefox-themes-website-updated/">been noticed by someone</a>. :)</p>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2008/06/16/putting-the-sexy-into-firefox-theme-browsing/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Firefox 3 Download Day Mega Widget</title>
		<link>http://decafbad.com/blog/2008/06/16/firefox-3-download-day-mega-widget</link>
		<comments>http://decafbad.com/blog/2008/06/16/firefox-3-download-day-mega-widget#comments</comments>
		<pubDate>Mon, 16 Jun 2008 19:55:04 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[entries]]></category>
		<category><![CDATA[downloadday]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[mozilla]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1148</guid>
		<description><![CDATA[Update: Oh, and rumor has it that this widget will switch to reporting on downloads, rather than pledges, once the main event has begun.

Update 2: It didn&#8217;t quite go like clockwork, but this widget is now showing estimated downloads by countries, rather than pledges.

Thanks to the completion of bug 435967, I can offer this totally [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Update:</strong> Oh, and rumor has it that this widget will switch to reporting on downloads, rather than pledges, once the main event has begun.</p>

<p><strong>Update 2:</strong> It didn&#8217;t <em>quite</em> go like clockwork, but this widget is now showing estimated downloads by countries, rather than pledges.</p>

<p>Thanks to the completion of <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=436967">bug 435967</a>, I can offer this totally unofficial hack of a mega widget (better late than never):</p>

<script type="text/javascript" src="http://decafbad.com/2008/download-day-top-ten.js"></script>

<p>If you&#8217;d like, you can include this on your own site with a Copy-and-Paste of the following:</p>

<p><textarea cols="80" rows="3"><script type="text/javascript" src="http://decafbad.com/2008/download-day-top-ten.js"></script></textarea></p>

<p>This is a total 2-hour cut, paste, reformat, and slight rejigger of <a href="http://kentbrewster.com/case-hardened-javascript/">Kent Brewster&#8217;s work on Content Syndication with Case-Hardened JavaScript</a>.  Hopefully it works, because I&#8217;m <a href="http://catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html">releasing early</a> before I&#8217;ve had a chance to check it out on anything besides the browsers in my lap.</p>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2008/06/16/firefox-3-download-day-mega-widget/feed</wfw:commentRss>
		<slash:comments>56</slash:comments>
		</item>
		<item>
		<title>Week 3 at Mozilla</title>
		<link>http://decafbad.com/blog/2008/05/22/week-3-at-mozilla</link>
		<comments>http://decafbad.com/blog/2008/05/22/week-3-at-mozilla#comments</comments>
		<pubDate>Fri, 23 May 2008 05:04:20 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[entries]]></category>
		<category><![CDATA[mozilla]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1130</guid>
		<description><![CDATA[So, it&#8217;s getting to the end of my third week at Mozilla, and I&#8217;m a part of the Planet now—hooray!  Having gotten a membership into that club, I feel like I should start making some noise about what I&#8217;m doing at work.  Having stayed mostly quiet about day job affairs thus far in [...]]]></description>
			<content:encoded><![CDATA[<p>So, it&#8217;s getting to the end of my third week at Mozilla, and <a href="http://blog.mozilla.com/planet/2008/05/19/planet-addition-class-of-5192008/">I&#8217;m a part</a> of <a href="http://planet.mozilla.org/">the Planet now</a>—hooray!  Having gotten a membership into that club, I feel like I should start making some noise about what I&#8217;m doing at work.  Having stayed mostly quiet about day job affairs thus far in my career, it&#8217;s going to take a bit to get used to a place as open as Mozilla.</p>

<p>Being a noob, I haven&#8217;t started anything earthshaking yet.  But, I have gotten a couple of starter bugs thrown my way:</p>

<ul>
<li><p><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=395271">Bug 395271</a> &#8211; Use memcache to cache output pages for non logged in users </p>

<p><a href="http://wiki.mozilla.org/Sumo">SUMO</a> is <a href="http://support.mozilla.com/en-US/kb/Firefox+Support+Home+Page">support.mozilla.org</a>, a humongous and mostly volunteer-driven support effort for Mozilla products.  I&#8217;ve never really been to the site before myself, so this bug is an iceberg-tip intro to the effort for me.  I&#8217;m wading chest deep into <a href="http://tikiwiki.org">TikiWiki</a> and plonking memcached into the middle of it to try to make knowledge base wiki page views a lot less expensive.</p>

<p>Oh, and the source I&#8217;m working on is <a href="https://svn.mozilla.org/projects/sumo/">in subversion</a>.  Weird.  Like, you could go look at it right now, and tell me <a href="http://viewvc.svn.mozilla.org/vc?view=rev&amp;revision=13362">how bad</a> <a href="http://viewvc.svn.mozilla.org/vc?view=rev&amp;revision=13504">my code</a> is.</p></li>
<li><p><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=419647">Bug 419647</a> &#8211; Add a sexy theme browser</p>

<p><a href="http://wiki.mozilla.org/Update:Remora">AMO</a> is <a href="https://addons.mozilla.org/en-US/firefox/">addons.mozilla.org</a>, another humongous effort to support distribution and developers of extensions for Firefox and more.  This is a site I&#8217;ve been to plenty of times, but never as an extension developer.  And so, here&#8217;s another opportunity to start wading into the deep end.  For this particular bug, the goal is to work up a presentation of themes more easily scanned visually.</p>

<p>Nothing checked into SVN for this one yet, so you&#8217;ll have to withhold ridicule for a little bit yet.</p></li>
</ul>

<p>I&#8217;m really working on squashing my nerd fanboy tendencies.  Because, I remember downloading the original Mozilla Open Source release, staying home from work to compile it on Windows with Visual Studio, and getting just one or two page views out of it before it fell over and caught on fire.  And of course, long before that, I remember using the original lizard in monochrome on a Sun workstation, freaking out over everything and looking up <a href="http://umsa7.ums.edu/~anniebw/earth2/">Earth 2</a> episode guides.</p>

<p>So, although I&#8217;m kinda subdued in general right now—subdued as in beat about the head and shoulders—I&#8217;ve got a serious amount of breathlessness going on while trying hard to just kinda be nonchalant.  :)</p>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2008/05/22/week-3-at-mozilla/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Go Midwest, Young Man!</title>
		<link>http://decafbad.com/blog/2008/05/14/go-midwest-young-man</link>
		<comments>http://decafbad.com/blog/2008/05/14/go-midwest-young-man#comments</comments>
		<pubDate>Thu, 15 May 2008 01:01:37 +0000</pubDate>
		<dc:creator>l.m.orchard</dc:creator>
				<category><![CDATA[entries]]></category>
		<category><![CDATA[mozilla]]></category>

		<guid isPermaLink="false">http://decafbad.com/blog/?p=1092</guid>
		<description><![CDATA[Reminiscent of this time almost two years ago, it&#8217;s been a busy period so far.  I&#8217;ve been working on another book, entitled Professional JavaScript Frameworks, and have changed jobs twice since leaving Yahoo! in early April.  

I think I&#8217;m done bouncing around now, though: As you may or may not already know, I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>Reminiscent of this time <a href="http://decafbad.com/blog/2006/06/24/go-west-young-man">almost two years ago</a>, it&#8217;s been a busy period so far.  I&#8217;ve been working on another book, entitled <a href="http://www.wiley.com/WileyCDA/WileyTitle/productCd-047038459X.html">Professional JavaScript Frameworks</a>, and have changed jobs twice <a href="http://twitter.com/lmorchard/statuses/787565793">since leaving Yahoo! in early April</a>.  </p>

<p>I think I&#8217;m done bouncing around now, though: As you may or may not already know, <a href="http://twitter.com/lmorchard/statuses/804009957">I&#8217;ve started working for the Mozilla Corporation</a>—I&#8217;ve <a href="http://people.mozilla.org/~lorchard/">got a username and everything</a>!  I&#8217;m a little overwhelmed at the moment by changes and drinking from a new firehose, so my enthusiasm may not yet be readily apparent.  But, remember that I&#8217;m a complete web geek—and it&#8217;s hard to get closer to web geekery than this.</p>

<p>But, one of the nicest things about this new Mozilla gig is that I&#8217;m going to start telecommuting.  And the reason that&#8217;s nice is because—and here&#8217;s the next big thing—<a href="http://www.flickr.com/photos/missadroit/2493000246/">my wife and I have bought a beautiful house in Livonia, Michigan</a>, and we&#8217;re moving back to the Midwest in a month and some change.</p>

<p>Why?  Because, after almost two years out here in the valley, we&#8217;ve discovered that being away from family and old friends while trying to make new friends and adjust to a very different locale was a lot harder than first imagined.  And, well, it would&#8217;ve been much longer than we&#8217;d've liked before we could have afforded a house at all—let alone something anything like what we&#8217;ll be enjoying back in Michigan.</p>

<p>The thing is, though, I&#8217;ve still got a lot of love for the Bay Area and its goings on—I&#8217;ve been pining for this place since at least the age of eight, after all.  And, we have made a few good friends out here, despite the difficulties we&#8217;ve experienced.  </p>

<p>So luckily, this Mozilla gig looks like the ideal thing.  I&#8217;m hoping it will ensure regular return visits to enjoy <a href="http://superhappydevhouse.org/">SuperHappyDevHouses</a>, the scent of <a href="http://transplanted-californian.blogspot.com/2007/10/star-jasmine.html">star jasmine</a> in the summer, and amazing cloudless skies lasting for days.</p>

<p>But, on the other hand—although I&#8217;m certainly not relishing the thought of readjusting to cold, clouds, and snow in a few months—I&#8217;m getting excited about the prospects of being back in southeastern Michigan.  Our house will be pretty close to both Ann Arbor and Detroit, and it seems like some interesting things have started warming up since we left.  Also, I suspect (and hope) we&#8217;ll discover a lot of friends and like-minded associates in short order upon our return.</p>

<p>Lots of change.  Very busy.  Not a little exciting.  But, I&#8217;m hopeful that things are going to get a lot better very soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://decafbad.com/blog/2008/05/14/go-midwest-young-man/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
