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

  <title><![CDATA[My Octopress Blog]]></title>
  <link href="http://DanBurton.github.io/atom.xml" rel="self"/>
  <link href="http://DanBurton.github.io/"/>
  <updated>2013-10-14T17:52:46-07:00</updated>
  <id>http://DanBurton.github.io/</id>
  <author>
    <name><![CDATA[Your Name]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Touring complex forms to improve UX]]></title>
    <link href="http://DanBurton.github.io/blog/2013/10/11/touring-complex-forms-to-improve-ux/"/>
    <updated>2013-10-11T13:11:00-07:00</updated>
    <id>http://DanBurton.github.io/blog/2013/10/11/touring-complex-forms-to-improve-ux</id>
    <content type="html"><![CDATA[<p>The web is hard. Let&rsquo;s make it easier.</p>

<p>(This post is in the works; it&rsquo;s security by obscurity, so shhh,
don&rsquo;t tell!)</p>

<!-- more -->


<p>When providing a web service with lots of features,
it is often the case that you want to deliver a lot of power
to your user without a lot of unnecessary clicking.
This sometimes leads to very dense configuration pages.
The user, when first confronted with so many options,
will surely be overwhealmed. She may be able to find just the right
nobs and frobs that she needs for some particular task,
but will surely have a hard time comprehending everything
that the page allows her to control. Features may be staring her in
the face, but such dense and confusing pages may cause her to miss
that which is right in front of her.</p>

<p>There are a few solutions to this problem.
We can simplify her experience by limiting her options.
Sometimes less is more. But sometimes not.
Another solution is to train her in person.
You can point at the screen and say, &ldquo;you can use this option to do this,&rdquo;
and &ldquo;when you want to do that, go here, and then click that.&rdquo;
For various reasons, this isn&rsquo;t always possible. It certainly becomes
a huge bottleneck when you want many people to spontaneously try out
your awesome web service.</p>

<p>Our goal today is to simulate the &ldquo;personal tour&rdquo; eperience mechanically.
We do this by:</p>

<ul>
<li>Darkening and disabling the page</li>
<li>Highlighting features on the screen, one at a time</li>
<li>Explaining how to use that feature</li>
<li>Lightening and re-enabling the page</li>
</ul>


<p>I&rsquo;m going to step you through the changes to a rails project,
using haml, sass, and coffeescript. However, note that the heart
of this tutorial really has nothing to do with those technologies,
and you can do everything I show here with a trivial translation to
plain old html, css, javascript, and your web server of choice.</p>

<p>Although this post isn&rsquo;t <em>about</em> rails, I do cover, in detail,
all of the little steps necessary to get things done, which I hope
can incidentally also serve as a nice little rails primer for those
who are interested.</p>

<h2>Initial setup</h2>

<p>Let&rsquo;s whip up a new rails project that uses haml.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>rails new tour-example <span class="o">&amp;&amp;</span> <span class="nb">cd </span>tour-example <span class="o">&amp;&amp;</span> <span class="nb">echo</span> <span class="s2">&quot;gem &#39;haml&#39;&quot;</span> &gt;&gt; Gemfile <span class="o">&amp;&amp;</span> bundle install
</span></code></pre></td></tr></table></div></figure>


<p>We&rsquo;ll start off with a simple page.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='haml'><span class='line'><span class="cp">-# app/views/application/index.haml</span>
</span><span class='line'>
</span><span class='line'><span class="nf">#example-page</span>
</span><span class='line'>  <span class="nc">.one</span>
</span><span class='line'>    Part one
</span><span class='line'>  <span class="nc">.two</span>
</span><span class='line'>    Part two
</span><span class='line'>  <span class="nc">.three</span>
</span><span class='line'>    Part three
</span></code></pre></td></tr></table></div></figure>


<p>With some style.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='sass'><span class='line'><span class="c1">// app/assets/stylesheets/index.sass</span>
</span><span class='line'>
</span><span class='line'><span class="nc">.one</span><span class="o">,</span> <span class="nc">.two</span><span class="o">,</span> <span class="nc">.three</span>
</span><span class='line'>  <span class="na">margin</span><span class="o">:</span> <span class="mi">5</span><span class="kt">em</span>
</span><span class='line'>  <span class="na">padding</span><span class="o">:</span> <span class="mi">5</span><span class="kt">em</span>
</span><span class='line'>  <span class="na">background-color</span><span class="o">:</span> <span class="ni">lightblue</span>
</span></code></pre></td></tr></table></div></figure>


<p>And we&rsquo;ll configure our application to serve this page at the root.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='diff'><span class='line'><span class="gh">diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb</span>
</span><span class='line'><span class="gh">index d83690e..99ee3ea 100644</span>
</span><span class='line'><span class="gd">--- a/app/controllers/application_controller.rb</span>
</span><span class='line'><span class="gi">+++ b/app/controllers/application_controller.rb</span>
</span><span class='line'><span class="gu">@@ -2,4 +2,7 @@ class ApplicationController &lt; ActionController::Base</span>
</span><span class='line'>   # Prevent CSRF attacks by raising an exception.
</span><span class='line'>   # For APIs, you may want to use :null_session instead.
</span><span class='line'>   protect_from_forgery with: :exception
</span><span class='line'><span class="gi">+</span>
</span><span class='line'><span class="gi">+  def index</span>
</span><span class='line'><span class="gi">+  end</span>
</span><span class='line'> end
</span><span class='line'><span class="gh">diff --git a/config/routes.rb b/config/routes.rb</span>
</span><span class='line'><span class="gh">index e92c058..43ccfc7 100644</span>
</span><span class='line'><span class="gd">--- a/config/routes.rb</span>
</span><span class='line'><span class="gi">+++ b/config/routes.rb</span>
</span><span class='line'><span class="gu">@@ -3,7 +3,7 @@ TourExample::Application.routes.draw do</span>
</span><span class='line'>   # See how all your routes lay out with &quot;rake routes&quot;.
</span><span class='line'>
</span><span class='line'>   # You can have the root of your site routed with &quot;root&quot;
</span><span class='line'><span class="gd">-  # root &#39;welcome#index&#39;</span>
</span><span class='line'><span class="gi">+  root &#39;application#index&#39;</span>
</span><span class='line'>
</span><span class='line'>   # Example of regular route:
</span><span class='line'>   #   get &#39;products/:id&#39; =&gt; &#39;catalog#view&#39;
</span></code></pre></td></tr></table></div></figure>


<p>If you&rsquo;re following along, go ahead and make sure everything is working so far.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>rails server
</span></code></pre></td></tr></table></div></figure>


<p>Visit <a href="http://localhost:3000">http://localhost:3000</a> and you should see that page we just added,
appropriately styled.</p>

<p><img src="http://DanBurton.github.io/images/tour-1.png"></p>

<h2>Darken the screen</h2>

<p>During the tour, we want everything to be darkened,
so that the user&rsquo;s focus will be on the features being showcased
during the tour. Let&rsquo;s start there.
All that we need to accomplish this
is a fixed element that covers the page,
and has a black background and high (but not total) opacity.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='diff'><span class='line'><span class="gh">diff --git a/app/views/application/index.haml b/app/views/application/index.haml</span>
</span><span class='line'><span class="gh">index e336443..92a257d 100644</span>
</span><span class='line'><span class="gd">--- a/app/views/application/index.haml</span>
</span><span class='line'><span class="gi">+++ b/app/views/application/index.haml</span>
</span><span class='line'><span class="gu">@@ -1,5 +1,7 @@</span>
</span><span class='line'> -# app/views/application/index.haml
</span><span class='line'>
</span><span class='line'><span class="gi">+#cover</span>
</span><span class='line'><span class="gi">+</span>
</span><span class='line'> #example-page
</span><span class='line'>   .one
</span><span class='line'>     Part one
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='sass'><span class='line'><span class="c1">// app/assets/stylesheets/tour.sass</span>
</span><span class='line'>
</span><span class='line'><span class="nn">#cover</span>
</span><span class='line'>  <span class="na">position</span><span class="o">:</span> <span class="no">fixed</span>
</span><span class='line'>  <span class="na">z-index</span><span class="o">:</span> <span class="mi">1</span>
</span><span class='line'>  <span class="na">top</span><span class="o">:</span> <span class="mi">0</span>
</span><span class='line'>  <span class="na">left</span><span class="o">:</span> <span class="mi">0</span>
</span><span class='line'>  <span class="na">right</span><span class="o">:</span> <span class="mi">0</span>
</span><span class='line'>  <span class="na">bottom</span><span class="o">:</span> <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'>  <span class="na">opacity</span><span class="o">:</span> <span class="mi">0</span><span class="mf">.8</span>
</span><span class='line'>  <span class="na">background-color</span><span class="o">:</span> <span class="nb">black</span>
</span></code></pre></td></tr></table></div></figure>


<p>Check <a href="http://localhost:3000">http://localhost:3000</a> and see how that looks now.
The whole page should remain dark, even when you scroll
up and down.</p>

<p><img src="http://DanBurton.github.io/images/tour-2.png"></p>

<h2>Annotating the page with tour information</h2>

<p>Then we add legs of the tour by wrapping them
up with some additional tagging information.
In this example, I&rsquo;ve annotated &ldquo;part one&rdquo; and
&ldquo;part three&rdquo; with tour information.
The whole thing gets wrapped in a <code>.tour</code> div,
the additional tour text is written in the <code>.callout</code> div,
and finally, the the highlighted feature is simply
nested inside the <code>.feature</code> div.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='haml'><span class='line'><span class="cp">-# app/views/application/index.haml</span>
</span><span class='line'>
</span><span class='line'><span class="nf">#cover</span>
</span><span class='line'>
</span><span class='line'><span class="nf">#example-page</span>
</span><span class='line'>  <span class="nc">.one</span>
</span><span class='line'>    <span class="nc">.tour</span>
</span><span class='line'>      <span class="nc">.callout</span>
</span><span class='line'>        This is part one
</span><span class='line'>      <span class="nc">.feature</span>
</span><span class='line'>        Part one
</span><span class='line'>  <span class="nc">.two</span>
</span><span class='line'>    Part two.
</span><span class='line'>  <span class="nc">.three</span>
</span><span class='line'>    <span class="nc">.tour</span>
</span><span class='line'>      <span class="nc">.callout</span>
</span><span class='line'>        This is part three
</span><span class='line'>      <span class="nc">.feature</span>
</span><span class='line'>        Part three
</span></code></pre></td></tr></table></div></figure>


<p>And we&rsquo;ll give it some style.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='sass'><span class='line'><span class="c1">// append to app/assets/stylesheets/tour.sass</span>
</span><span class='line'>
</span><span class='line'><span class="nc">.tour</span>
</span><span class='line'>  <span class="na">position</span><span class="o">:</span> <span class="no">relative</span>
</span><span class='line'>  <span class="na">background-color</span><span class="o">:</span> <span class="no">inherit</span>
</span><span class='line'>
</span><span class='line'>  <span class="nc">.callout</span>
</span><span class='line'>    <span class="na">position</span><span class="o">:</span> <span class="no">absolute</span>
</span><span class='line'>    <span class="na">z-index</span><span class="o">:</span> <span class="mi">2</span>
</span><span class='line'>    <span class="na">top</span><span class="o">:</span> <span class="mi">0</span>
</span><span class='line'>    <span class="na">right</span><span class="o">:</span> <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'>    <span class="na">padding</span><span class="o">:</span> <span class="mi">2</span><span class="kt">em</span>
</span><span class='line'>    <span class="na">border</span><span class="o">:</span> <span class="mi">1</span><span class="kt">px</span> <span class="no">solid</span> <span class="nb">white</span>
</span><span class='line'>    <span class="na">background-color</span><span class="o">:</span> <span class="nb">white</span>
</span><span class='line'>    <span class="na">color</span><span class="o">:</span> <span class="nb">black</span>
</span><span class='line'>
</span><span class='line'>  <span class="nc">.feature</span>
</span><span class='line'>    <span class="na">position</span><span class="o">:</span> <span class="no">relative</span>
</span><span class='line'>    <span class="na">z-index</span><span class="o">:</span> <span class="mi">2</span>
</span><span class='line'>
</span><span class='line'>    <span class="na">border-radius</span><span class="o">:</span> <span class="mi">5</span><span class="kt">px</span>
</span><span class='line'>    <span class="na">background-color</span><span class="o">:</span> <span class="no">inherit</span>
</span></code></pre></td></tr></table></div></figure>


<p>Notice how we&rsquo;ve cleverly
positioned the <code>.callout</code> absolutely in reference to the <code>.tour</code>.
This means that the <code>.feature</code> div will be rendered exactly
in the same position where it would have been without these
extra elements.
Also note how <code>.tour</code> and <code>.feature</code> inherit the background color
of the parent. This helps them pop out a little better.</p>

<p>Let&rsquo;s see how that looks so far.</p>

<p><img src="http://DanBurton.github.io/images/tour-3.png"></p>

<p>Well, it&rsquo;s not bad, but not great.
Notice how the callout overlaps the feature.
We&rsquo;ll improve the placement of the callout
when we get to scripting. In other words, now.</p>

<h2>One step at a time</h2>

<p>The tour should take our user through features
one at a time. Let&rsquo;s throw in some scripting to
get that done.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'><span class="c1"># app/assets/javascripts/tour.coffee</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nx">@Tour</span>
</span></code></pre></td></tr></table></div></figure>


<p>Using <code>class @Tour</code> is a little bit of sugar
that lets me use <code>new Tour()</code> in the haml file by attaching
the <code>Tour</code> class to the <code>window</code> object.
There are better namespacey ways to do this which are
beyond the scope of this blog post.</p>

<p>I&rsquo;ve defined a few helpers in this class.
First, we want to be able to scroll the user gently
to a given element. This is easy with jQuery.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="c1"># smoothly scroll an element to the top</span>
</span><span class='line'>  <span class="nv">prettyScroll = </span><span class="nf">(e) -&gt;</span>
</span><span class='line'>    <span class="nx">$</span><span class="p">(</span><span class="s">&#39;html, body&#39;</span><span class="p">).</span><span class="nx">animate</span> <span class="p">{</span>
</span><span class='line'>      <span class="nv">scrollTop: </span><span class="nx">$</span><span class="p">(</span><span class="nx">e</span><span class="p">).</span><span class="nx">offset</span><span class="p">().</span><span class="nx">top</span>
</span><span class='line'>    <span class="p">},</span> <span class="mi">500</span>
</span></code></pre></td></tr></table></div></figure>


<p>Next, we need a way to initiate and terminate
each portion of the tour.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="c1"># embark on a particular leg of the tour</span>
</span><span class='line'>  <span class="nv">summon = </span><span class="nf">(tour) -&gt;</span>
</span><span class='line'>    <span class="nv">feature = </span><span class="nx">$</span><span class="p">(</span><span class="nx">tour</span><span class="p">).</span><span class="nx">find</span> <span class="s">&#39;.feature&#39;</span>
</span><span class='line'>    <span class="nv">callout = </span><span class="nx">$</span><span class="p">(</span><span class="nx">tour</span><span class="p">).</span><span class="nx">find</span> <span class="s">&#39;.callout&#39;</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">callout</span><span class="p">.</span><span class="nx">show</span><span class="p">()</span>
</span><span class='line'>    <span class="nx">feature</span><span class="p">.</span><span class="nx">addClass</span> <span class="s">&#39;on-tour&#39;</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">prettyScroll</span> <span class="nx">feature</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>  <span class="c1"># complete a leg of the tour</span>
</span><span class='line'>  <span class="nv">dismiss = </span><span class="nf">(tour) -&gt;</span>
</span><span class='line'>    <span class="nv">feature = </span><span class="nx">$</span><span class="p">(</span><span class="nx">tour</span><span class="p">).</span><span class="nx">find</span> <span class="s">&#39;.feature&#39;</span>
</span><span class='line'>    <span class="nv">callout = </span><span class="nx">$</span><span class="p">(</span><span class="nx">tour</span><span class="p">).</span><span class="nx">find</span> <span class="s">&#39;.callout&#39;</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">callout</span><span class="p">.</span><span class="nx">hide</span><span class="p">()</span>
</span><span class='line'>    <span class="nx">feature</span><span class="p">.</span><span class="nx">removeClass</span> <span class="s">&#39;on-tour&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Pretty straightforward.
Now, we just need to give the user a way to actually
interact with the tour, and move from one leg to the next.
I chose to set this up by appending a link to each callout.</p>

<p>As an additional item of pre-processing, I&rsquo;ve used javascript
to move the callout just below the feature, by calculating
that feature&rsquo;s height, and setting the callout css to be just below.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
</pre></td><td class='code'><pre><code class='coffeescript'><span class='line'>  <span class="nv">constructor: </span><span class="nf">(cover, scope) -&gt;</span>
</span><span class='line'>    <span class="nx">scope</span> <span class="o">||=</span> <span class="nx">$</span><span class="p">(</span><span class="s">&#39;body&#39;</span><span class="p">)</span>
</span><span class='line'>    <span class="nv">tours = </span><span class="nx">$</span><span class="p">(</span><span class="nx">scope</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="s">&#39;.tour&#39;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># attach &#39;next/okay&#39; button to each leg of the tour</span>
</span><span class='line'>    <span class="nx">tours</span><span class="p">.</span><span class="nx">each</span> <span class="nf">(i, tour) -&gt;</span>
</span><span class='line'>      <span class="nv">callout = </span><span class="nx">$</span><span class="p">(</span><span class="nx">tour</span><span class="p">).</span><span class="nx">find</span> <span class="s">&#39;.callout&#39;</span>
</span><span class='line'>      <span class="nv">feature = </span><span class="nx">$</span><span class="p">(</span><span class="nx">tour</span><span class="p">).</span><span class="nx">find</span> <span class="s">&#39;.feature&#39;</span>
</span><span class='line'>      <span class="nv">upNext = </span><span class="nx">tours</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
</span><span class='line'>
</span><span class='line'>      <span class="nv">advance = </span><span class="nx">$</span><span class="p">(</span><span class="s">&#39;&lt;a href=&quot;#&quot;&gt;&lt;/a&gt;&#39;</span><span class="p">)</span>
</span><span class='line'>      <span class="nx">advance</span><span class="p">.</span><span class="nx">addClass</span> <span class="s">&#39;tour-next-button&#39;</span>
</span><span class='line'>      <span class="nx">advance</span><span class="p">.</span><span class="nx">html</span><span class="p">(</span><span class="k">if</span> <span class="nx">upNext</span> <span class="k">then</span> <span class="s">&#39;next&#39;</span> <span class="k">else</span> <span class="s">&#39;okay&#39;</span><span class="p">)</span>
</span><span class='line'>      <span class="nx">advance</span><span class="p">.</span><span class="nx">click</span> <span class="nf">(e) -&gt;</span>
</span><span class='line'>        <span class="nx">e</span><span class="p">.</span><span class="nx">preventDefault</span><span class="p">()</span>
</span><span class='line'>        <span class="nx">dismiss</span> <span class="nx">tour</span>
</span><span class='line'>
</span><span class='line'>        <span class="k">if</span> <span class="nx">upNext</span>
</span><span class='line'>          <span class="nx">summon</span> <span class="nx">upNext</span>
</span><span class='line'>        <span class="k">else</span>
</span><span class='line'>          <span class="nx">$</span><span class="p">(</span><span class="s">&#39;html, body&#39;</span><span class="p">).</span><span class="nx">animate</span> <span class="p">{</span>
</span><span class='line'>            <span class="nv">scrollTop: </span><span class="mi">0</span>
</span><span class='line'>          <span class="p">},</span> <span class="mi">2000</span>
</span><span class='line'>          <span class="nx">$</span><span class="p">(</span><span class="nx">cover</span><span class="p">).</span><span class="nx">fadeOut</span> <span class="mi">2000</span>
</span><span class='line'>
</span><span class='line'>      <span class="nx">callout</span><span class="p">.</span><span class="nx">append</span> <span class="nx">$</span><span class="p">(</span><span class="s">&#39;&lt;br /&gt;&#39;</span><span class="p">)</span>
</span><span class='line'>      <span class="nx">callout</span><span class="p">.</span><span class="nx">append</span> <span class="nx">$</span><span class="p">(</span><span class="s">&#39;&lt;br /&gt;&#39;</span><span class="p">)</span>
</span><span class='line'>      <span class="nx">callout</span><span class="p">.</span><span class="nx">append</span> <span class="nx">advance</span>
</span><span class='line'>
</span><span class='line'>      <span class="c1"># move the callout to just below the feature</span>
</span><span class='line'>      <span class="nx">callout</span><span class="p">.</span><span class="nx">css</span>
</span><span class='line'>        <span class="nv">top: </span><span class="nx">feature</span><span class="p">.</span><span class="nx">height</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># begin the tour</span>
</span><span class='line'>    <span class="nx">$</span><span class="p">(</span><span class="nx">cover</span><span class="p">).</span><span class="nx">show</span><span class="p">()</span>
</span><span class='line'>    <span class="nx">summon</span> <span class="nx">tours</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now we can invoke this in the haml.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='haml'><span class='line'><span class="cp">-# append to app/views/application/index.haml</span>
</span><span class='line'>
</span><span class='line'><span class="nd">:javascript</span>
</span><span class='line'>  <span class="nd">$(function() { new Tour(&#39;#cover&#39;, &#39;#example-page&#39;); });</span>
</span></code></pre></td></tr></table></div></figure>


<p>And that&rsquo;s just about it. Let&rsquo;s tweak the style so that
it leverages the <code>on-tour</code> class, and have the cover and
the callouts be hidden by default.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
</pre></td><td class='code'><pre><code class='diff'><span class='line'><span class="gh">diff --git a/app/assets/stylesheets/tour.sass b/app/assets/stylesheets/tour.sass</span>
</span><span class='line'><span class="gh">index acb3466..e65b811 100644</span>
</span><span class='line'><span class="gd">--- a/app/assets/stylesheets/tour.sass</span>
</span><span class='line'><span class="gi">+++ b/app/assets/stylesheets/tour.sass</span>
</span><span class='line'><span class="gu">@@ -1,6 +1,8 @@</span>
</span><span class='line'> // app/assets/stylesheets/tour.sass
</span><span class='line'>
</span><span class='line'> #cover
</span><span class='line'><span class="gi">+  display: none</span>
</span><span class='line'><span class="gi">+</span>
</span><span class='line'>   position: fixed
</span><span class='line'>   z-index: 1
</span><span class='line'>   top: 0
</span><span class='line'><span class="gu">@@ -16,6 +18,8 @@</span>
</span><span class='line'>   background-color: inherit
</span><span class='line'>
</span><span class='line'>   .callout
</span><span class='line'><span class="gi">+    display: none</span>
</span><span class='line'><span class="gi">+</span>
</span><span class='line'>     position: absolute
</span><span class='line'>     z-index: 2
</span><span class='line'>     top: 0
</span><span class='line'><span class="gu">@@ -26,7 +30,7 @@</span>
</span><span class='line'>     background-color: white
</span><span class='line'>     color: black
</span><span class='line'>
</span><span class='line'><span class="gd">-  .feature</span>
</span><span class='line'><span class="gi">+  .feature.on-tour</span>
</span><span class='line'>     position: relative
</span><span class='line'>     z-index: 2
</span></code></pre></td></tr></table></div></figure>


<h2>Nasty bug, easy fix</h2>

<p>What happens if you can interact with the features
on tour? I&rsquo;ll tell you what can happen: nasty things.
Here&rsquo;s an example.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
</pre></td><td class='code'><pre><code class='diff'><span class='line'><span class="gh">diff --git a/app/views/application/index.haml b/app/views/application/index.haml</span>
</span><span class='line'><span class="gh">index 6991ff1..447b87f 100644</span>
</span><span class='line'><span class="gd">--- a/app/views/application/index.haml</span>
</span><span class='line'><span class="gi">+++ b/app/views/application/index.haml</span>
</span><span class='line'><span class="gu">@@ -8,7 +8,10 @@</span>
</span><span class='line'>       .callout
</span><span class='line'>         This is part one
</span><span class='line'>       .feature
</span><span class='line'><span class="gd">-        Part one</span>
</span><span class='line'><span class="gi">+        %p Part one</span>
</span><span class='line'><span class="gi">+</span>
</span><span class='line'><span class="gi">+        %p</span>
</span><span class='line'><span class="gi">+          %a{href: &#39;javascript:oops();&#39;} A wild link has appeared!</span>
</span><span class='line'>   .two
</span><span class='line'>     Part two.
</span><span class='line'>   .three
</span><span class='line'><span class="gu">@@ -20,3 +23,7 @@</span>
</span><span class='line'>
</span><span class='line'> :javascript
</span><span class='line'>   $(function() { new Tour(&#39;#cover&#39;, &#39;#example-page&#39;); });
</span><span class='line'><span class="gi">+</span>
</span><span class='line'><span class="gi">+  function oops() {</span>
</span><span class='line'><span class="gi">+    $(&#39;.three&#39;).remove();</span>
</span><span class='line'><span class="gi">+  }</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now click the wild link, and try to complete the tour.
Whoops, you can&rsquo;t, because the final leg of the tour was removed
from the DOM!</p>

<p>CSS has a really cool and easy solution for this.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='diff'><span class='line'><span class="gh">diff --git a/app/assets/stylesheets/tour.sass b/app/assets/stylesheets/tour.sass</span>
</span><span class='line'><span class="gh">index e65b811..86b61b2 100644</span>
</span><span class='line'><span class="gd">--- a/app/assets/stylesheets/tour.sass</span>
</span><span class='line'><span class="gi">+++ b/app/assets/stylesheets/tour.sass</span>
</span><span class='line'><span class="gu">@@ -31,8 +31,11 @@</span>
</span><span class='line'>     color: black
</span><span class='line'>
</span><span class='line'>   .feature.on-tour
</span><span class='line'><span class="gi">+    pointer-events: none</span>
</span><span class='line'><span class="gi">+</span>
</span><span class='line'>     position: relative
</span><span class='line'>     z-index: 2
</span><span class='line'>
</span><span class='line'>     border-radius: 5px
</span><span class='line'>     background-color: inherit
</span></code></pre></td></tr></table></div></figure>


<p>Now no pointer events are allowed for a feature on tour,
and the continuity of the tour is saved. Neat.</p>

<h2>Exercises for the reader</h2>

<ul>
<li>You may wish to lead the tour in a different order than the default
DOM traversal order discovered by jQuery. Change the coffeescript and add metadata
to the haml so that the tour order is configurable.</li>
<li>If you nest one legs of the tour inside of the feature of another
leg of the tour, you will probably get weird behavior. Explain why this is,
and provide a solution.</li>
</ul>

]]></content>
  </entry>
  
</feed>
