<?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>BEKK Open &#187; Grensesnittutvikling</title>
	<atom:link href="http://open.bekk.no/category/bekk/interactive/gsu/feed/" rel="self" type="application/rss+xml" />
	<link>http://open.bekk.no</link>
	<description>Et innblikk i hva som skjer i BEKK</description>
	<lastBuildDate>Fri, 11 May 2012 16:31:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Mixins in Backbone.js</title>
		<link>http://open.bekk.no/mixins-in-backbone/</link>
		<comments>http://open.bekk.no/mixins-in-backbone/#comments</comments>
		<pubDate>Tue, 08 May 2012 11:24:01 +0000</pubDate>
		<dc:creator>Kim Joar Bekkelund</dc:creator>
				<category><![CDATA[Dynamiske språk]]></category>
		<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Webarkitektur]]></category>
		<category><![CDATA[backbone.js]]></category>
		<category><![CDATA[jasmine]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[test]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=8722</guid>
		<description><![CDATA[In this blog post I show how functionality can easily be reused across Backbone.js models, collections and views in a very powerful way. This technique helps decouple code and make each component more focused on its primary task.]]></description>
			<content:encoded><![CDATA[<p>In our Backbone.js code we have a few times seen the need to reuse similar methods in several models, collections and views. I&#039;ve seen many create a component which they extend from, e.g. a <code>PaginationCollection</code>, but we didn&#039;t like this solution as we only wanted to share some code between objects, not add another layer to our architecture (and, even worse, potentially even more layers if we wanted to include several shared components). Basically we wanted a more decoupled solution, and we solved it by using mixins.</p>
<h2>So — what&#039;s a mixin?</h2>
<p>Basically, a mixin allows you to extend your Backbone components with utility functions. Let&#039;s, for example, say that we have pagination which is similar in many views, but not in all. How should we include this functionality?</p>
<p>We have the following API for adding extra functionality:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">UsersView.<span style="color: #660066;">mixin</span><span style="color: #009900;">&#40;</span>Pagination<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
AppView.<span style="color: #660066;">mixin</span><span style="color: #009900;">&#40;</span>Transitions<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>We have, however, taken the concept of mixins one step further than what I&#039;ve seen before. In addition to including all the properties which are present in the mixin, our implementation enable mixins to include their own <code>initialize</code> which will extend the existing <code>initialize</code>. When mixing into views a mixin can also include its own <code>render</code> and <code>events</code>. Let&#039;s take a look at what this means in practice:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> UserView <span style="color: #339933;">=</span> BaseView.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    events<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;click h1&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;user&quot;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
    initialize<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>
        console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;user init&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
    user<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: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;name&quot;</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;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// This is our mixin:</span>
<span style="color: #003366; font-weight: bold;">var</span> Pagination <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// expects the view it's mixed into to have a link with class `next`</span>
    <span style="color: #006600; font-style: italic;">// present in the DOM</span>
    events<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;click a.next&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;next&quot;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
    initialize<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>
        console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;pagination init&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
&nbsp;
    next<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: #000066; font-weight: bold;">return</span> <span style="color: #3366CC;">&quot;next for: &quot;</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;name&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #006600; font-style: italic;">// yeah, you would absolutely use a collection as it's named</span>
        <span style="color: #006600; font-style: italic;">// pagination, this was just to keep the example short ;)</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
UserView.<span style="color: #660066;">mixin</span><span style="color: #009900;">&#40;</span>Pagination<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> model <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Backbone.<span style="color: #660066;">Model</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
model.<span style="color: #660066;">set</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;name&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;Kim&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">var</span> view <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> UserView<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> model<span style="color: #339933;">:</span> model <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #006600; font-style: italic;">// this initialization console logs (in order):</span>
<span style="color: #006600; font-style: italic;">// &quot;user init&quot;</span>
<span style="color: #006600; font-style: italic;">// &quot;pagination init&quot;</span>
&nbsp;
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>view.<span style="color: #660066;">user</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// &quot;Kim&quot;</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>view.<span style="color: #660066;">next</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// &quot;next for: Kim&quot;</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>view.<span style="color: #660066;">events</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// {</span>
                          <span style="color: #006600; font-style: italic;">//   &quot;click a.next&quot;: &quot;next&quot;,</span>
                          <span style="color: #006600; font-style: italic;">//   &quot;click h1&quot;: &quot;user&quot;</span>
                          <span style="color: #006600; font-style: italic;">// }</span></pre></div></div>

<p>As we can see from the code, a mixin has access to <code>this</code> in the same way as the model, collection or view itself. Additionally, mixins can potentially be self-contained, i.e. because <code>initialize</code>, <code>render</code> and <code>events</code> can be extended the component we mix into does not need to know anything about the the mixin. This makes it especially easy to include a new mixin or remove one that is in use.</p>
<h2>Implementation</h2>
<p>Let&#039;s have a look at an example of how these mixins can be implemented. Specifically we will take a look at an implementation of mixins for views:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">Utils <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
Utils.<span style="color: #660066;">viewMixin</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>from<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> to <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">prototype</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// we add those methods which exists on `from` but not on `to` to the latter</span>
  _.<span style="color: #660066;">defaults</span><span style="color: #009900;">&#40;</span>to<span style="color: #339933;">,</span> from<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #006600; font-style: italic;">// … and we do the same for events</span>
  _.<span style="color: #660066;">defaults</span><span style="color: #009900;">&#40;</span>to.<span style="color: #660066;">events</span><span style="color: #339933;">,</span> from.<span style="color: #660066;">events</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// we then extend `to`'s `initialize`</span>
  Utils.<span style="color: #660066;">extendMethod</span><span style="color: #009900;">&#40;</span>to<span style="color: #339933;">,</span> from<span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;initialize&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #006600; font-style: italic;">// … and its `render`</span>
  Utils.<span style="color: #660066;">extendMethod</span><span style="color: #009900;">&#40;</span>to<span style="color: #339933;">,</span> from<span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;render&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Helper method to extend an already existing method</span>
Utils.<span style="color: #660066;">extendMethod</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>to<span style="color: #339933;">,</span> from<span style="color: #339933;">,</span> methodName<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #006600; font-style: italic;">// if the method is defined on from ...</span>
  <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>_.<span style="color: #660066;">isUndefined</span><span style="color: #009900;">&#40;</span>from<span style="color: #009900;">&#91;</span>methodName<span style="color: #009900;">&#93;</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> old <span style="color: #339933;">=</span> to<span style="color: #009900;">&#91;</span>methodName<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// ... we create a new function on to</span>
    to<span style="color: #009900;">&#91;</span>methodName<span style="color: #009900;">&#93;</span> <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>
&nbsp;
      <span style="color: #006600; font-style: italic;">// wherein we first call the method which exists on `to`</span>
      <span style="color: #003366; font-weight: bold;">var</span> oldReturn <span style="color: #339933;">=</span> old.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> arguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #006600; font-style: italic;">// and then call the method on `from`</span>
      from<span style="color: #009900;">&#91;</span>methodName<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">apply</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> arguments<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #006600; font-style: italic;">// and then return the expected result,</span>
      <span style="color: #006600; font-style: italic;">// i.e. what the method on `to` returns</span>
      <span style="color: #000066; font-weight: bold;">return</span> oldReturn<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Now we need to include this mixin in such a way that <code>this</code> means the correct thing and we can use it like we saw in the example above. This can be done in two ways, both of which utilize the <code>viewMixin</code> method we created above:</p>
<ol>
<li>
<p>As <a href="http://documentcloud.github.com/backbone/#FAQ-extending">mentioned</a> in the Backbone docs it&#039;s okey to add methods directly to a Backbone component. We can use this idea and add <code>mixin</code> like this:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">Backbone.<span style="color: #660066;">View</span>.<span style="color: #660066;">mixin</span> <span style="color: #339933;">=</span> Utils.<span style="color: #660066;">viewMixin</span><span style="color: #339933;">;</span></pre></div></div>

</li>
<li>
<p>If you create a layered architecture you can include <code>viewMixin</code> in one of your layers. In our project we had a <code>BaseView</code> which we created all our views from. Remember, this is how Backbone views are defined:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">Backbone.<span style="color: #660066;">View</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span>properties<span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>classProperties<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p>So, in order to create our desired API we can add <code>mixin</code> as a class property on our <code>BaseView</code>, for example:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> BaseView <span style="color: #339933;">=</span> Backbone.<span style="color: #660066;">View</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// lots of methods</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
  mixin<span style="color: #339933;">:</span> Utils.<span style="color: #660066;">viewMixin</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span></pre></div></div>

</li>
</ol>
<p>In my project we chose to go for the latter solution as we already had a <code>BaseView</code>.</p>
<h2>Testing</h2>
<p>Mixins can be tested both by themselves and when mixed into a component. We&#039;ll take a look at how the latter can be done.</p>
<p>Jasmine has a great way to include similar tests several places. Davis W. Frank of Pivotal Labs <a href="http://pivotallabs.com/users/dwfrank/blog/articles/1720-drying-up-jasmine-specs-with-shared-behavior">wrote a great blog post</a> about this a year ago. Basically, the point is to write a function that contains regular Jasmine specs. For example:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> sharedBehaviorForPagination<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  describe<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;pagination&quot;</span><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>
    it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;should be able to paginate to the next page&quot;</span><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: #006600; font-style: italic;">// ...</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;should not be able to paginate to the next page when on the last page&quot;</span><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: #006600; font-style: italic;">// ...</span>
    <span style="color: #009900;">&#125;</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></pre></div></div>

<p>In the specs for the component we mix into we can then call this function:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">describe<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;users&quot;</span><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: #006600; font-style: italic;">// ... lots of users specific specs</span>
&nbsp;
  sharedBehaviorForPagination<span style="color: #009900;">&#40;</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></pre></div></div>

<p>We have now included the shared set of specs into our regular tests for &quot;users&quot;. If some shared state is needed, we can change <code>sharedBehaviorForPagination</code> to receive arguments in order to share state. We found this to be a great technique for ensuring that our mixins works as expected in all the components which include them.</p>
<h2>When?</h2>
<p>Mixins are a simple but potentially very powerful abstraction. We used them for mainly for three things: pagination, local error handling and handling transitions between pages. Basically, we used mixins when we found them to help decouple our code and make each component more focused. The right time to use them appears to be when a component does more than one thing and when we can better separate concerns when splitting to the code.</p>
<hr />
<p>In this blog post I&#039;ve only looked at using them for views, but they are also great for breaking up models and collections.</p>
<p>To give credit were credit is due, this blog post, and our solution to the mixin problem, was heavily influenced by Dmitry Polushkin&#039;s <a href="https://gist.github.com/1256695">gist on mixins</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/mixins-in-backbone/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Erfaringer fra testdrevet JavaScript</title>
		<link>http://open.bekk.no/erfaringer-fra-testdrevet-javascript/</link>
		<comments>http://open.bekk.no/erfaringer-fra-testdrevet-javascript/#comments</comments>
		<pubDate>Tue, 07 Feb 2012 00:10:40 +0000</pubDate>
		<dc:creator>Snorre Brandstadmoen</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Dynamiske språk]]></category>
		<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[Webarkitektur]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[web sockets]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=8033</guid>
		<description><![CDATA[Magnar Sveen gir en glimrende introduksjon til testdrevet JavaScript-utvikling i screencast-serien &#8220;Zombier, mafia og testdrevet utvikling&#8221;, zombietdd.com. Etter å ha fulgt med på denne i høst, ble jeg inspirert til å gjøre noe tilsvarende selv og bestemte meg for å utvikle en enkel applikasjon, der jeg benytter TDD-metodikk og tilhørende verktøy. iTouch App&#8217;en som skal [...]]]></description>
			<content:encoded><![CDATA[<p>Magnar Sveen gir en glimrende introduksjon til testdrevet JavaScript-utvikling i screencast-serien &#8220;Zombier, mafia og testdrevet utvikling&#8221;, <a href="http://zombietdd.com" target="_blank">zombietdd.com</a>. Etter å ha fulgt med på denne i høst, ble jeg inspirert til å gjøre noe tilsvarende selv og bestemte meg for å utvikle en enkel applikasjon, der jeg benytter TDD-metodikk og tilhørende verktøy.</p>
<p><span id="more-8033"></span></p>
<h2>iTouch</h2>
<p>App&#8217;en som skal lages er et spill, hvor poenget er å taste en gitt tekst feilfritt, raskest mulig. Spillet skal støtte flere samtidige spillere, og alle spillere skal fortløpende se hvordan konkurrenter ligger an underveis, samt status på egen tasting i form av fargekoding av tastet tekst.</p>
<p>Jeg ser for meg en arkitektur der vi kjører JavaScript på server, JavaScript+HTML på klienter, og sanntidsoppdatering av konkurrentstatus over Web Sockets.</p>
<p style="text-align: center"> <a href="http://open.bekk.no/wp-content/uploads/2012/02/overordnet_arkitektur.png"><img class="size-full wp-image-8041 aligncenter" src="http://open.bekk.no/wp-content/uploads/2012/02/overordnet_arkitektur.png" alt="Overordnet arkitektur" width="722" height="494" /></a></p>
<p>Tanken er at på hvert tastetrykk, sender klienten inntastet tekst til serveren for validering. Serveren sender så tilbake et statusobjekt som sier noe om hvorvidt tastet tekst er feil, hvor mye av tekst som gjenstår osv. Det blir så opp til klienten presentere denne statusen til brukeren.</p>
<h2>Litt om teknologi</h2>
<p>Til Web Sockets-kommunikasjonen skal jeg bruke rammeverket <a href="http://nowjs.com" target="_blank">NowJS</a>, som er ganske fascinerende. Det lar deg synkronisere JavaScript-variabler og -funksjoner mellom klient og server, slik at man kan kalle funksjoner på server direkte fra klient, og faktisk også funksjoner definert på klient(er) direkte fra server. NowJS baserer seg på veletablerte SocketIO.</p>
<p>Serverkoden kjører på <a href="http://nodejs.org" target="_blank">Node.js</a>, som er blitt en defacto plattform for serverside JavaScript.</p>
<h2>Testdrevet utvikling</h2>
<p>I JavaScript er det p.t. en rekke testrammeverk tilgjengelig. Jeg har valgt å bruke <a href="http://pivotal.github.com/jasmine" target="_blank">Jasmine</a>, mest fordi jeg liker BDD-syntaksen, og at man kan benytte rammeverket til å teste både klient- og serverkode. I dag ville jeg nok gått for <a href="http://busterjs.org" target="_blank">Buster.JS</a>, men mer om Buster senere.</p>
<p>Man kan fint kjøre Jasmine-tester <a href="https://github.com/pivotal/jasmine/blob/master/lib/jasmine-core/example/SpecRunner.html" target="_blank">standalone i en nettleser</a>, men det er fornuftig å benytte seg av en test runner, eksempelvis <a href="http://code.google.com/p/js-test-driver" target="_blank">JS Test Driver</a>. Bloggpost’en til kollegaer Torstein og Børge: <a title="Getting started with JS and TDD" href="http://open.bekk.no/getting-started-with-js-and-tdd/" target="_blank">”Getting started with JS and TDD”</a>,  gir en grundig innføring i hvordan Jasmine er i bruk, samt hvordan man integrerer med JS Test Driver.</p>
<p>Det avgjørende her er å få lastet ned riktige biblioteker, lagt disse inn i en fornuftig <a href="https://gist.github.com/1747920" target="_blank">mappestruktur</a>, og fått satt opp en <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/jsTestDriver.conf" target="_blank">jsTestDriver.conf</a>-fil til å reflektere denne.  I tillegg kan det være fornuftig å installere &#8220;jstdutil&#8221;. Dette verktøyet lar deg kjøre kommandoene &#8220;jstestdriver&#8221; og &#8220;jsautotest&#8221; fra kommandolinja. Sjekk siden til Christian Johansen for <a href="http://cjohansen.no/en/javascript/jstdutil_a_ruby_wrapper_over_jstestdriver" target="_blank">installasjonsbeskrivelse</a>.</p>
<p>Prosjektet mitt benytter altså Jasmine som testrammeverk, og JS Test Driver for å kjøre testene. Når disse tingene er på plass, er man klar til å skrive første test!</p>
<h2>Første test</h2>
<p>Dette blir litt som å skrive første setningen i en bok, eller i denne bloggposten for den saks skyld. Jeg tenker det enkleste å teste i min kode måtte være mekanismen som validerer inntastet tekst. Jeg ser for meg at vi oppretter en scoringobjekt som tar inn en tekst, og returnerer et statusobjekt som sier noe om hvilke bokstaver i teksten som evt. er feil.</p>
<p>Vi spesifiserer forventet oppførsel i filen spec/scoring.spec.js:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;should validate text with 2 errors&quot;</span><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> typedText <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;DeTte Er en test&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    expect<span style="color: #009900;">&#40;</span>scoring.<span style="color: #660066;">validate</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toBeDefined</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> results <span style="color: #339933;">=</span> scoring.<span style="color: #660066;">validate</span><span style="color: #009900;">&#40;</span>originalText<span style="color: #339933;">,</span> typedText<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    expect<span style="color: #009900;">&#40;</span>results.<span style="color: #660066;">errors</span>.<span style="color: #660066;">length</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span>results.<span style="color: #660066;">errors</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">6</span><span style="color: #009900;">&#93;</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></pre></div></div>

<p>og kjører kommandoen ”jstestdriver –tests all –reset”, eller enda bedre ”jsautotest”. Vi får beskjed om å opprette scoring-modulen i namespacet TDD, med funksjonen &#8220;validate&#8221;. Og etter litt TDD’ing ender vi opp med en mer eller mindre komplett <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/spec/server/scoring.spec.js" target="_blank">scoring.spec.js</a>  med tilhørende implementasjon <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/src/server/scoring.js" target="_blank">scoring.js</a>.</p>
<h2>Arkitektur</h2>
<p>Før vi går videre med tester, kan vi titte litt på kodearkitektur. I tillegg til scoring-modulen, trenger vi funksjonalitet for å administrere selve spillets gang. La oss gi denne modulen navnet &#8220;game&#8221;. På klientsiden trenger vi en modul som styrer kommunikasjonen med server og oppdatering av skjermbilder; game_controller.js</p>
<p>Hvis vi skisserer opp systemet, så har vi et avhengighetsbilde som ligner dette:</p>
<p>&nbsp;</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2012/02/javascriptarkitektur.png"><img class="aligncenter size-full wp-image-8059" src="http://open.bekk.no/wp-content/uploads/2012/02/javascriptarkitektur.png" alt="" width="360" height="427" /></a></p>
<p>Vi vet at game benytter NowJS-rammeverket for å formidle sanntidsinformasjon, i tillegg til scoringmodulen for å kalkulere status. Samtidig skal game_controller.js kommunisere med game.js vha. NowJS.</p>
<p>Når man nå skal sette sammen disse bitene, er det viktig å tenke at de skal være <strong>løst koblet</strong>. Dette kan man få til ved å spesifisere eksterne avhengigheter ved opprettelse av modulene. F.eks., får game.js <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/src/server/game.js#LC17" target="_blank">sprøytet inn en referanse til scoring</a> og <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/src/server/game.js#LC20" target="_blank">NowJS</a> når den blir opprettet, og kode for å opprette et game-objekt blir:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> game <span style="color: #339933;">=</span> TDD.<span style="color: #660066;">game</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    originalText<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;En tekst&quot;</span><span style="color: #339933;">,</span>
    scoring<span style="color: #339933;">:</span> TDD.<span style="color: #660066;">scoring</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    everyone<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">everyone</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Dette gjør det lett å enhetsteste game.js, da man enkelt kan stubbe/mocke disse avhengighetene.</p>
<h2>Mer testing</h2>
<p>Nå har det liten hensikt å gå i gjennom all kildekode og tester i teksten her, men vi skal se litt mer på hvordan utvalgt funksjonalitet er implementert og testet.</p>
<p>Når det gjelder game-modulen, skal denne bla. ha funksjonalitet for å</p>
<ul>
<li>registrere deltakere</li>
<li>sette i gang en ny omgang</li>
<li>distribuere forløpende status til alle deltakere</li>
</ul>
<p>Hvis vi ser nærmere på det siste punktet, så skal status sendes fortløpende til alle deltakerne i sanntid over Web Sockets vha. NowJS. Web Sockets-kommunikasjonen er fullstendig abstrahert bort av rammeverket, og alt man trenger å gjøre er å legge til funksjoner i det spesielle ”<a href="http://nowjs.com/doc/nowjs" target="_blank">now</a>”-objektet som blir synkronisert mellom server og klient. Rammeverket fungerer slik at man kan adressere server via now-objektet på klienten, samt adressere alle klienter via everyone.now-objektet fra serveren.</p>
<p>Når man vet hvordan dette rammeverket fungerer, er man i stand til å spesifisere testen:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;should validate text and distribute scores upon validation request&quot;</span><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> typedText <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;Dette er en&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066;">status</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;errors&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;percentage&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">98</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    spyOn<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">game</span>.<span style="color: #660066;">scoring</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;validate&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">andReturn</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">status</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    spyOn<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">everyone</span>.<span style="color: #660066;">now</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'receiveScores'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">game</span>.<span style="color: #660066;">validate</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">everyone</span>.<span style="color: #660066;">now</span><span style="color: #339933;">,</span> typedText<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">everyone</span>.<span style="color: #660066;">now</span>.<span style="color: #660066;">receiveScores</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toHaveBeenCalledWith</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
        clientId<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;123&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #000066;">name</span><span style="color: #339933;">:</span> undefined
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #000066;">status</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></pre></div></div>

<p>Her bruker vi <a href="https://github.com/pivotal/jasmine/wiki/Spies" target="_blank">spy-egenskapene</a> til Jasmine, til å legge til en forventning om at når man kaller ”validate”-funksjonen på serveren, så skal ”receiveScores”-funksjonen kalles på alle klienter.</p>
<p>Selve this.everyone.now er en stub vi selv spesifiserer:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">everyone</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
    now<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        validate<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: #009900;">&#125;</span><span style="color: #339933;">,</span>
        receiveScores<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>clientId<span style="color: #339933;">,</span> score<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        startGame<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: #009900;">&#125;</span><span style="color: #339933;">,</span>
        displayTextToBeTyped<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: #009900;">&#125;</span><span style="color: #339933;">,</span>
        hideStartButton<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: #009900;">&#125;</span><span style="color: #339933;">,</span>
        showStartButton<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: #009900;">&#125;</span><span style="color: #339933;">,</span>
        clearText<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: #009900;">&#125;</span><span style="color: #339933;">,</span>
        gameOver<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: #009900;">&#125;</span><span style="color: #339933;">,</span>
        user<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
            clientId<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;123&quot;</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></div></div>

<p>Igjen, er det bare å <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/src/server/game.js#LC85" target="_blank">implementere spesifikasjonen</a> og kjøre testene:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Game.should massage original text
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Game.should validate text and distribute scores upon validation request
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Game.should NOT end game when text is errornous
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Game.should end game when text is <span style="color: #7a0874; font-weight: bold;">complete</span> with no errors
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Game.should start game on request
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Validation of text and scoring.should validate typed text
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Validation of text and scoring.should validate text with <span style="color: #000000;">2</span> errors
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Validation of text and scoring.should calculate score when typed text is <span style="color: #000000;">100</span><span style="color: #000000; font-weight: bold;">%</span> <span style="color: #7a0874; font-weight: bold;">complete</span>
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Validation of text and scoring.should calculate score when typed text is <span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">%</span> <span style="color: #7a0874; font-weight: bold;">complete</span>
Firefox <span style="color: #000000;">10.0</span> Mac OS <span style="color: #7a0874; font-weight: bold;">&#91;</span>PASSED<span style="color: #7a0874; font-weight: bold;">&#93;</span> Validation of text and scoring.should calculate score when typed text is incomplete
Total <span style="color: #000000;">10</span> tests <span style="color: #7a0874; font-weight: bold;">&#40;</span>Passed: <span style="color: #000000;">10</span>; Fails: <span style="color: #000000;">0</span>; Errors: <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">8.00</span> ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  Firefox <span style="color: #000000;">10.0</span> Mac OS: Run <span style="color: #000000;">10</span> tests <span style="color: #7a0874; font-weight: bold;">&#40;</span>Passed: <span style="color: #000000;">10</span>; Fails: <span style="color: #000000;">0</span>; Errors <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">8.00</span> ms<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<h2>Hva med klienten?</h2>
<p>Det er like enkelt å teste klientkode som serverkode, selv om man må hanskes med en DOM. Det avgjørende her er å gjøre klientkoden ”unobtrusive” og ikke mikse JavaScript og HTML-markup mer enn nødvendig.</p>
<p>Vi kan begynne med å tenke litt på hvordan markup’en på klienten skal se ut. Da spillet går ut på taste en gitt tekst, trenger vi i hvert fall et editerbart felt, og et element til å presentere tekst som skal tastes. I tillegg kan vi legge til en knapp for å starte en omgang, samt et element for å vise progress bars. Grensesnittet kan f.eks. se slik ut:</p>
<p style="text-align: left"><a href="http://open.bekk.no/wp-content/uploads/2012/02/gui.png"><img class="aligncenter size-full wp-image-8064" src="http://open.bekk.no/wp-content/uploads/2012/02/gui.png" alt="" width="618" height="539" /></a><br />
med tilhørende HTML:</p>
<pre>&lt;!DOCTYPE&gt;
&lt;html&gt;
  &lt;body&gt;
    &lt;div id="wrapper"&gt;
      &lt;h1&gt;iTouch&lt;/h1&gt;
      &lt;input id="name" type="text" placeholder="Skriv inn navnet ditt her og trykk ENTER"/&gt;
      &lt;button id="startButton"&gt;Start ny omgang (vent til alle er klare da)&lt;/button&gt;
      &lt;div id="text-to-be-typed"&gt;&lt;/div&gt;
      &lt;div id="typed-text" contenteditable="true"&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Med disse antakelsene, kan vi utvikle klientlogikken – <strong>test først</strong>.</p>
<p>Eksempelvis kan vi spesifisere at spillet skal startes når noen klikker på ”Start ny omgang”-knappen på følgende vis:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;should do start game when start button is clicked&quot;</span><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>
    spyOn<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">game</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;startGame&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">startButton</span>.<span style="color: #660066;">trigger</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;click&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    expect<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">game</span>.<span style="color: #660066;">startGame</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toHaveBeenCalled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">startButton</span><span style="color: #009900;">&#41;</span>.<span style="color: #000066; font-weight: bold;">is</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">':hidden'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toBeTruthy</span><span style="color: #009900;">&#40;</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></pre></div></div>

<p>Denne testen spesifiserer at startGame-funksjonen skal kalles, og at knappen skal skjules.<br />
$(this.startButton) er et jQuery-wrappet element som er definert slik:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">startButton</span> <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&lt;button&gt;&lt;/button&gt;&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
    id<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;startButton&quot;</span><span style="color: #339933;">,</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">appendTo</span><span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>og <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/spec/client/game_controller.spec.js#LC45" target="_blank">sprøytet inn i game_controller-modulens create-funksjon</a>.</p>
<p>Slik kan vi fortsette; ta f.eks. koden som tester at tekst fargelegges korrekt. Ganske avansert GUI-messig, og ganske enkelt å teste da man kan simulere nettleser-eventer, kjøre css-spørringer osv.:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;should color text upon text validation and update progress bar&quot;</span><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> self <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> originalText <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;Dette er en test&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> typedText <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;Dette er En&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> errorIndex <span style="color: #339933;">=</span> <span style="color: #CC0000;">9</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> clientId <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;123&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    spyOn<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">now</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;validate&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">andCallFake</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>
        self.<span style="color: #660066;">now</span>.<span style="color: #660066;">receiveScores</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
            clientId<span style="color: #339933;">:</span> clientId<span style="color: #339933;">,</span>
            <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Snorre&quot;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #3366CC;">&quot;errors&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>errorIndex<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
            <span style="color: #3366CC;">&quot;percentage&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">95</span>
        <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">game</span>.<span style="color: #660066;">now</span>.<span style="color: #660066;">displayTextToBeTyped</span><span style="color: #009900;">&#40;</span>originalText<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">typedTextElement</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>typedText<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">typedTextElement</span>.<span style="color: #660066;">trigger</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;keyup&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    expect<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">now</span>.<span style="color: #660066;">validate</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toHaveBeenCalled</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">textToBeTypedElement</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;:nth-child(1)&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;color&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;rgb(0, 128, 0)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">textToBeTypedElement</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;:nth-child(&quot;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>errorIndex <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;color&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;rgb(255, 0, 0)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    expect<span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">textToBeTypedElement</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;:nth-child(&quot;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>typedText.<span style="color: #660066;">length</span> <span style="color: #339933;">+</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;)&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;color&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;rgb(0, 0, 0)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    expect<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">wrapperElement</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#&quot;</span> <span style="color: #339933;">+</span> clientId<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;value&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toEqual</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">95</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></pre></div></div>

<p>Når man lager JavaScript-koden &#8220;unobtrusive&#8221; (i mangel av et bedre norsk ord), blir man kvitt all spagettikode man ofte ser i $(document).ready(), og sitter igjen med en <strong>ryddig</strong> <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/public/index.html" target="_blank">index.html</a>.</p>
<h2>Hmmm, hvorfor kjører vi alle testene i Firefox?</h2>
<p>Inntil nå, har vi kjørt klientestene og servertesten i kontekst av en nettleser via JS Test Driver. Da vi at vet at serverkoden skal kjøre på Node, gir det ikke mening å la ymse <a href="http://en.wikipedia.org/wiki/JavaScript_engine#JavaScript_engines" target="_blank">nettleser-JavaScript-motorer</a> - og ikke Nodes Google V8-baserte kjøretidsmiljø, tolke koden vår. Vi kan bote på dette ved å kjøre server testene med <a href="https://github.com/mhevery/jasmine-node" target="_blank">jasmine-node</a>. Dette er en Node.js-modul, som installeres med <a href="http://npmjs.org/" target="_blank">npm</a> (som nå bundles med Node-installasjonen). Da kan vi kjøre servertestene våre med:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">~<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>faggruppe<span style="color: #000000; font-weight: bold;">/</span>iTouch<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">git</span>::master<span style="color: #7a0874; font-weight: bold;">&#41;</span>:➔ jasmine-node spec<span style="color: #000000; font-weight: bold;">/</span>server <span style="color: #660033;">--verbose</span>
Started
..........
Spec Game
  it should massage original text
  it should validate text and distribute scores upon validation request
  it should NOT end game when text is errornous
  it should end game when text is <span style="color: #7a0874; font-weight: bold;">complete</span> with no errors
  it should start game on request
Spec Validation of text and scoring
  it should validate typed text
  it should validate text with <span style="color: #000000;">2</span> errors
  it should calculate score when typed text is <span style="color: #000000;">100</span><span style="color: #000000; font-weight: bold;">%</span> <span style="color: #7a0874; font-weight: bold;">complete</span>
  it should calculate score when typed text is <span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">%</span> <span style="color: #7a0874; font-weight: bold;">complete</span>
  it should calculate score when typed text is incomplete
Finished <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000;">0.005</span> seconds
<span style="color: #000000;">2</span> tests, <span style="color: #000000;">24</span> assertions, <span style="color: #000000;">0</span> failures</pre></div></div>

<p>Dette fremprovoserer også det faktum at vi er nødt til å gjøre om scoring.js-modulen til å være <a href="http://www.commonjs.org/">Node/CommonJS</a>-kompatibel, da Node krever dette. Dette gjøres ved å legge til disse linjene i scoring:</p>

<div class="wp_syntax"><div 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: #000066; font-weight: bold;">typeof</span> module <span style="color: #339933;">===</span> <span style="color: #3366CC;">'object'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    module.<span style="color: #660066;">exports</span> <span style="color: #339933;">=</span> TDD.<span style="color: #660066;">scoring</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Man kan da &#8220;hente&#8221; ut en referanse til scoring-modulen som en vanlig Node-modul slik:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">TDD.<span style="color: #660066;">scoring</span> <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;./src/server/scoring&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h2>Buster</h2>
<p>Her kommer vi tilbake til <a href="http://busterjs.org/" target="_blank">Buster.js</a>. I tillegg til å være et flott testrammeverk på andre måter, gir Buster deg mulighet til å <a href="http://busterjs.org/docs/hybrid-testing/" target="_blank">kjøre klient- og servertester med samme test runner</a>. Buster.js er snart ute av beta, blir spennende å sjekke det ut nærmere.</p>
<h2>Skru alt sammen</h2>
<p>Når all JavaScript-logikken er ferdig implementert, gjenstår konfigurasjon av Node, slik at vi kan begynne å teste spillet. All denne konfigurasjonen gjøres i filen <a href="https://github.com/snorrebrandstadmoen/iTouch/blob/master/app.js" target="_blank">app.js</a>. Her ser vi hvordan vi oppretter et game-objekt, med alle dets avhengigheter.</p>
<p>Her er et artig lite avbrekk i en ellers hektisk prosjekthverdag:<br />
<span style="text-align:center; display: block;"><a href="http://open.bekk.no/erfaringer-fra-testdrevet-javascript/"><img src="http://img.youtube.com/vi/kXEiXN3ezFI/2.jpg" alt="" /></a></span></p>
<h2>Oppsummering</h2>
<p>Å komme fra en typisk hverdag der jeg skriver &#8220;mvn clean install&#8221; altfor mange ganger i løpet av en dag, er det utrolig frigjørende å se hvor raskt disse JavaScript-testene kjører. Når man først kommer inn i det, er JavaScript en fornøyelse å jobbe med, spesielt med tanke på egenskapene ved språket. TDD i JavaScript er definitivt ikke vanskelig, og det er like greit å lære seg teknikkene først som sist.</p>
<h3>On a side note:</h3>
<p>Magnar Sveen snakker om zombietdd-prosjektet sitt <strong>i morgen på </strong><a href="http://www.meetup.com/framsia/events/49837362/" target="_blank"><strong>Framsia at CiA 2012 &#8211; Responsive, realtime and Zombies</strong>!</a> Meetup&#8217;en omhandler forøvrig Web Sockets og Node.js, så det er ikke helt urelatert til det som blir tatt opp her!</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/erfaringer-fra-testdrevet-javascript/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Getting started with JS and TDD</title>
		<link>http://open.bekk.no/getting-started-with-js-and-tdd/</link>
		<comments>http://open.bekk.no/getting-started-with-js-and-tdd/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 07:00:26 +0000</pubDate>
		<dc:creator>Torstein Nicolaysen</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Dynamiske språk]]></category>
		<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Kvalitet og testing]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[jasmine]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[jstestdriver]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[test-driven development]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=6436</guid>
		<description><![CDATA[Introduction Are you working on unmaintainable JavaScript code? Are you afraid to make changes to your 5000+ lines long JS file? If so, you&#8217;ve probably not written tests or done TDD. Fear not! Read on, and we will show you how to get started with writing tests and setting up the needed tools. We will [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Are you working on unmaintainable JavaScript code? Are you afraid to make changes to your 5000+ lines long JS file? If so, you&#8217;ve probably not written tests or done TDD. Fear not! Read on, and we will show you how to get started with writing tests and setting up the needed tools. We will show by example how to create a small, yet complex, JS web application using TDD.</p>
<p>JavaScript is becoming increasingly popular for developing full-fledged applications &#8211; both <a href="http://en.wikipedia.org/wiki/Nodejs">server</a> and client side. Looking at the current trend of how JS is used, we can see that it’s being used for business critical applications and large-scale applications. With all this popularity and extensive use, we are under the impression that the testing and quality focus is lagging behind.</p>
<p>After reading this blog post, you will know how to get started with JS TDD using tools and frameworks we consider easy to use and relatively mature. If you already know <strong>why</strong> you should test your JS code, feel free to skip the background.</p>
<p>If you want to take a closer look at the example application, feel free to check out the entire project from GitHub @ <a href="http://github.com/bekk/jstdd">http://github.com/bekk/jstdd</a>.</p>
<h2>Background</h2>
<p><img class="size-full wp-image-7874" src="http://open.bekk.no/wp-content/uploads/2012/01/JavaScript-logo.png" alt="The JavaScript logo" width="192" height="192" align="right" /> JavaScript has received a popularity boost from browser vendor’s quest to write the fastest JS engine, as well as the popular programming language <a href="http://en.wikipedia.org/wiki/Nodejs">node.js</a>. In addition, jQuery has simplified the way we interact with the DOM and smooths over annoying browser differences &#8211; making JS more accessible for everyday developers. Focus have been primarily on producing functionality, and not on testing and good design/clean code. We believe that one reason is the lack of standardized or commonly available testing tools and frameworks. Another reason might be that traditionally JS have been written by UI and UX developers, who’s focus have been primarily on functionality &#8211; not on <em>Clean Code</em> and testability.</p>
<p>JS and all other dynamic programming languages is in dire need of tests since there is no compile-time checking. Tests can be used to ensure that the application <strong>behaves as expected</strong>, and gives developers confidence to make changes to existing code. Despite the obvious need for testing, many developers skimp on writing tests when developing large JS applications. All the advantages of TDD that applies for other programming languages, also applies for JS. Who does not want testable, maintainable, readable, well-designed, modular and working code? It’s well established that TDD has positive effects on code quality (read the chapter on TDD by Robert C. Martin in <a href="http://www.amazon.com/Clean-Coder-Conduct-Professional-Programmers/dp/0137081073">The Clean Coder</a>).</p>
<p>Other popular programming languages like Java and C# have mature and well-documented testing-tools. At the time of writing, JS has <a href="http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#JavaScript">several testing frameworks available</a>, but only a handful mature. Looking at the options, no one really stands out as a clear choice. To make things worse, getting started with JavaScript TDD can be challenging. There are so many ways of going about setting up a complete test-environment for JS. We have looked into this and had some experience with what works and what doesn&#8217;t.</p>
<h2>The runner</h2>
<p><a href="http://code.google.com/p/js-test-driver/">JsTestDriver</a> is (as it’s name implies) a tool that let you run your JS tests. You can run your tests directly from your favorite IDE (at least in theory) to get into your TDD rhythm. It runs from the command line and even on your continuous integration server. In our examples we’ll be running it from the command line.</p>
<p>A quote from their home site says it all: “The goal of JS Test Driver is to make JavaScript unit test development as seamless as and easy as Java unit tests.”</p>
<p>JsTestDriver supports testing in different browsers through capturing browsers as a slave machines. It includes it’s own limited assertion framework, but also supports add-ons, which opens for a wide range of <a href="http://code.google.com/p/js-test-driver/wiki/XUnitCompatibility">third party</a> assertion frameworks. We will be using Jasmine BDD through an adapter.</p>
<p>As with everything else, there is room for improvement. JsTestDriver&#8217;s configuration can sometimes be too simple, and advanced users may feel limited. In our simple example it works great, but expect some issues when scaling up. As a note, we did not get the IDE integration in IntelliJ IDEA to work properly.</p>
<p>Recently Buster.js was released as beta, and is worth checking out as an alternative to JsTestDriver.</p>
<h2>The framework</h2>
<p><img class="size-full wp-image-7875" src="http://open.bekk.no/wp-content/uploads/2012/01/jasmine_logo.png" alt="The Jasmine logo" width="282" height="90" align="right" /> We’ve picked out <a href="http://pivotal.github.com/jasmine/">Jasmine</a> because it is a mature (compared to most other frameworks) and a popular testing framework for JS. It features BDD syntax, which gives clear and readable tests with functionality in focus. It does not depend on any other framework and does not require a DOM. It can be run in the browser, through JsTestDriver or through node.js. It is well documented and is easy to get started with.</p>
<p>There are a few things to consider. They don’t separate between mocks, stubs and spies. All of that is packed into what Jasmine describes as a spy. The bundled matchers are good, but few. To get readable tests, it’s often necessary to write custom matchers to match the domain language. Still, we consider this one of the few viable options for doing TDD in JS.</p>
<p><a href="https://github.com/pivotal/jasmine/wiki">Installing, setting up and using Jasmine</a> is easy, and will not be detailed here. We’re using Jasmine through JsTestDriver, and have configured it thereafter.</p>
<p>QUnit was considered as an option, but it’s syntax did not help us achieve as readable and clear tests as Jasmine. It’s simplicity makes it very attractive and useful for beginners, but more advanced users will want more.</p>
<h2>Demo application</h2>
<p>As stated in the introduction, we’ll make a little application that does an “I feel lucky” search from Flickr. One of the choices we made was to have a minimal setup. No jQuery and third-party libraries in the production code, with the intention to reduce complexity and make the example more transparent as to how things work.</p>
<h3>Pre-requisites</h3>
<p>If you want to use the same setup as us, we recommend doing the following.<br />
(Or you can check out the entire project from GitHub @ <a href="http://github.com/bekk/jstdd">http://github.com/bekk/jstdd</a>).</p>
<h3>Download these libraries:</h3>
<ul>
<li><a href="https://github.com/ibolmo/jasmine-jstd-adapter">https://github.com/ibolmo/jasmine-jstd-adapter</a> (version 1.1.1)</li>
<li><a href="https://github.com/pivotal/jasmine">https://github.com/pivotal/jasmine</a> (version 1.0.1)</li>
<li><a href="http://code.google.com/p/js-test-driver/">http://code.google.com/p/js-test-driver/</a> (version 1.3.2)</li>
</ul>
<p>Create the following folder structure:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">.
├── lib<span style="color: #000000; font-weight: bold;">/</span> <span style="color: #666666; font-style: italic;"># 3rd party libs lies here</span>
│   ├── jasmine.js
│   ├── jasmine-jstd-adapter<span style="color: #000000; font-weight: bold;">/</span>
│   └── JsTestDriver-1.3.2.jar
├── spec<span style="color: #000000; font-weight: bold;">/</span> <span style="color: #666666; font-style: italic;"># test/specs lies here</span>
├── src<span style="color: #000000; font-weight: bold;">/</span>  <span style="color: #666666; font-style: italic;"># application source lies here</span>
├── server.sh <span style="color: #666666; font-style: italic;"># Starts a JSTD server (symlinked)</span>
├── test.sh <span style="color: #666666; font-style: italic;"># Runs the test (symlinked)</span>
└── jsTestDriver.conf <span style="color: #666666; font-style: italic;"># JSTD configuration for our project</span></pre></div></div>

<p>server.sh and test.sh are just shortcuts to scripts bundled with js-test-driver.</p>
<p>Configure jsTestDriver.conf to match your setup.</p>
<h3>Getting familiar with the framework</h3>
<p>We started off with a simple test to get familiar with the syntax and to verify that everything is set up correctly. Consider it a warm-up exercise.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">describe<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Jasmine&quot;</span><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>
    it<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;makes testing JavaScript awesome!&quot;</span><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>
        expect<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toBeTruthy</span><span style="color: #009900;">&#40;</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: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h3>Running it</h3>
<p>Running it the first time might seem a bit overly hard, but once you’re set up it’s easy to run the tests. Before you start the server, you need to write a little config file. Take a <a href="https://github.com/bekk/jstdd/blob/master/jsTestDriver.conf">look at ours</a> if you need an example.<br />
Starting the server can seem a bit tedious, but we found a shell-script that starts the server. All we had to do was modify the path to suit our project structure (see <a href="https://github.com/bekk/jstdd/blob/master/server.sh">server.sh</a>). Running it is just a matter of typing ./server and seconds later the server is up and running.</p>
<p>Example output from a test run:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">Running all tests
Chrome: Runner reset.
....
Total <span style="color: #000000;">1</span> tests <span style="color: #7a0874; font-weight: bold;">&#40;</span>Passed: <span style="color: #000000;">1</span>; Fails: <span style="color: #000000;">0</span>; Errors: <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">1.00</span> ms<span style="color: #7a0874; font-weight: bold;">&#41;</span>
Chrome 12.0.742.112 Mac OS: Run <span style="color: #000000;">4</span> tests <span style="color: #7a0874; font-weight: bold;">&#40;</span>Passed: <span style="color: #000000;">1</span>; Fails: <span style="color: #000000;">0</span>; Errors <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">1.00</span> ms<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Next task is capturing browsers. We spun up browsers on each others computers and went to http://[my address]:9876/capture and the browser became a slave. Excellent! We used Safari, Firefox and Chrome to test. Make sure to keep the browser running while testing.</p>
<div id="attachment_6928" class="wp-caption aligncenter" style="width: 310px"><a href="http://open.bekk.no/wp-content/uploads/2011/10/Screen-shot-2011-10-21-at-18.04.51.png"><img class="size-medium wp-image-6928 " src="http://open.bekk.no/wp-content/uploads/2011/10/Screen-shot-2011-10-21-at-18.04.51-300x133.png" alt="Screenshot from captured browser" width="300" height="133" /></a><p class="wp-caption-text">Captured browser</p></div>
<p>JsTestDriver supports distributed test-running, but that is not something we will explore in this blog post. Now all that is left is telling the server to ask the browsers to run the tests. With the scripts, it’s just a matter of typing ./test in the shell and the tests are run.</p>
<p>The flow for starting the first time is the following:<br />
1. Start server<br />
2. Capture browsers<br />
3. Run tests</p>
<p>After than you just type ./test each time you want to run the tests.</p>
<h3>Working on LuckyFlickr</h3>
<h4>Start with the tests</h4>
<p>We decided to start with writing tests to verify output on the result page. The simplest possible test we could think of was to test for a message when no result was found.</p>
<p>Next, we added a new test to verify that if a result were received, the parser would pick the first result and display the image on the result page. Since we were doing unit testing we didn’t want to go all the way to Flickr when we ran the test, so we created a <a href="https://github.com/bekk/jstdd/blob/master/spec/result-stub.js">simple stub</a> that returned some JSON data on the expected flickr format so we could run the test in isolation. The specs for the parser read:</p>
<ul>
<li>&#8220;outputting result&#8221;</li>
<ul>
<li>&#8220;should not output an image when there are no results&#8221;</li>
<li>&#8220;should output the image from the result&#8221;</li>
</ul>
</ul>
<p dir="ltr">Note: When reading these specs, read them like “Outputting result should not output an image when there are no results”.</p>
<p>When pondering what to do next, we figured we could create a test for the component that would fetch data from flickr. Since we wanted to get out data from another site, we decided to use JSONP to overcome the cross-site problem. We also wanted the component to send the flickr request asynchronously, so we had to write a test that would handle that. To fix this we created setup code to temporarily replace the default XMLHttpRequest implementation in JS with our own. That way we could control what the response would be. We decided to let it respond with the same JSON stub as in the parser test.</p>
<ul>
<li>“when querying flickr”</li>
<ul>
<li>&#8220;should create a global function that handles the JSON-P callback&#8221;</li>
<li>“should do a search and call the callback function”</li>
</ul>
</ul>
<p>The last step was to create some tests to make sure the GUI was displaying the result in the right container in the result page. On this step, we saw that some of the components came together, and introduced the need for mocking. We mocked the result given by the “fetcher”. Doing so, we’re not dependent on a connection to flickr.com. We created 2 tests for this. The first asserts that the result from flickr is displayed in the result container, and the second one asserts that “Loading” is displayed while it is fetching data from flickr.</p>
<h4>The result</h4>
<p>Since our focus was unit testing, our implementation ended out with three separate “units” that each did one important thing. We have a “fetcher” that goes out and fetches the result from Flickr, a “result parser” that knows how to parse the JSON data structure from Flickr and finally the component that enables the user to do a search. No enterprisy patterns, no unneeded complexity, no silver bullets. Just enough to make things work. Also, the design emerged from writing the tests first.</p>
<h2>Our experiences</h2>
<p>We experienced a couple of notable challenges when doing TDD in JS. Doing TDD in it self is not a problem. Some challenges appear when doing browser-specific things with JS. Such as asynchronous callbacks, handling the DOM and the AJAX browser API.</p>
<p>The DOM is an issue. When not using jQuery, there are a lot of quirks that can mess up tests in specific browsers. Also, doing DOM-operations without jQuery results in a lot of ugly code that affects readability.</p>
<p>Testing AJAX without support from the test framework is problematic, and is why several tools exist and mitigate this (Sinon.js, Mockjax, etc.). Before we changed to JSONP, we wanted to do this with no extra support, and ended up with an extremely simplified version of what the mentioned tools provide. But for most people it would be simpler to use an existing tool to help you do AJAX-testing.</p>
<p>But all these things mentioned above are relatively easy to overcome and the upside of being able to write tests for your JS code easily outweighs the small quirks you may experience. And you won’t regret spending time on writing tests when your code base is expanding and you need to make a change.</p>
<h2>Give me more!</h2>
<p><a href="http://sinonjs.org/">Sinon.JS</a> &#8211; Standalone test spies, stubs and mocks for JavaScript. Works with any unit testing framework.<br />
<a href="http://docs.jquery.com/Qunit">QUnit</a> &#8211; alternative to Jasmine. Developed by the jQuery-team<br />
<a href="https://github.com/cucumber/cucumber-js">Cucumber.JS</a> &#8211; early stages. Could be good.<br />
<a href="http://busterjs.org/">Buster.js</a> &#8211; a new test framework (currently in beta) from Christan Johansen (the man behind Sinon.js)</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/getting-started-with-js-and-tdd/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>MVC med Sammy og Handlebars</title>
		<link>http://open.bekk.no/mvc-med-sammy-og-handlebars/</link>
		<comments>http://open.bekk.no/mvc-med-sammy-og-handlebars/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 11:51:08 +0000</pubDate>
		<dc:creator>Hans Magnus Inderberg</dc:creator>
				<category><![CDATA[Dynamiske språk]]></category>
		<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mvc]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=7807</guid>
		<description><![CDATA[I disse dager hvor server-side er ut og klient-side er kult har det dukket opp mange avanserte JavaScript-rammeverk som flytter kompleksitet fra serveren til nettleseren. Backbone, Knockout og JavaScriptMVC er alle gode eksempler som kan brukes til å lage komplekse applikasjoner, uten antikvariske operasjoner som lasting av hele sider eller rendering av HTML på serveren. I denne [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://open.bekk.no/wp-content/uploads/2012/01/sammy.png"><img src="http://open.bekk.no/wp-content/uploads/2012/01/sammy.png" alt="" width="748" height="150" /></a></p>
<p>I disse dager hvor server-side er ut og klient-side er kult har det dukket opp mange avanserte JavaScript-rammeverk som flytter kompleksitet fra serveren til nettleseren. <a href="http://documentcloud.github.com/backbone/">Backbone</a>, <a href="http://knockoutjs.com/">Knockout</a> og <a href="http://javascriptmvc.com/">JavaScriptMVC</a> er alle gode eksempler som kan brukes til å lage komplekse applikasjoner, uten antikvariske operasjoner som lasting av hele sider eller rendering av HTML på serveren. I denne nye verden tilbyr serveren et REST-API, og all koden for å bruke dette API-et er Javascript som kjøres av brukerens nettleser.</p>
<p>Vi vil gjerne presentere én metode for å strukturere komplekse JS-applikasjoner, sammen med to flotte biblioteker: <a href="http://sammyjs.org/">Sammy</a> og <a href="http://handlebarsjs.com/">Handlebars</a>.</p>
<p><strong>Sammy</strong> er ikke like kjent eller kraftig som de tidligere nevnte rammeverkene, men er likevel svært godt til sitt bruksområde og fortjener en vurdering ved valg av rammeverk. Hovedsakelig brukes Sammy til routing, hvor en URL besvares av en JS-funksjon, og til å rendre HTML-en som skal vises på den aktuelle siden. Biblioteket er i seg selv svært lite, og delegerer det meste av funksjonalitet til sin strålende plugin-arkitektur. I dag er Sammy tungt avhengig av jQuery.</p>
<p><strong>Handlebars</strong> har den siste tiden fått masse oppmerksomhet, og bygger på det allerede kjente template-rammeverket Mustache. Handlebars brukes til å sammenflette data og HTML på en enklere og strukturert måte. Hensikten er å skille HTML- og DOM-maipulasjon fra resten av applikasjonen, og Handlebars inneholder mange hjelpemetoder som gjør dette ganske elegant.</p>
<p><strong>Model-View-Controller (MVC)</strong> er en type arkitektur som kan brukes til komplekse klient-side JS applikasjoner. I vår (svært) løse definisjon av MVC får vi følgende struktur:</p>
<ul style="font-size: 120%; line-height: 1.7em;">
<li><em>Datamodellene </em>håndterer entiteter og kommunikasjon med serveren.</li>
<li><em>View-modellene står </em>for oppførselen og strukturen til HTML-elementene.</li>
<li><em>Controllerene</em> knytter datamodeller og view-modeller sammen mot spesifikke URL-er.</li>
</ul>
<p>God struktur er vanskelig i komplekse JS-applikasjoner. Språket gir store muligheter og få begrensninger, og ingen forslag til hvordan strukturen bør være. Det hele kan fort bli uoversiktelig hvis man ikke baserer seg på velkjent struktur, som for eksempel MVC. I denne teksten bygger vi deler av en slik applikasjon.</p>
<p>I eksempelet har serveren en liste personer, som vi ønsker å få tak i, instansiere som modeller og vise en liste av i nettleseren. All kode i denne bloggposten kommer fra <a href="https://github.com/hinderberg/sammy-handlebars-blog-example">en minimal eksempelapplikasjon du finner på Github</a>. Last den gjerne ned og prøv resultatet i din nettleser. Koden kan også brukes som refferanse om det er noe som er uklart i teksten.</p>
<h2>Datamodeller og API-kall</h2>
<hr />
<p><a href="http://open.bekk.no/wp-content/uploads/2012/01/neurons.png"><img class="alignnone size-full wp-image-7919" src="http://open.bekk.no/wp-content/uploads/2012/01/neurons.png" alt="" width="748" height="150" /></a></p>
<p>Datamodellene tar seg av kommunikasjon med serveren via Ajax-baserte HTTP-kall mot et REST-API. Det er mange måter dette kan gjøres på, det finnes ingen fasit, men her kommer ett eksempel. Her har vi kodet modellene selv, men merk at på samme måte som Handlebars tar seg av templates, og Sammy tar seg av controller-ene, kunne vi brukt et tredje bibliotek til å ta seg av datamodellene. Men la oss lage noe selv.</p>
<p>Noen vil kanskje reagere på at datamodeller her potensielt defineres to steder &#8212; hos klienten og på serveren &#8212; men det er viktig å huske at disse modellene har lite felles funksjonalitet. Datamodellene på klientsiden er der utelukkende for å hjelpe view-modellene, ved å abstrahere bort funksjonalitet for kommunikasjon med serveren, formatering av modelldata og lignende.</p>
<p>Det er to <em>oppgaver</em> som kan skilles i datamodellene:</p>
<ul style="font-size: 120%; line-height: 1.7em;">
<li>Selve datamodellene som instansieres og har metoder for å jobbe med hver entitet,</li>
<li>og statiske metoder for hver klasse av modeller, som blant annet gjør API-kall.</li>
</ul>
<p>Vi har valgt å bruke standard prorotype-baserte JS objekter. I dette eksempelet lager vi en modell kalt “person”, lagt under namespacet “myapp.models”.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/* prototype for alle data-modeller. */</span>
myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">datamodel</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009966; font-style: italic;">/* Metode for å instansiere en modell. */</span>
myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">create</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>prototype<span style="color: #339933;">,</span> properties<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">merge</span><span style="color: #009900;">&#40;</span>Object.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>prototype<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> properties<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009966; font-style: italic;">/* Prototype for person-instanser. */</span>
myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">person</span> <span style="color: #339933;">=</span> myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">datamodel</span><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: #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: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">firstname</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot; &quot;</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">lastname</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009966; font-style: italic;">/* Instansiering. */</span>
<span style="color: #003366; font-weight: bold;">var</span> person <span style="color: #339933;">=</span> myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">person</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> 
    firstname<span style="color: #339933;">:</span> “Foo”<span style="color: #339933;">,</span> 
    lastname<span style="color: #339933;">:</span> “Bar” 
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Som sagt kan API-kall tilhørende hver modell skilles ut i egne moduler. Dette er flott når man skal teste systemet, og hjelper holde kompleksiteten nede. Her er et enkelt eksempel på API-kall for modellen:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/* Metode for å lage mange instanser. */</span>
myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">createAll</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>prototype<span style="color: #339933;">,</span> propertiesList<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">return</span> propertiesList.<span style="color: #660066;">map</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>properties<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>prototype<span style="color: #339933;">,</span> properties<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: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009966; font-style: italic;">/* Metoder for å gjøre kall mot person-API. */</span>
myapp.<span style="color: #660066;">api</span>.<span style="color: #660066;">person</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
    all<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #009966; font-style: italic;">/* Hent listen over alle personer fra serveren. */</span>
        $.<span style="color: #660066;">ajax</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> 
	    success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>serverdata<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                callback<span style="color: #009900;">&#40;</span>myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">createAll</span><span style="color: #009900;">&#40;</span>
                    myapp.<span style="color: #660066;">models</span>.<span style="color: #660066;">person</span><span style="color: #339933;">,</span> 
                    serverdata<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>
            ........
        <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;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009966; font-style: italic;">/* Bruk */</span>
myapp.<span style="color: #660066;">api</span>.<span style="color: #660066;">person</span>.<span style="color: #660066;">all</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>people<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #009966; font-style: italic;">/* “people” er her et array av person-instanser. */</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Dette kan virke som mye kode for enkle operasjoner, men etterhvert som applikasjonen blir større er det fint å ha alt som har med serverkommunikasjon og datamodeller skilt fra resten av applikasjonen. La oss nå se hvordan disse datamodellene kan kobles sammen med rendring av HTML.</p>
<p>&nbsp;</p>
<h2>View-modeller med Handlebars</h2>
<hr />
<p><a href="http://open.bekk.no/wp-content/uploads/2012/01/handlebars1.png"><img class="alignnone size-full wp-image-7913" src="http://open.bekk.no/wp-content/uploads/2012/01/handlebars1.png" alt="" width="748" height="120" /></a></p>
<p>View-modellene knytter data sammen med HTML. Disse modellene holder på dataene som trengs for å vise en side, representert av datamodellene. I tillegg legger view-modellene på oppførsel, animasjoner og hendelser på siden-, eller delen av siden de representerer. Dette kan for eksempel være ting som skal skje når brukeren klikker på en link, flytter på elementer eller vil lagre eller endre data.</p>
<p>Poenget med å bruke view-modeller er å abstrahere bort alt som omhandler hvordan HTML skal produseres og oppføre seg. På samme måte som datamodellene innkapsulerer alt som har med entiteter og server-kall, tar view-modellene seg av all JS-kode som manipulerer DOM-en direkte. Målet er som alltid å ende opp med veldefinerte og klart avskillte moduler med hver sine oppgaver. Her er et eksempel på en view-modell:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">myapp.<span style="color: #660066;">view</span>.<span style="color: #660066;">people</span> <span style="color: #339933;">=</span> myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">viewmodel</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>
    compile<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: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#123;</span> people<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">people</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    apply<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: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#people li&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</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: #339933;">+</span> <span style="color: #3366CC;">&quot; clicked!&quot;</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: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>En view-modell jobber i to faser og trenger to forskjellige metoder. For det første har vi compile-metoden, som returnerer alle variabler som skal kunne brukes fra template-filen. Deretter har vi apply-metoden, som kalles etter at template filen har blitt renderet.</p>
<p>Den første metoden gjør altså klar variabler som skal brukes, mens den andre tar seg av all DOM-manipuilasjon etter at HTML-en er rendret. <em>Apply-metodene til view-modellene er altså de eneste stedene i applikasjonen JS-kode jobber direkte med HTML-elementer, noe som gjør det hele svært ryddig</em>. Se eksempelapplikasjonen på GitHub [g] for mer av koden som jobber med view-modeller.</p>
<p>View-modellen jobber med en eller flere template-filer, som spesifiserer strukturen på markup-en til den aktuelle siden. Her er et eksempel på en slik template-fil:</p>

<div class="wp_syntax"><div class="code"><pre class="handlebar" style="font-family:monospace;">&lt;div id=&quot;content&quot;&gt;
{{ &gt;search }}
    &lt;ul id=&quot;people&quot;&gt;
    {{ #each people }}
        &lt;li&gt;{{ name }}&lt;/li&gt;
    {{ /each }}
    &lt;/ul&gt;
&lt;/div&gt;</pre></div></div>

<p>I Handlebars bruker man Handlebar Expressions til å hente ut objekter ved å skrive {<em>{ objektnavn }}</em>, eller <em>{{{ objektnavn }}}</em> når man ønsker å un-escape. <em>people</em> er definert av view-modellen og brukes direkte i template-filen. <em>name</em> er definert av data-modellen for person-entiteten, som også brukes direkte i dette templatet.</p>
<p>I templaten har vi også en partial komponent, kalt <em>search</em>. Partials vil bli brukt der man ønsker å dele opp templates og lage gjenbrukbare deler som kan brukes på tvers av andre templates. Partial-templaten vil også ha direkte tilgang til view-modellen og dens innhold, men vil som oftest tilhøre en egen view-modell.</p>
<p>I tillegg til å kunne hente ut objekter og kjøre funksjoner, kan man bruke såkalte Block Expressions. Block Expressions gjør det mulig å kjøre Block Helpers som er hjelpefunksjoner for å eksempelvis gjøre operasjoner med lister og sjekke verdier med if/else spørringer. Handlebars kommer med ett sett innebygde helpers, men man kan også lage sine egne om dette skulle være nødvendig.</p>
<p>Her er et eksempel på en Block Helper, som kjører en loop inntil et visst maksimalt antall ganger:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/* Definering av en egen hjelpemetode kalt “until”. */</span>
Handlebars.<span style="color: #660066;">registerHelper</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'until'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>context<span style="color: #339933;">,</span> block<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> max <span style="color: #339933;">=</span> block.<span style="color: #660066;">hash</span>.<span style="color: #660066;">max</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> ret <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> j <span style="color: #339933;">=</span> context.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> j<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">&gt;=</span> max<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> ret<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span>
        ret <span style="color: #339933;">=</span> ret <span style="color: #339933;">+</span> block<span style="color: #009900;">&#40;</span>context<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066; font-weight: bold;">return</span> ret<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="handlebar" style="font-family:monospace;">/* Bruk av denne hjelpemetoden i en template-fil. */
{{ #until persons max=&quot;3&quot; }}
    {{ name }}
{{ /until }}</pre></div></div>

<p>En annen interessant mulighet man har i Handlebars er å gjøre kall mot parent-objektet til det objektet man jobber med. Her er et eksempel hvor vi bruker notasjonen “../” til å aksessere en variabel som tilhører parent-objektet til det vi looper gjennom:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/* Variabel definert i view-modellen. */</span>
<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">family</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> surname<span style="color: #339933;">:</span> “I skogen”<span style="color: #339933;">,</span> members<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
    <span style="color: #009900;">&#123;</span> <span style="color: #000066;">name</span><span style="color: #339933;">:</span> “Hans”<span style="color: #339933;">,</span> age<span style="color: #339933;">:</span> “<span style="color: #CC0000;">90</span>” <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span> <span style="color: #000066;">name</span><span style="color: #339933;">:</span> “Grete”<span style="color: #339933;">,</span> age<span style="color: #339933;">:</span> “<span style="color: #CC0000;">100</span>” <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span> <span style="color: #000066;">name</span><span style="color: #339933;">:</span> “Ulven”<span style="color: #339933;">,</span> age<span style="color: #339933;">:</span> “<span style="color: #CC0000;">120</span>” <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="handlebar" style="font-family:monospace;">/* Bruk av variabelen i template-filen. */
{{ #each family.members }}
    {{ name }} {{ ../surname }}
{{ /each }}</pre></div></div>

<p>Dette er selvfølgelig bare noen få av muligheten man har med Handlebars, men de viser hvordan komplekse templates kan spesifiseres i template-filer som jobber direkte mot en view-modell. Dette sørger for praktisk innkapsulering av alt som dreier seg om HTML og DOM-elementer i applikasjonen.</p>
<p>La oss nå se hvordan det hele kobles sammen ved hjelp av controller-ene og Sammy.</p>
<h2>Controllere med Sammy</h2>
<hr />
<p><a href="http://open.bekk.no/wp-content/uploads/2012/01/sammy.png"><img class="alignnone size-full wp-image-7916" src="http://open.bekk.no/wp-content/uploads/2012/01/sammy.png" alt="" width="748" height="150" /></a></p>
<p>Controller-ene er selve limet som holder applikasjonen sammen. Disse beskriver hva som skal skje når en bruker besøker en URL. Controlleren bruker datamodellene til å hente data som trengs på den aktuelle siden, og rendrer HTML ved hjelp av de tidligere nevnte view-modellene og deres representative template filer. Vi trenger både routing og template-rendring, altså er dette en perfekt oppgave for Sammy.</p>
<div style="background-color: #eee; line-height: 1.7em; padding: 1.5em; font-size: 120%; margin-bottom: 1em;">For å få et inntrykk av hva mer enn dette Sammy kan brukes til er det bare å se på listen over tilgjengelige <a href="https://github.com/quirkey/sammy/tree/master/lib/plugins">plugins</a>. Eksempler inkluderer templating med mange forskjellige biblioteker, Form Builder som minner om hvordan Ruby on Rails setter opp skjemaer, Storage som innkapsulerer mange forskjellige lokale lagringsmetoder i et enkelt API, eller OAuth-pluginen, forklart av sitt eget navn.</div>
<p>Vi ønsker å bruke Sammy-spesifikk kode utelukkende i controller-ene, og ikke i andre deler av applikasjonen. På denne måten vil minst mulig av applikasjonen bli avhengig av dette rammeverket, i tilfelle man skulle ønske bytte det ut på et senere tidspunkt. I tillegg blir applikasjonen enklere å teste, spesielt på enhetsnivå, da vi ikke trenger å bry oss om Sammy annet enn i controller-ene.</p>
<p>Her er en kodebit som kjøres når brukeren gjør en GET-request mot URL-en “/#people”:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/* Jobb på HTML-elementet “#page”. */</span>
$.<span style="color: #660066;">sammy</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#page&quot;</span><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: #009966; font-style: italic;">/* Bruk Handlebars-plugin. */</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #003366; font-weight: bold;">use</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Handlebars'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'hb'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009966; font-style: italic;">/* Start routes. */</span>
    myapp.<span style="color: #660066;">route</span>.<span style="color: #660066;">person</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</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: #660066;">run</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #009966; font-style: italic;">/* Route for person-listen. */</span>
myapp.<span style="color: #660066;">route</span>.<span style="color: #660066;">person</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>app<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #009966; font-style: italic;">/* Definer en route. */</span>
    app.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&quot;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>context<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #009966; font-style: italic;">/* Gjør et kall mot serveren. */</span>
        myapp.<span style="color: #660066;">api</span>.<span style="color: #660066;">person</span>.<span style="color: #660066;">all</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>people<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
            <span style="color: #009966; font-style: italic;">/* Definer hvilken template-filer som trengs. */</span>
            <span style="color: #003366; font-weight: bold;">var</span> template <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;template/person-list.hb&quot;</span><span style="color: #339933;">;</span>
            <span style="color: #003366; font-weight: bold;">var</span> partials <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> searchbox<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;template/shared/searchbox.hb&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #009966; font-style: italic;">/* Instansierer view-modellene */</span>
            <span style="color: #003366; font-weight: bold;">var</span> search <span style="color: #339933;">=</span> myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>myapp.<span style="color: #660066;">view</span>.<span style="color: #660066;">shared</span>.<span style="color: #660066;">searchbox</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #003366; font-weight: bold;">var</span> list <span style="color: #339933;">=</span> myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span>myapp.<span style="color: #660066;">view</span>.<span style="color: #660066;">people</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> people<span style="color: #339933;">:</span> people <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #009966; font-style: italic;">/* Bytt ut innholdet i &quot;#page&quot; med ny HTML. */</span>
            context.<span style="color: #660066;">renderAll</span><span style="color: #009900;">&#40;</span>template<span style="color: #339933;">,</span> partials<span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span>list<span style="color: #339933;">,</span> search<span style="color: #009900;">&#93;</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: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Den første kodebiten sier at Sammy skal jobbe på HTML-elementet med ID-en “page”, definert i den initsielle HTML-filen. Del to tar tak i URL-en ved hjelp av en <em>route</em>-funksjon. En <em>route</em> består av et <em>verb</em>, en <em>sti</em>, og en <em>callback-funksjon</em>. Verbet er et av de velkjente HTTP-metodene POST, PUT, GET eller DELETE. Stien kan enten være en vanlig URL, eller en hash-basert URL som i dette eksempelet.</p>
<p>Hver Sammy-rute tar inn et context-objekt som inneholder mye informasjon om tilstanden til applikasjonen. Dette objektet inneholder også mange nyttige hjelpefunksjoner. For at applikasjonen skal holde seg modulær er det viktig å kunn bruke dette objektet i controllerene. Hvis context-objektet blir med til datamodellene eller view-modellene, vil disse bli avhengig av Sammy-logikk, som igjen vil komplisere testing og vedlikehold.</p>
<p>Det meste skjer i context.renderAll-metoden. Denne rendrer et template, et sett partials og en samling view-modeller ved hjelp av Sammy’s context-render-metode:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">context.<span style="color: #660066;">helpers</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #009966; font-style: italic;">/* En hjelpefunksjon for å rendre sider med mange view-modeller. */</span>
    renderAll<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>tmpl<span style="color: #339933;">,</span> partials<span style="color: #339933;">,</span> models<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
       	<span style="color: #003366; font-weight: bold;">var</span> context <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span>
       	<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span>tmpl<span style="color: #339933;">,</span> myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">compileAll</span><span style="color: #009900;">&#40;</span>models<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>html<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            context.<span style="color: #660066;">swap</span><span style="color: #009900;">&#40;</span>html<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            myapp.<span style="color: #660066;">model</span>.<span style="color: #660066;">applyAll</span><span style="color: #009900;">&#40;</span>models<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> partials<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;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><em>context.render</em> tar først inn stien til template-filen man vil bruke. Det neste argumentet er dataene man vil bruke til å rendre template-filen, i vårt tilfelle representert dataene av en view-modell. Denne view-modellen vil da være tilgjengelig for template-filen når den rendres av Handlebars-pluginen til Sammy.</p>
<p>Callback-argumentet <em>context.swap</em> tar imot ferdig rendret HTML, og bytter ut hva som allerede er i elementet som jobbes på (“#<em>page</em>”) med den nye HTML-en.</p>
<p>Det siste argumentet, “partials”, er et objekt som kan inneholde flere deler som hovedtemplaten er avhengig av, for eksempel en topp, meny og bunn. Render-metoden cacher template-filene, uten å laste de på nytt hver gang, slik at operasjonen blir kjappere andre gang denne kalles.</p>
<p>En fin måte å organisere disse Sammy-routene på er å ha én JS-fil pr side (hvis det gir mening i applikasjonens sidestruktur, vel å merke). Metoden <em>$.sammy</em> kan brukes på tvers av filer uten problemer. Hver side får ofte flere routes for forskjellige operasjoner, for eksempel:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/* settings.js: routes for én side. */</span>
&nbsp;
$.<span style="color: #660066;">sammy</span><span style="color: #009900;">&#40;</span>“#page”<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: #006600; font-style: italic;">// Vise innstillinger</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span>“#<span style="color: #339933;">/</span>settings<span style="color: #339933;">/</span>profile”<span style="color: #339933;">,</span>  <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>context<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> … <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span>“#<span style="color: #339933;">/</span>settings<span style="color: #339933;">/</span>friends”<span style="color: #339933;">,</span>  <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>context<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> … <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">// Lagre innstillinger</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">put</span><span style="color: #009900;">&#40;</span>“#<span style="color: #339933;">/</span>settings<span style="color: #339933;">/</span>profile”<span style="color: #339933;">,</span>  <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>context<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> … <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">post</span><span style="color: #009900;">&#40;</span>“#<span style="color: #339933;">/</span>settings<span style="color: #339933;">/</span>friends”<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>context<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</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></pre></div></div>

<p>Med controllerene på plass er applikasjonens struktur komplett:</p>
<ul style="font-size: 120%; line-height: 1.7em;">
<li><strong>Datamodellene</strong> innkapsulerer alt som beskriver entiteter og serverkall.</li>
<li><strong>View-modellene</strong> innkapsulerer alt som beskriver HTML-en og oppførselen til DOM-elementer, og kobler dette med datamodellene.</li>
<li><strong>Controllerene</strong> tar det hele i bruk og bruker datamodellene og view-modellene til å rendre flott HTML når brukerne besøker forskjellige URL-er.</li>
</ul>
<h2></h2>
<h2>Oppsummering</h2>
<hr />
<p>Selv om en struktur som den presentert her kan virke overdrevet i starten av et prosjekt, vil det hjelpe etterhvert som kompleksiteten og kodemengden øker. Det viktigste er å starte med et godt utgangspunkt, og deretter kontinuerlig forbedre og utvikle arkitekturen.</p>
<p>Det er selvfølgeilig ulemper med tunge JS-applikasjoner. De setter store krav til nettleserens JS-motor, og til utviklernes testing på tvers av mange nettlesere. Språkets frie natur gjør det enkelt å skrive lite vedlikeholdbar kode, og det er sjelden klare svar på hvordan noe bør gjøres.</p>
<p>Til syvende å sist krever komplekse JS-applikasjoner mye av disiplin innen struktur og testing, men denne friheten betyr også at JS-programmering er veldig spennende. Med gode biblioteker som Sammy og Handlebars blir det hele enda morsommere.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/mvc-med-sammy-og-handlebars/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Responsive design med Enonic CMS</title>
		<link>http://open.bekk.no/responsive-design-med-enonic-cms/</link>
		<comments>http://open.bekk.no/responsive-design-med-enonic-cms/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 07:00:26 +0000</pubDate>
		<dc:creator>Per Allan Dahl Johansson</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[CMS]]></category>
		<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[Enonic]]></category>
		<category><![CDATA[Responsive]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=7617</guid>
		<description><![CDATA[Det er mange måter å lage responsive design på og da er det viktig å ta en nøye titt på verktøykassa til den tekniske plattformen som skal ligge i bunnen av løsningen. Enonic CMS følger med i timen og det er flere muligheter i malverket til CMS&#8217;et som kan være greit å titte litt nærmere [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Det er mange måter å lage responsive design på og da er det viktig å ta en nøye titt på verktøykassa til den tekniske plattformen som skal ligge i bunnen av løsningen. Enonic CMS følger med i timen og det er flere muligheter i malverket til CMS&#8217;et som kan være greit å titte litt nærmere på.</strong></p>
<p>1. april 2011 lanserte <a href="http://www.enonic.com/">Enonic</a> sin CMS som open source i tillegg til sin standard Enterprise utgave. Enonic CE 4.6 (Community Edition) er det offisielle navnet. De har opprettet en egen sone på <a title="Enonic's profile on GitHub" href="https://github.com/enonic" target="_blank">GitHub</a> der all koden ligger og man kan samtidig følge utviklingen av versjon 5.0 som er under utvikling. Det mest spennende som er å finne på GitHub er <a title="CMS Packages" href="https://github.com/enonic/cms-packages" target="_blank">pakkemalene</a>. Her kan man plukke funksjonalitet som er gjennomtestet og som funker veldig bra som et utgangspunkt, og det vil også funke 100 % slik de allerede er på et mindre nettsted. Man trenger da kun å endre på designelementer og CSS&#8217;en.</p>
<p>Når du har lastet ned Enonic CE fra GitHub og du har installert den lokalt for testing står det veldig greit i dokumentasjonen om hvordan du kommer i gang.</p>
<h2>Walkthrough</h2>
<ul>
<li>Connect to WebDAV and upload the resources.</li>
<li>Edit your site and set the Internal Resources to &#8216;/config/*&#8217; where * contains a valid config.xml file</li>
<li>Set the Public Resources to &#8216;/_public/themes/&#8217;</li>
<li>Set Device Classification Script to &#8216;/libraries/resolvers/device-classification.xsl&#8217;</li>
</ul>
<p>Start developing!</p>
<p>Etter du har logget deg inn i adminkonsollet kan du laste ned og konfigurere en del innholdstyper for å teste CMS&#8217;et. Eksempler på innholdstyper, som passer med pakkemalene du har lastet opp via WebDAV, finner du <a title="Innholdstyper til Enonic CMS" href="https://github.com/enonic/cms-packages/tree/master/contenttypes" target="_blank">her</a>. Disse xml-filene skal ikke lastes opp i WebDAV men du må gjøre litt god gammeldags cut&#8217;n'paste inn i konsollet. Når du har dette på plass kan du opprette mapper/kategorier i <strong>Innholdsarkivet</strong> og komme igang med litt innholdsproduksjon. Å produsere innhold er alltid tidkrevende og kan du i prosjektsammenheng definere innholdet på et så tidlig tidspunkt som mulig og før siten er ferdig kodet opp kan innholdsprodusentene få startet arbeidet sitt så tidlig som mulig.</p>
<p>Sett at du har en del testinnhold klart og skal begynne å implementere maler (xslt). Hvor skal man begynne? På hvilket nivå skal man tenke responsivt? Er det behov for responsivt design? Det er jo ikke helt sikkert at det er det. Hvis det er et eksisterende nettsted som skal lages på nytt kan det være lurt å ta en titt på besøksstatistikken og spesielt da forholdet mellom besøkende med og uten mobiltelefon eller tablet. Når man har en god oversikt over hvilke nettlesere og enheter som besøker siten må man se på målgrupper og strategi. Men det er utenfor scope av denne artikkelen så nå er det på tide å hoppe inn i malverket.</p>
<p>I Enonic CMS ligger det støtte for en device-detektor. Den hekter du på nettstedet ditt i adminkonsollet om du vil bruke denne som utgangspunkt. Det er lurt å ta denne i bruk uavhengig om du skal ha responsivt design eller ikke. Det er her informasjonen til hvilke breddeverdier de forskjellige regionene på sidene dine innehar. Dette brukes igjen til dynamisk skalering av bilder.</p>
<p>I pakkene som du allerede har lastet opp kan du starte med å titte på <em>theme.xml</em>. Denne xml-fila finner du på roten av siten din. Du finner den i dav&#8217;en her omtrent:</p>
<p>dav: /themes/&lt;navn-på-demosite&gt;/<em>theme.xml</em></p>
<p>Når man jobber med denne fila er det greit å ha oversikt over designet som skal implementeres. Man trenger å vite maksbredder på bilder/grafikk i de forskjellige regionene som siden kan deles opp i. Vi tar en liten titt på xml&#8217;en</p>
<pre>&lt;theme&gt;
    &lt;region-prefix/&gt;
    &lt;accessibility&gt;
        ...
    &lt;/accessibility&gt;
    &lt;device-classes&gt;
        &lt;device-class name="pc,unknown,mobile"&gt;
            &lt;layout name="default"&gt;

                &lt;area width="950"&gt;
                    &lt;region name="north"&gt;
                        &lt;width&gt;950&lt;/width&gt;
                        &lt;margin&gt;
                            &lt;bottom&gt;10&lt;/bottom&gt;
                        &lt;/margin&gt;
                    &lt;/region&gt;
                &lt;/area&gt;
                &lt;area width="950"&gt;
                    &lt;region name="center" role="main" element="section" class="wide"&gt;
                        &lt;padding&gt;
                            &lt;right&gt;30&lt;/right&gt;
                            &lt;left&gt;30&lt;/left&gt;
                            &lt;top&gt;30&lt;/top&gt;
                            &lt;bottom&gt;30&lt;/bottom&gt;
                        &lt;/padding&gt;
                        &lt;scalable&gt;true&lt;/scalable&gt;
                        &lt;system&gt;true&lt;/system&gt;
                    &lt;/region&gt;
                    &lt;region name="single-sidebar" element="aside" role="complementary"&gt;
                        &lt;width&gt;180&lt;/width&gt;
                        &lt;margin&gt;
                            &lt;right&gt;10&lt;/right&gt;
                        &lt;/margin&gt;
                    &lt;/region&gt;
                    &lt;region name="east"&gt;
                        &lt;width&gt;180&lt;/width&gt;
                        &lt;margin&gt;
                            &lt;left&gt;10&lt;/left&gt;
                        &lt;/margin&gt;
                    &lt;/region&gt;
                &lt;/area&gt;
                &lt;area width="950"&gt;
                    &lt;region name="south"&gt;
                        &lt;width&gt;950&lt;/width&gt;
                    &lt;/region&gt;
                &lt;/area&gt;
            &lt;/layout&gt;
            &lt;image&gt;
                ... bilder
            &lt;/image&gt;
            &lt;styles&gt;
                ... css-filer
            &lt;/styles&gt;
            &lt;scripts&gt;
                ... js-filer
            &lt;/scripts&gt;
        &lt;/device-class&gt;
        &lt;device-class name="pc,unknown,mobile"&gt;
            ...... ipad spesifikk kode
        &lt;/device-class&gt;
    &lt;/device-classes&gt;
&lt;/theme&gt;</pre>
<p>Strukturen er oversiktlig nok når man er vant til malverket til Enonic men det er regionene her som er interessante.</p>
<pre>&lt;region name="single-sidebar" element="aside" role="complementary"&gt;
&lt;region name="center" role="main" element="section"&gt;</pre>
<p>Det er støtte for html5-elementer i malverket og man kan definere det enkelt ved å bruke dette oppsettet her. Dette er da tenkt som globale elementer i html-kilden. Strukturen settes opp her og støttes videre med global css slik at rammeverket sitter dønn selv uten innhold på siden. Det er fint å kunne teste siten så tidlig som mulig.</p>
<p>Disse navnene på regionene, hhv. <em>single-sidebar</em> og <em>center</em>, blir nå hardkodete navn som må gjenspeiles i sidemalen som til slutt skriver ut html-koden på sidenivå. Denne fila heter <em>page.xsl</em> og den finner du på samme nivå som <em>theme.xml</em>. Når du senere skal lage flere siter er det fint å klone disse filene, opprette ny mappe under /themes/, dumpe filene her, opprette nytt nettsted i Enonic og deretter koble de nye malene på nettstedet og sidemalen og du er i gang med å lage site nr 2. Gjenbruk er gull.</p>
<p>Hvis vi tar en titt på page.xsl ser man kjapt hvor regionene defineres</p>
<pre>&lt;!-- regions --&gt;
  &lt;xsl:param name="north"&gt;
    &lt;type&gt;region&lt;/type&gt;
  &lt;/xsl:param&gt;
  &lt;xsl:param name="single-sidebar"&gt;
    &lt;type&gt;region&lt;/type&gt;
  &lt;/xsl:param&gt;
  &lt;xsl:param name="center"&gt;
    &lt;type&gt;region&lt;/type&gt;
  &lt;/xsl:param&gt;
  &lt;xsl:param name="east"&gt;
    &lt;type&gt;region&lt;/type&gt;
  &lt;/xsl:param&gt;
  &lt;xsl:param name="south"&gt;
    &lt;type&gt;region&lt;/type&gt;
  &lt;/xsl:param&gt;</pre>
<p>Disse navnene må være like som i theme.xml. Når det er på plass kan man starte utviklingen. I theme.xml har jeg satt opp 960px som bredde for standardoppsettet mitt. Hadde jeg konfigurert nettstedet også for tablet og smartphone ville jeg lagt på to device-classes og definert breddene som f.eks. 768px og 320px eller eventuelt ytterpunktene med høyest oppløsning i landscape-modus. Dette vil da være størrelsen som bilder som skrives ut i de forskjellige regionene vil ha. Alt skjer via dynamiske funksjoner som man kan laste opp fra pakkene og bruke fritt i malene. I en artikkelmal kan man tenke seg at man kaller på et bilde slik:</p>
<pre>&lt;xsl:call-template name="image"&gt;
	&lt;xsl:with-param name="size" select="'wide'"/&gt;
	&lt;xsl:with-param name="image-path" select="image/@key"/&gt;
	&lt;xsl:with-param name="class" select="'list-image'"/&gt;
&lt;/xsl:call-template&gt;</pre>
<p>Her sier jeg til bildefunksjonen at den skal skrive ut bildet med full bredde i widescreen-format og samtidig legge på en klasse med navn &#8220;list-image&#8221;. Hvis man bruker standardoppsettet uten noen som helst form for tweaking blir dette en fast størrelse på bildet og ikke så skalerbart. Nå gjelder det å ta en titt på include-fila som skriver ut bilder. Den heter <em>image.xsl</em> og den finner du her: /libraries/utilities/<em>image.xsl</em></p>
<p>Se etter templaten som heter &#8220;<strong>image.display-image</strong>&#8220;. Den er stor og kompleks og du trenger ikke endre så mye her, bare kommentere ut bredden og høyden til bildet som til slutt skrives ut. Se etter:</p>
<pre>&lt;xsl:if test="$width"&gt;
	&lt;xsl:attribute name="width"&gt;
		&lt;xsl:value-of select="$width"/&gt;
	&lt;/xsl:attribute&gt;
&lt;/xsl:if&gt;
&lt;xsl:if test="$height"&gt;
	&lt;xsl:attribute name="height"&gt;
		&lt;xsl:value-of select="$height"/&gt;
	&lt;/xsl:attribute&gt;
&lt;/xsl:if&gt;</pre>
<p>Når dette er kommentert ut er det bare å styre bredden til bildene enkelt via css slik:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">img <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">max-width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">100%</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">auto</span> !important
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Ganske enkelt egentlig. Nå er det opp til deg og dine CSS-Ninja-egenskaper for å gjøre resten, men husk, vær smart og bruk device-detektoren i malene og scope hva slags enhet du jobber mot. Det vil optimalisere ytelsen og farten på siten. Du kan også justere innholdet og tilpasse siten på en mye enklere måte. Du kan gjøre dette helt ute i rammeverket og inne i portletene. Lag sjekker på device og tilpass bildet ditt. Ikke noe vits i skrive ut et 960px bilde for så å skalere det ned til 320px på en iPhone. Da er det bedre å bruke dette opplegget og skrive ut et bra skalert bilde fra serveren som passer til den devicen du har i målgruppen din. Malverket til Enonic baserer seg på XSLT og er du god på XSLT, XHTML og CSS er det bare moro herfra og frem til siten skal lanseres.</p>
<p>Lykke til.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/responsive-design-med-enonic-cms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Få orden i JavaScript-testene med QUnit</title>
		<link>http://open.bekk.no/fa-orden-i-javascript-testene-med-qunit/</link>
		<comments>http://open.bekk.no/fa-orden-i-javascript-testene-med-qunit/#comments</comments>
		<pubDate>Tue, 06 Sep 2011 07:45:43 +0000</pubDate>
		<dc:creator>Holger Ludvigsen</dc:creator>
				<category><![CDATA[BEKK]]></category>
		<category><![CDATA[Dynamiske språk]]></category>
		<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[Webarkitektur]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[qunit]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[testdrevet utvikling]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=6269</guid>
		<description><![CDATA[Når man skriver i et dynamisk språk som JavaScript med mye kraft i fingerspissene er det lett å ødelegge det man allerede har fått på plass. QUnit er et lettvektig rammeverk for enhetstesting i JavaScript. Med QUnit kan du blant annet teste asynkron kode og fasilitere automatisert testkjøring. Denne artikkelen forklarer hva QUnit gjør og hvordan man bruker det.]]></description>
			<content:encoded><![CDATA[<p><strong>Når man skriver i et dynamisk språk som JavaScript med mye kraft i fingerspissene er det lett å ødelegge det man allerede har fått på plass. Hvor mange ganger har du ikke skutt deg selv i foten på grunn av underlige syntaksregler eller dårlig dokumentasjon? En solid samling enhetstester kan forhindre dette og gjøre deg trygg på at koden din fungerer.</strong></p>
<blockquote style="margin-left: 220px;"><p>&#34;QUnit er et lettvektig rammeverk<br />
for enhetstesting i JavaScript&#34;</p></blockquote>
<p>QUnit er et lettvektig rammeverk for enhetstesting i JavaScript. Denne artikkelen forklarer hva QUnit gjør og hvordan man bruker det. Med QUnit kan du blant annet:</p>
<ul>
<li>Enhetsteste din eksisterende kode</li>
<li>Få testresultatene opp formatert på en side</li>
<li>Teste asynkron kode, som f.eks. animasjoner eller ajax</li>
<li>Teste server-side kode</li>
<li>Fasilitere automatisert testkjøring og resultatrapportering</li>
</ul>
<p>QUnit bygger på jQuery &#8212; det populære Javascript-biblioteket &#8212; og blir brukt som det interne testverktøyet på jQuery-teamet. Slik ser testresultater ut i QUnit:</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2011/09/screen.png"><img src="http://open.bekk.no/wp-content/uploads/2011/09/screen.png" alt="" title="" style="margin: auto;" width="473" height="349" class="aligncenter size-full wp-image-6273" /></a></p>
<h2>QUnit basics</h2>
<p>En demonstrasjon sier mer enn tusen ord. Slik skriver man en enkel test i QUnit:</p>
<pre style="font-family: Courier new">
test('Beskriv testen her', function() {
   var x = Math.max(3, 4);
   equals(x, 4);
   var y = Math.max(3, 4);
   notEquals(x, y, "Beskriv evt. assertion her");
});
</pre>
<p>Her er equals() og notEquals() assertions som får testen til å feile om de ikke stemmer. Dette ligner kjente testerammeverk som f.eks. JUnit. Tilgjengelige assertions i QUnit er:</p>
<p><code style="font-family: Courier new">ok(a)</code><br />
Sjekker om a er true.</p>
<p><code style="font-family: Courier new">equal(a,b), notEqual(a,b)</code><br />
Sammenligner a og b, og viser den spesifikke forskjellen om de ikke matcher. For eksempel:</p>
<p><a href="http://open.bekk.no/wp-content/uploads/2011/09/failed-test.png"><img src="http://open.bekk.no/wp-content/uploads/2011/09/failed-test.png" alt="" title="" width="350" height="61" class="aligncenter size-full wp-image-6274" /></a></p>
<p><code style="font-family: Courier new">strictEqual(a,b), notStrictEqual(a,b)</code><br />
Samme som equals, men sjekker om også typen til a matcher b. (F.eks. strictEquals(2, &#8220;2&#8243;) feiler.)</p>
<p><code style="font-family: Courier new">deepEqual(a,b), notDeepEqual(a,b)</code><br />
Sjekker rekursivt feltene inni a og b for å se om hver av dem matcher.</p>
<p><code style="font-family: Courier new">raises(f), raises(f,e)</code><br />
Sjekker om et exception kastes når funksjonen f kjøres. Evt. kan typen exception spesifiseres i e.</p>
<h2>Strukturer testene med moduler</h2>
<p>Antall tester kan bli mange, men QUnit har mekanismer for å strukturere tester i grupper og la dem dele felles kode for å sette opp og rydde opp etter testene. Sett inn module() for å separere tester som hører sammen:</p>
<pre style="font-family: Courier new">
module('Touch-komponenten');

test(...);
test(...);

module('Søketjenesten');

test(...);
test(...);
</pre>
<p>Disse modulene kan også ta imot setup- og teardown-funksjoner som kjøres før og etter hver test:</p>
<pre style="font-family: Courier new">
module("Ajaxtestene", {
 setup: function() {
    // kjøres før test
 },
 teardown: function() {
    // kjøres etter test
 }
});
</pre>
<h2>Test asynkron JavaScript</h2>
<p>Mye av moroa med JavaScript er asynkrone metoder. Det vil si at etter at man gjør kall på en asynkron metode fortsetter koden etter kallet å kjøre, mens den asynkrone metoden også kjøres samtidig. Typisk brukes slike asynkrone metoder i ajax-kall og animasjoner, og de får som regel en callback-metode som kjøres når de er ferdig. For eksempel er jQuerys ajax-metode asynkron:</p>
<pre style="font-family: Courier new">
function asynkronMetode(callback) {
    $.ajax({
       url: 'server.php',
       success: callback
    });
}
</pre>
<p>Hvordan kan man teste asynkrone metoder? Dette er vanskeligere enn man kanskje tror. Om man kjører assertions etter et asynkront kall kan det hende at den asynkrone koden ikke er ferdig enda, og assertionene vil feile. Hva om man heller putter assertions inni callbacken slik at de kjøres når den asynkrone koden er ferdig? Nei, det går ikke fordi hele testen kan samtidig kjøre seg ferdig og dermed vellykket før assertionene får kommet på banen, og da merker man ikke om de feiler.</p>
<blockquote style="margin-left: 220px;"><p>&#34;Mye av moroa med JavaScript<br />
er asynkrone metoder&#34;</p></blockquote>
<p>QUnit tilbyr en metode stop() som pauser testen slik at man kan vente på asynkrone kall. Testen startes igjen ved å kalle start(). JavaScript tilbyr allerede en metode setTimeout() som kan sørge for å vente så og så lenge før start() kjøres. Høres ut som vi har det vi trenger for å teste asynkron kode!</p>
<p>Men hva om et asynkront kall henger lenger enn tiden setTimeout venter? Da vil den asynkrone metodens assertions aldri kjøre, og ingen assertions betyr tilsynelatende vellykket test, uavhengig av om det funket eller ikke! Løsningen er å spesifisere antall assertions man forventer å gjøre med expect(). Slik vil testen feile om noe asynkron kode aldri returnerte.</p>
<p>Her er et eksempel som omfatter disse asynkrone mekanismene:</p>
<pre style="font-family: Courier new">
test('Min asynkrone test', function() {
    expect(3); // Vi forventer 3 assertions
    stop();  // Pause testen

    asynkronMetode(function() {
       equals(bla, bla);
    })  

    asynkronMetode(function() {
      equals(bla, bla);
      equals(bla, bla);
    })  

    setTimeout(function() {
       start();  // Fortsett testen etter 2 sekunder
    }, 2000);
});
</pre>
<h2>Automatiser testene og presenter resultatene</h2>
<p>Enhetstesting i QUnit ser vel og bra ut, men hvordan får man testene kjørt og testresultatene presentert på en fin måte? Heldigvis følger det med funksjoner og CSS i QUnit for dette. Følgende html-kode kjører testene i mine_tester.js og presenter resultatene slik som sett i skjermdumpen øverst i denne artikkelen:</p>
<pre style="font-family: Courier new">
&lt;html&gt;
&lt;head&gt;
    &lt;script src="http://pre.jquery.com/jquery-latest.js"&gt;&lt;/script&gt;
    &lt;link rel="stylesheet" href="http://pre.jquery.com/qunit/git/qunit.css" type="text/css" /&gt;
    &lt;script type="text/javascript" src="http://pre.jquery.com/qunit/git/qunit.js"&gt;&lt;/script&gt;

    &lt;script type="text/javascript" src="mine_tester.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1 id="qunit-header"&gt;Min overskrift her&lt;/h1&gt;
    &lt;h2 id="qunit-banner"&gt;&lt;/h2&gt;
    &lt;div id="qunit-testrunner-toolbar"&gt;&lt;/div&gt;
    &lt;h2 id="qunit-userAgent"&gt;&lt;/h2&gt;
    &lt;ol id="qunit-tests"&gt;&lt;/ol&gt;
    &lt;div id="qunit-fixture"&gt;test markup, will be hidden&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<blockquote style="margin-left: 220px;"><p>&#34;QUnit vil skape strukturert html<br />
med testresultatene&#34;</p></blockquote>
<p>Som man ser krever QUnit jQuery-biblioteket, og kommer til å fylle html-elementene i <body> med riktig innhold ut fra hvilken id de har. Den medfølgende CSS-en kan såklart byttes ut med ens egne stilark. Og QUnit vil skape strukturert html med testresultatene som så kan analyseres av automatiske verktøy. Slik vil for eksempel oppsummeringen av resultene se ut:</p>
<pre style="font-family: Courier new">
&lt;p id="qunit-testresult" class="result"&gt;
    Tests completed in 76 milliseconds.&lt;br&gt;
    &lt;span class="passed"&gt;5&lt;/span&gt; tests of
    &lt;span class="total"&gt;8&lt;/span&gt; passed,
    &lt;span class="failed"&gt;3&lt;/span&gt; failed.
&lt;/p&gt;
</pre>
<p>QUnit API-et tilbyr også en rekke callbacks som kalles i de ulike stadiene av testingen. F.eks. QUnit.begin(), QUnit.testDone() og QUnit.moduleDone(), hvis funksjonalitet bør være selvforklarende. Alt dette fasiliterer automatiske tredjeparts testverktøy.</p>
<h2>Konklusjon</h2>
<p>QUnit er et enkelt rammeverk for enhetstesting i JavaScript. Det har støtte for assertions slik man kjenner fra andre rammeverk som JUnit, og man kan strukturere testene i modules. Mekanismer for testing av asynkron kode finnes også, samt støtte for tredjeparts automatiserte verktøy for å kjøre testene og presentere resultatene. API-en er liten, men gir deg de verktøyene man trenger for å innføre enhetstester i din eksisterende kode, og det er veldig lett å sette i gang. Les mer om QUnit på <a href="http://docs.jquery.com/QUnit" title="QUnit">nettsidene deres</a>, og sjekk ut <a href="http://net.tutsplus.com/tutorials/javascript-ajax/how-to-test-your-javascript-pre-with-qunit/" title="Asynkron testing med QUnit">denne artikkelen</a> om asynkron testing i QUnit.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/fa-orden-i-javascript-testene-med-qunit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Remote Log4J in Flex?</title>
		<link>http://open.bekk.no/remote-log4j-in-flex/</link>
		<comments>http://open.bekk.no/remote-log4j-in-flex/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 09:22:14 +0000</pubDate>
		<dc:creator>Ole Christian Langfjæran</dc:creator>
				<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[Webarkitektur]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[blazeds]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=1247</guid>
		<description><![CDATA[Case: You&#8217;ve finally made that all-so-snazzy Flex application with DataGrids, Charts, transitions from here to the end of eternety, nice looking validators and all else you can think of. Also, you made it in no-time. The users are thrilled and so is the client. In other words, all is peachy in Rich Client Web Application [...]]]></description>
			<content:encoded><![CDATA[<p>Case: You&#8217;ve finally made that all-so-snazzy Flex application with DataGrids, Charts, transitions from here to the end of eternety, nice looking validators and all else you can think of. Also, you made it in no-time. The users are thrilled and so is the client. In other words, all is peachy in Rich Client Web Application Land.</p>
<p>Hadn&#8217;t been for those re-occuring complaints from the users that &#8220;An unknown exception has occured&#8221; message with a big warning label pops up from time to time. A nice little feature you made to hide all of those unexpected exceptions that can, but should not, occur in your application. All in all a good thing as we would like to spare the user the experience of reading an unpleasant stacktrace from an external webservice error. But YOU, on the other hand. You would love to get your hands on the stacktrace from that Error that shouldn&#8217;t happen. So, how?</p>
<p>In Java-Land this is usually done by incorporating some form of logging that logs messages to file or almost whatever you would like. Most preferred being <a title="Log4J homepage" href="http://logging.apache.org/log4j/1.2/index.html">Log4J</a>. Unfortunately I feel that a just-as-easy solution for Flex/Actionscript has yet to present itself. Until now. As a left-over artifact from the development of <a title="Spring Integration Home" href="http://www.springsource.org/spring-integration">Spring Integration</a>, the guys from Prana and Spring has made library called <a title="Home as3commons" href="http://code.google.com/p/as3-commons/">as3commons-logging</a>. The library mimics Log4j in many ways and makes an excellent job doing so. Adding the as3commons-logging swc to your project then makes remote logging a peach. Here&#8217;s howto:</p>
<h2>Some code</h2>
<p><strong>Step 1 of 3</strong><br />
Implement an ILoggerFactory like this. It&#8217;s responsibility will be to create Loggers for your classes:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">public</span> <span style="color: #003366; font-weight: bold;">class</span> RemoteLoggerFactory implements ILoggerFactory
<span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">private</span> <span style="color: #003366; font-weight: bold;">var</span> remote<span style="color: #339933;">:</span>RemoteObject<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">public</span> <span style="color: #003366; font-weight: bold;">function</span> RemoteLoggerFactory<span style="color: #009900;">&#40;</span>url<span style="color: #339933;">:</span>String<span style="color: #339933;">,</span> destination<span style="color: #339933;">:</span>String<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;remoteObjectLogger&quot;</span><span style="color: #339933;">,</span> fault<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">Function</span><span style="color: #339933;">=</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
                remote <span style="color: #339933;">=</span> createRemote<span style="color: #009900;">&#40;</span>url<span style="color: #339933;">,</span> destination<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                remote.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span>FaultEvent.<span style="color: #660066;">FAULT</span><span style="color: #339933;">,</span> fault <span style="color: #339933;">==</span> <span style="color: #003366; font-weight: bold;">null</span> <span style="color: #339933;">?</span> onRemoteFault<span style="color: #339933;">:</span>fault<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">public</span> <span style="color: #003366; font-weight: bold;">function</span> getLogger<span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #339933;">:</span>String<span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span>ILogger
        <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">new</span> RemoteLogger<span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #339933;">,</span> remote<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #009966; font-style: italic;">/** Creates a RemoteObject using SecureAMFChannel if https */</span>
        <span style="color: #003366; font-weight: bold;">private</span> <span style="color: #003366; font-weight: bold;">function</span> createRemote<span style="color: #009900;">&#40;</span>url<span style="color: #339933;">:</span>String<span style="color: #339933;">,</span> destination<span style="color: #339933;">:</span>String<span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> RemoteObject
        <span style="color: #009900;">&#123;</span>
                <span style="color: #003366; font-weight: bold;">var</span> channelSet<span style="color: #339933;">:</span>ChannelSet <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> ChannelSet<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                channelSet.<span style="color: #660066;">addChannel</span><span style="color: #009900;">&#40;</span>isHttps<span style="color: #009900;">&#40;</span>url<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #003366; font-weight: bold;">new</span> SecureAMFChannel<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> url<span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">new</span> AMFChannel<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> url<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #003366; font-weight: bold;">var</span> remoteService<span style="color: #339933;">:</span>RemoteObject <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> RemoteObject<span style="color: #009900;">&#40;</span>destination<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                remoteService.<span style="color: #660066;">channelSet</span> <span style="color: #339933;">=</span> channelSet<span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #000066; font-weight: bold;">return</span> remoteService<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">private</span> <span style="color: #003366; font-weight: bold;">function</span> isHttps<span style="color: #009900;">&#40;</span>url<span style="color: #339933;">:</span>String<span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> Boolean
        <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">return</span> url.<span style="color: #660066;">indexOf</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;https&quot;</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;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #009966; font-style: italic;">/** Default FaultHandler. Just traces the message. */</span>
        <span style="color: #003366; font-weight: bold;">private</span> <span style="color: #003366; font-weight: bold;">function</span> onRemoteFault<span style="color: #009900;">&#40;</span>evt<span style="color: #339933;">:</span>FaultEvent<span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">void</span>
        <span style="color: #009900;">&#123;</span>
                trace<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Could not log to server: &quot;</span><span style="color: #339933;">+</span>evt.<span style="color: #660066;">fault</span>.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><strong>Step 2 of 3</strong><br />
And then create the actual Logger which sends log messages to the backend, be that java, php, rails, .NET or name it.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">public</span> <span style="color: #003366; font-weight: bold;">class</span> RemoteLogger <span style="color: #003366; font-weight: bold;">extends</span> DefaultLogger
<span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">protected</span> <span style="color: #003366; font-weight: bold;">var</span> _level<span style="color: #339933;">:</span>uint<span style="color: #339933;">;</span>
	<span style="color: #003366; font-weight: bold;">protected</span> <span style="color: #003366; font-weight: bold;">var</span> remote<span style="color: #339933;">:</span>Object<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">public</span> <span style="color: #003366; font-weight: bold;">function</span> RemoteLogger<span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #339933;">:</span>String<span style="color: #339933;">,</span> remote<span style="color: #339933;">:</span>Object<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span><span style="color: #000066;">name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">remote</span> <span style="color: #339933;">=</span> remote<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	override <span style="color: #003366; font-weight: bold;">protected</span> <span style="color: #003366; font-weight: bold;">function</span> log<span style="color: #009900;">&#40;</span>level<span style="color: #339933;">:</span>uint<span style="color: #339933;">,</span> message<span style="color: #339933;">:</span>String<span style="color: #339933;">,</span> params<span style="color: #339933;">:</span>Array<span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span><span style="color: #000066; font-weight: bold;">void</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>level <span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;=</span> <span style="color: #000066; font-weight: bold;">this</span>._level<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                        <span style="color: #006600; font-style: italic;">// add datetime</span>
			<span style="color: #003366; font-weight: bold;">var</span> msg<span style="color: #339933;">:</span>String <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;[&quot;</span> <span style="color: #339933;">+</span> <span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;]&quot;</span><span style="color: #339933;">;</span>
			<span style="color: #006600; font-style: italic;">// add the name given to this logger. Usually the Class name</span>
			msg <span style="color: #339933;">+=</span> <span style="color: #3366CC;">&quot;[&quot;</span> <span style="color: #339933;">+</span> <span style="color: #000066;">name</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;]&quot;</span><span style="color: #339933;">;</span>
			<span style="color: #006600; font-style: italic;">// add message</span>
			msg <span style="color: #339933;">+=</span> <span style="color: #3366CC;">&quot; - &quot;</span> <span style="color: #339933;">+</span> MessageUtil.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span>message<span style="color: #339933;">,</span> params<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
			<span style="color: #003366; font-weight: bold;">var</span> logLevel<span style="color: #339933;">:</span>String <span style="color: #339933;">=</span> LogLevel.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span>level<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			remote.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>logLevel<span style="color: #339933;">,</span> msg<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></pre></div></div>

<p><strong>Step 3 of 3</strong><br />
Next instantiate your factory. Preferably as early as possible, so snapping in something like this at your Main mx:Application will do the trick.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">private</span> static <span style="color: #003366; font-weight: bold;">var</span> loggerSetup<span style="color: #339933;">:*</span> <span style="color: #339933;">=</span> LoggerFactory.<span style="color: #660066;">loggerFactory</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> RemoteLoggerFactory<span style="color: #009900;">&#40;</span>ROOT_PATH<span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;messagebroker/amf&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>And voila! It is now useable in any of your classes thiswise:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">...
<span style="color: #003366; font-weight: bold;">private</span> static <span style="color: #003366; font-weight: bold;">const</span> logger<span style="color: #339933;">:</span>ILogger <span style="color: #339933;">=</span> LoggerFactory.<span style="color: #660066;">getClassLogger</span><span style="color: #009900;">&#40;</span>Jesus<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">public</span> <span style="color: #003366; font-weight: bold;">function</span> Jesus<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      logger.<span style="color: #660066;">info</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Attention: We constructed Jesus.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h2>A dash of backend</h2>
<p>The last but not least is to have a backend that can receive the messages and log them in a human readable way for later error debugging.<br />
Why not splash out a java class with log4j? Well, this will do your trick:<br />
<strong>Step 3.5</strong></p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> RemoteObjectLogger
<span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> PRE_FLEX <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;[FLEX]&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">final</span> Log logger <span style="color: #339933;">=</span> LogFactory.<span style="color: #006633;">getLog</span><span style="color: #009900;">&#40;</span>getClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> log<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> level, <span style="color: #003399;">String</span> message<span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;INFO&quot;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>level<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                        logger.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span>PRE_FLEX <span style="color: #339933;">+</span> message<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;DEBUG&quot;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>level<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                        logger.<span style="color: #006633;">debug</span><span style="color: #009900;">&#40;</span>PRE_FLEX <span style="color: #339933;">+</span> message<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;WARN&quot;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>level<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                        logger.<span style="color: #006633;">warn</span><span style="color: #009900;">&#40;</span>PRE_FLEX <span style="color: #339933;">+</span> message<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;ERROR&quot;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>level<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                        logger.<span style="color: #006633;">error</span><span style="color: #009900;">&#40;</span>PRE_FLEX <span style="color: #339933;">+</span> message<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;FATAL&quot;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>level<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                        logger.<span style="color: #006633;">fatal</span><span style="color: #009900;">&#40;</span>PRE_FLEX <span style="color: #339933;">+</span> message<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">else</span>
                        logger.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span>PRE_FLEX <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;[&quot;</span> <span style="color: #339933;">+</span> level <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;] - &quot;</span> <span style="color: #339933;">+</span> message<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h2>Try it</h2>
<p>Would you like to see it in action? From top to bottom? Well I coded a small example for you to play with using Java as a backend. Svn the code from <a href="http://code.google.com/p/flex-code-examples/source/browse/#svn/trunk/src/spring-logging-blazeds">google-code</a>. Only prerequisite is <a href="http://maven.apache.org/download.html">Maven</a> installed. From there run compileAndRun and you are up and running!</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/remote-log4j-in-flex/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Raske prototyper med haml og sass</title>
		<link>http://open.bekk.no/haml_og_sass/</link>
		<comments>http://open.bekk.no/haml_og_sass/#comments</comments>
		<pubDate>Wed, 10 Jun 2009 06:55:09 +0000</pubDate>
		<dc:creator>Øystein Ellingbø</dc:creator>
				<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[haml]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[sass]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=432</guid>
		<description><![CDATA[Haml (HTML Abstraction Markup Language) er et markup-språk for å lage enkel og ren html uten inline-koding. Det er laget som en erstatning for Rails sin RHTML, men kan utmerket godt brukes som en erstatning til ren html. Haml er indenteringssensitiv. Resultatet er mindre og mer kompakt kode, i tillegg til at vi automatisk får [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://haml.hamptoncatlin.com/">Haml (HTML Abstraction Markup Language)</a> er et markup-språk for å lage enkel og ren html uten inline-koding. Det er laget som en erstatning for Rails sin RHTML, men kan utmerket godt brukes som en erstatning til ren html. Haml er indenteringssensitiv. Resultatet er mindre og mer kompakt kode, i tillegg til at vi automatisk får generert pen xhtml. Det tar ikke mange minuttene å lære seg haml. Sjekk ut <a href="http://haml.hamptoncatlin.com/tutorial/">tutorial</a> for en rask innføring.</p>
<div style="height: 21em;">
<div style="float: left; margin-right: 2em; width: 40%;"><strong>HTML</strong></p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;div id=&quot;content&quot;&gt;
&lt;div class=&quot;left column&quot;&gt;
&lt;h2&gt;Velkommen til open.bekk.no&lt;/h2&gt;
innhold&lt;/div&gt;
&lt;div class=&quot;right column&quot;&gt;
    &lt;a href=&quot;url&quot;&gt;En link&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;</pre></div></div>

</div>
<div style="float: left; width: 40%;"><strong>Haml</strong></p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">#content
  .left.column
    %h2 Velkommen til open.bekk.no
    %p innhold
  .right.column
    %a{:href =&gt; &quot;url&quot;} En link</pre></div></div>

</div>
</div>
<p>Haml kommer med sin egen versjon av CSS, kalt <a href="http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html">Sass (Syntactically Awesome StyleSheets)</a>. Sass er en oversiktlig og god måte å skrive nøstede regler. I Sass kan man definere variabler, noe som gjør det enklere og raskere å endre verdier.</p>
<div style="height: 22em;">
<div style="float: left; margin-right: 2em; width: 40%;"><strong>CSS</strong></p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #cc00cc;">#header</span> <span style="color: #00AA00;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#FFFFFF</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
<span style="color: #cc00cc;">#header</span> <span style="color: #6666ff;">.error</span> <span style="color: #00AA00;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#FF0000</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
<span style="color: #cc00cc;">#header</span> a <span style="color: #00AA00;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">text-decoration</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span>
<span style="color: #00AA00;">&#125;</span>
<span style="color: #cc00cc;">#header</span> a<span style="color: #3333ff;">:hover </span><span style="color: #00AA00;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">text-decoration</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">underline</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

</div>
<div style="float: left; width: 40%;"><strong>Sass</strong></p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">!error_color <span style="color: #00AA00;">=</span> <span style="color: #cc00cc;">#FF0000</span>
&nbsp;
<span style="color: #cc00cc;">#header</span>
  <span style="color: #00AA00;">:</span><span style="color: #000000; font-weight: bold;">background</span> <span style="color: #cc00cc;">#FFFFFF</span>
&nbsp;
  <span style="color: #6666ff;">.error</span>
    <span style="color: #00AA00;">:</span><span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">=</span> !error_color
&nbsp;
  a
    <span style="color: #00AA00;">:</span><span style="color: #000000; font-weight: bold;">text-decoration</span> <span style="color: #993333;">none</span>
    <span style="color: #3333ff;">:hover
      </span><span style="color: #00AA00;">:</span><span style="color: #000000; font-weight: bold;">text-decoration</span> <span style="color: #993333;">underline</span></pre></div></div>

</div>
</div>
<p>Kombinasjonen Haml og Sass er utmerket for å lage raske prototyper. Selv om dette er laget for ruby, er det ikke noe i veien for å bruke det til ren html/css. Den største fordelen for rask prototyping er Sass. Det er mye raskere og mer oversiktlig å gjøre endringer i sass enn det er i css. Muligheten for variabler føles naturlig for en programmerer, og gjør også koden mer lesbar (!error_color sier leseren myer mer enn #FF0000).</p>
<p>Weblesere forstår ikke haml/sass. Du trenger derfor en server som kan oversette dette. En rask og enkel løsning er å bruke Serve. Serve fyrer opp en instans av Webrick fra katalogen du står i. Ønsker du muligheten til å bruke partials for å redusere duplisering i haml-filene, kan jeg anbefale å bruke <a href="http://www.sinatrarb.com/">Sinatra</a> i stedet for Serve.</p>
<p>Så enkelt er det å komme i gang:</p>
<ul style="list-style-type:decimal;">
<li><a href="http://www.ruby-lang.org/en/downloads/">ruby</a></li>
<li>haml (&#8220;gem install haml&#8221; fra commandprompt)</li>
<li>serve (&#8220;gem install serve&#8221; fra commandprompt)</li>
<li>starte opp serve (&#8220;serve&#8221; fra commandprompt i ønsket katalog)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/haml_og_sass/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>JSON-ressurser og eksempel JavaScript-kode</title>
		<link>http://open.bekk.no/json-ressurser-og-eksempel-javascript-kode/</link>
		<comments>http://open.bekk.no/json-ressurser-og-eksempel-javascript-kode/#comments</comments>
		<pubDate>Fri, 27 Mar 2009 12:52:55 +0000</pubDate>
		<dc:creator>Andreas Øverland</dc:creator>
				<category><![CDATA[Grensesnittutvikling]]></category>
		<category><![CDATA[Teknologi]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[json]]></category>

		<guid isPermaLink="false">http://open.bekk.no/?p=31</guid>
		<description><![CDATA[JSON rocks. JavaScript Object Notation &#8211; Det er et enkelt data-format med lite overhead, det er en genial måte å bruke et allerede eksisterende språk på. På ett av de mange track&#8217;ene på Bekks fagdag i Mars 2009, jobbet vi med JavaScript og rammeverk og teknologier knyttet til det. Ett av fokusområdene var JSON. Under [...]]]></description>
			<content:encoded><![CDATA[<h1>JSON rocks.</h1>
<p><strong>JavaScript Object Notation &#8211; Det er et enkelt data-format med lite overhead, det er en genial måte å bruke et allerede eksisterende språk på.</strong></p>
<p>På ett av de mange track&#8217;ene på Bekks fagdag i Mars 2009, jobbet vi med JavaScript og rammeverk og teknologier knyttet til det. Ett av fokusområdene var JSON. Under følger en kort intro til JSON, samt noen eksempler på tjenester som tilbyr åpne JSON-API&#8217;er og kode som viser hvordan man kan importere og bruke dataen.</p>
<h2>Hva er JSON</h2>
<p>JSON er en måte å representere data på vha. enkel (og standard) JavaScript. Det betyr at man ikke trenger noen plugin eller noe rammeverk hverken på server- eller klient-side for å bruke det.</p>
<p>Et lite JSON-objekt:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> myObject <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #3366CC;">&quot;field&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;value hmhmhm&quot;</span><span style="color: #339933;">,</span>
	<span style="color: #3366CC;">&quot;childobj&quot;</span><span style="color: #339933;">:</span><span style="color: #009900;">&#123;</span>
		<span style="color: #3366CC;">&quot;childfield&quot;</span><span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;childvalue&quot;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>For å &#8220;vise&#8221;  verdien til felter/objektet &#8220;field&#8221;:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"> <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span> myObject.<span style="color: #660066;">field</span>.<span style="color: #660066;">value</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Eller child-objektet &#8220;childobj&#8221; sitt &#8220;childfield&#8221;:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"> <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span> myObject.<span style="color: #660066;">field</span>.<span style="color: #660066;">childobj</span>.<span style="color: #660066;">childvalue</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h2>Importering av JSON-data</h2>
<p>Man kan som kjent bruke AJAX til å hente data dynamisk inn på en side uten å relaste hele siden. En sikkerhetsbegrensning i måten nettlesere behandler AJAX-requester på hindrer henting av data fra en webside som ligger på en annen server enn der hoved-siden ligger. For eksempel går det greit at siden som ligger på http://www.bekk.no/ henter søkeresultater vha AJAX fra http://www.bekk.no/search/ . Men det er ikke mulig for http://www.bekk.no/ å hente noe fra feks http://search.bekk.no/ vha. standard AJAX (uten noen form for proxy).</p>
<p>Derimot er det greiere å få hentet inn JSON fra andre kilder enn sin egen server.  Må kan <em>injecte</em> en ny javascript-kilde-referanse i HTML-dom&#8217;en. Følgende kodesnutt viser i klartekst hvordan det går til:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"> document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;head&quot;</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;">appendChild</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">&lt;</span>em<span style="color: #339933;">&gt;</span>jsonScriptBlock<span style="color: #339933;">&lt;/</span>em<span style="color: #339933;">&gt;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Innholdet i variabelen <em>jsonScriptBlock</em> er HTML og kan være noe ala dette:<br />
&lt;script src=&#8221;http://api.flickr.com/services/feeds/news.gne?format=json&#8221; type=&#8221;text/javascript&#8221;/&gt;</p>
<p>Når den linjen settes inn i HTMLdom&#8217;en vil browseren laste ned og eksekvere JavaScriptet som mottas. Dette skjer på samme måte som man inkluderer vanlige JavaScript-filer i HTML&#8217;en. Den eneste lille forskjellen er at det skjer dynamisk, og typisk etter at siden er lastet og gjerne som en del av interaksjon med brukeren.</p>
<h2>Vi har data. Now what?</h2>
<p>Første linje i JSON-responsen fra Flickr ser ca slik ut:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"> jsonFlickrFeed<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>...</pre></div></div>

<p>Ettersom typen på og innholdet i fila som nettopp har blitt lastet ned er JavaScript, vil nettleseren eksekvere innholdet. I dette tilfellet betyr det at den vil kjøre funksjonen <em>jsonFlickrFeed( arg );</em> Argumentet er JSON-objektet, som representerer dataen vi har forespurt fra Flickr. Men funksjonen  <em>jsonFlickrFeed </em>finnes ikke ennå, og den står  vi fritt til å lage  (les: vi må, ellers skjer det fint lite):</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"> <span style="color: #003366; font-weight: bold;">function</span> jsonFlickrFeed<span style="color: #009900;">&#40;</span> json <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #006600; font-style: italic;">// Gjør ting med JSON-objektet</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Hva vi vil gjøre med JSON-objektet avhenger selvsagt litt av hva tilbyderen av dataen har inkludert, og av hvordan datastrukturen ser ut. For Flickr inneholder JSON-strukturen først noen header-felter med litt info om dataen, og deretter kommer en <em>array</em> med items man kan løpe gjennom for å hente ut forskjellige felter fra.</p>
<h2>Eksempel</h2>
<p>Dette eksempelet forutsettet at vi har javascript-rammeverket <a href="http://www.prototypejs.org/">Prototype</a> inkludert på HTML-siden, og at man har ett DIV-element på HTML-siden med<em> id=flickrContent.</em></p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">/**
  En generell funksjon for å sette inn en SCRIPT-tag med gitt src-URL i HEAD
  i HTML-dokumentet.
*/</span>
<span style="color: #003366; font-weight: bold;">function</span> injectScript<span style="color: #009900;">&#40;</span> url <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #003366; font-weight: bold;">var</span> scriptBlock <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Element<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">&quot;script&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">'src'</span><span style="color: #339933;">:</span> url<span style="color: #339933;">,</span><span style="color: #3366CC;">'type'</span><span style="color: #339933;">:</span><span style="color: #3366CC;">'text/javascript'</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;HEAD&quot;</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;">appendChild</span><span style="color: #009900;">&#40;</span> scriptBlock <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">/**
  Kaller bare injectScript, med vår flickr-URL.
*/</span>
<span style="color: #003366; font-weight: bold;">function</span> injectFlickrJson<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	injectScript<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'http://api.flickr.com/services/feeds/photos_public.gne?format=json&amp;amp;tags=bekk'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">/**
  Dette er funksjonen som JSON-responsen fra Flickr kaller når den blir lastet av nettleseren.
*/</span>
<span style="color: #003366; font-weight: bold;">function</span> jsonFlickrFeed<span style="color: #009900;">&#40;</span> resp <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	<span style="color: #006600; font-style: italic;">// For hver item som ligger i arrayen items i JSON-objektet...</span>
	resp.<span style="color: #660066;">items</span>.<span style="color: #660066;">each</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: #000066; font-weight: bold;">item</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        	<span style="color: #006600; font-style: italic;">// .. gjør følgende: Put item sin description inn i</span>
		<span style="color: #006600; font-style: italic;">// ett nytt DIV-elemenent og legg det inn i</span>
		<span style="color: #006600; font-style: italic;">// elementet 'flickrContent' som er en DIV i HTML-dokumentet vårt.</span>
		$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'flickrContent'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">new</span> Element<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">&quot;div&quot;</span> <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">update</span><span style="color: #009900;">&#40;</span> <span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #660066;">description</span> <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: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Og det var det hele. Resultatet skal være at en rekke bilder og tekst dukker opp i flickrContent-DIV&#8217;en. Ser man nøye på URL&#8217;en i funksjonen <em>injectFlickrJson </em>ser man parametert <em>tags=bekk</em>. En enkel utvidelse av denne funksjonen er å la den ta i mot et argument som kan sendes med til flickr. Dermed har man implementert et &#8220;søk&#8221; blandt alle flickrs millioner av bilder, med ca 9 linjer kode.</p>
<h2>Hva kan man bruke denne teknikken til</h2>
<p>Flere og flere tjenester som sitter på større mengder data, enten det er nyheter, bilder, værdata, trafikkdata, økonomi-ting, statistikk osv, åpner opp for bruk av hele eller deler av dataen sin. Ved å gi ut slik data til mange kloke hoder kan det komme uventede resultater. Kanskje det finnes sammenhenger mellom tempraturene i Sør-Afrika og økonomien på Island. Kan det være mindre tafikk i Bærum enn i indre Oslo Øst når Storebrand holder pressekonferanse?</p>
<p>Ekstern data kan også brukes til å berike ditt eget innhold. Har du artikler som handler om teknologi, og hvor teknologi-ord går igjen i teksten, kan det kanskje være en ide å knytte disse ordene til nyheter og andre artikler som tagget med den aktuelle teknologien. Disse nyhetene og artiklene kan da være hentet med JSON fra andre kilder og matchet med din artikkel-tekst. Stedsnavn kan knyttes til både værdata og bilder. Selskaper kan knyttes til børs-informasjon.</p>
<h2>Kilder og andre ressurser</h2>
<ul>
<li><a href="http://www.json.org/">http://www.json.org/</a></li>
<li><a href="http://www.prototypejs.org/learn/json">http://www.prototypejs.org/learn/json</a></li>
<li><a href="http://flickr.com/services/feeds/">http://flickr.com &#8211; http://flickr.com/services/feeds/</a></li>
<li><a href="http://apiwiki.twitter.com/REST+API+Documentation#TheEasiestWaytoPlayAroundwiththeTwitterAPI">http://twitter.com &#8211; http://apiwiki.twitter.com/REST+API+Documentation#TheEasiestWaytoPlayAroundwiththeTwitterAPI</a></li>
<li><a href="http://api.yr.no/weatherapi/documentation">http://api.yr.no/weatherapi/documentation</a></li>
<li><a href="http://www.bbc.co.uk/programmes/developers">http://www.bbc.co.uk/programmes/developers</a></li>
</ul>
<h2>PS.</h2>
<p>Merk at denne artikkelen ikke berører hverken kode-kvalitet eller sikkerhet. Det man får tilbake fra andre i form av JSON kan inneholde funksjonskall som kan være en sikkerhets risiko. Det man bør alltid utføre <em>santitization</em> på JSON-responsen.</p>
]]></content:encoded>
			<wfw:commentRss>http://open.bekk.no/json-ressurser-og-eksempel-javascript-kode/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

