﻿<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Colourblind</title>
  <link href="http://monochromacy.net/Feeds/Atom.ashx" rel="self" />
  <link href="http://monochromacy.net" rel="alternate" />
  <updated>2012-01-17T09:10:32Z</updated>
  <author>
    <name>Tom</name>
  </author>
  <id>tag:monochromacy.net,2000-01-01:</id>
  <entry>
    <title>Linq to SQL Deferred Loading Gotcha</title>
    <link href="http://monochromacy.net/Post/Linq-to-SQL-Deferred-Loading-Gotcha.aspx" />
    <id>tag:monochromacy.net,2012-01-17:/Posts/20120117091032</id>
    <updated>2012-01-17T09:10:32Z</updated>
    <content type="html">&lt;p&gt;So here's a good one. Say we have some data in a table:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;Id | Name
---+-------
 1 | Steve
 2 | Claire
 3 | Sarah 
 4 | Dave
 5 | Katie&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And we run a LINQ-to-SQL query against it.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;var results = dataContext.Persons.Where(x =&amp;gt; x.Name.Contains(&quot;dave&quot;));&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It does what you'd expect it to do. Our database is case insensitive, so it matches as such.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;Func&amp;lt;Persons, bool&amp;gt; predicate = x =&amp;gt; x.Name.Contains(&quot;dave&quot;));
var results = dataContext.Persons.Where(predicate);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Just when you think you have it licked, the above returns no rows. The problem is that the fact that we're using the predicate through a variable means that the data is grabbed from the DB before the Where() and then is filtered on the C#-side of the fence, which means your string comparisons are now case sensitive.&lt;/p&gt;
&lt;p&gt;It's a slightly odd example (just a specific one that bit me on the arse), but it could have more serious ramifications. While this one fails pretty obviously, how about this: rather than getting 10 rows from the database you could be getting a million and then processing the lot of them in code.&lt;/p&gt;
&lt;p&gt;Between enigmatic stuff like this, DataContext lifetime, detached objects and the eternally fun &lt;a href=&quot;http://goneale.com/2009/03/26/untie-linq-to-sql-connection-string-from-application-settings/&quot;&gt;connection string pinata game&lt;/a&gt;, I still don't &lt;em&gt;trust&lt;/em&gt; Linq to SQL completely.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Making MSBuild in NANT act like MSBuild in Visual Studio</title>
    <link href="http://monochromacy.net/Post/Making-MSBuild-in-NANT-act-like-MSBuild-in-Visual-Studio.aspx" />
    <id>tag:monochromacy.net,2011-12-21:/Posts/20111221094537</id>
    <updated>2011-12-21T09:45:37Z</updated>
    <content type="html">&lt;p&gt;So I was making some NANT scripts for an ASP.NET MVC project.&lt;/p&gt;
&lt;p&gt;Rather than going through the rigmarole of maintaining references and dependencies in two places (the VS project file and the NANT scripts), this time round I started using the &amp;lt;msbuild&amp;gt; task from nantcontrib instead of invoking the compiler directly using the plain old &amp;lt;csc&amp;gt; task. After making sure I set my OutDir I run NANT and get a failed build while copying a file, which is odd because I don't want MSBuild doing anything of the sort. It builds fine from Visual Studio, but after a little investigation it turns out that MSBuild is attempting to copy a file which is in the project but is missing from the file system. It's trying to drop it, along with the rest of the project contents, into _PublishedWebsites which has attaching itself to my output directory, like a warty blemish or tumour on my otherwise pristine build.&lt;/p&gt;
&lt;p&gt;By setting the verbosity level of MSBuild to Diagnostic in both NANT and Visual Studio I could diff the two outputs and see where the processes started to diverge. The output of the NANT ran to a svelte 26k lines, but a quick search on '_PublishedWebsites' turns up the part of the log which includes the failing build. The copy operation is happening within a _CopyWebApplication target. Time to do a quick search in the Visual Studio MSBuild log . . .&lt;/p&gt;
&lt;p&gt;Aha! Here's the slippery little devil:&lt;/p&gt;
&lt;blockquote&gt;Target &quot;_CopyWebApplication&quot; skipped, due to false condition;  (!$(Disable_CopyWebApplication) And '$(OutDir)' != '$(OutputPath)') was evaluated as (!False And 'bin\' != 'bin\').&lt;/blockquote&gt;
&lt;p&gt;But why? Why would you do that? What is the OutputPath even supposed to be? According to &lt;span class=&quot;code&quot;&gt;MSBuild\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets&lt;/span&gt; . . .&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&amp;lt;!--
============================================================
_CopyWebApplication

This target will copy the build outputs along with the content files into a 
_PublishedWebsites folder.

This Task is only necessary when $(OutDir) has been redirected to a folder 
other than ~\bin such as is the case with Team Build.

The original _CopyWebApplication is now a Legacy, you can still use it by 
setting $(UseWPP_CopyWebApplication) to true. By default, it now change to 
use _WPPCopyWebApplication target in Microsoft.Web.Publish.targets. It allow 
to leverage the web.config trsnaformation.
============================================================
--&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Fine. Whatever. Regardless of the rationale, if you set your OutDir and OutputPath properties to the same value in the NANT &amp;lt;msbuild&amp;gt; task:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&amp;lt;msbuild project=&quot;${dir.src}/${project::get-name()}/${project::get-name()}.csproj&quot;
      target=&quot;Rebuild&quot; verbosity=&quot;Minimal&quot;&amp;gt;
   &amp;lt;property name=&quot;Configuration&quot; value=&quot;Release&quot; /&amp;gt;
   &amp;lt;property name=&quot;OutDir&quot; value=&quot;../../${dir.build}/${project::get-name()}/bin/&quot; /&amp;gt;
   &amp;lt;property name=&quot;OutputPath&quot; value=&quot;../../${dir.build}/${project::get-name()}/bin/&quot; /&amp;gt;
&amp;lt;/msbuild&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then your case of _PublishedWebsites should clear up in no time. (Alternatively you could set the Disable_CopyWebApplication property, but I'm attempting to get our NANT builds as close to our VS builds as possible.) As an addendum, once I knew what I was looking for I found quite a bit of confusion related to OutputPut, including a blog post from Mark Needham who also &lt;a href=&quot;http://www.markhneedham.com/blog/2008/08/14/msbuild-use-outputpath-instead-of-outdir/&quot;&gt;ran into problems related to OutputPath when tweaking OutDir&lt;/a&gt; and who turned up this nugget from MSDN:&lt;/p&gt;
&lt;blockquote&gt;OutputPath: This property is typically specified in the project file and resembles OutDir. OutputPath has been deprecated and OutDir should be used instead whenever possible.&lt;/blockquote&gt;
&lt;p&gt;At this point I stopped caring and reversed out of the rabbit hole.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Client-side templating with Handlebars.js</title>
    <link href="http://monochromacy.net/Post/Client-side-templating-with-Handlebarsjs.aspx" />
    <id>tag:monochromacy.net,2011-11-30:/Posts/20111130224338</id>
    <updated>2011-11-30T22:43:38Z</updated>
    <content type="html">&lt;p&gt;So back to data molestation in Javascript.&lt;/p&gt;
&lt;p&gt;Now we have our post-processed data it's time to display it to the user.&lt;/p&gt;
&lt;p&gt;Templating in Javascript seems to be in vogue at the moment, so there's a pretty decent selection to choose from. Originally I was using jquery-tmpl, but since that project got &lt;a href=&quot;https://github.com/jquery/jquery-tmpl/blob/master/README.md&quot;&gt;abandoned&lt;/a&gt; in favour of something &lt;a href=&quot;http://www.borismoore.com/2011/10/jquery-templates-and-jsviews-roadmap.html&quot;&gt;more awesomer&lt;/a&gt; it was time to have a look at alternatives. I initially fell upon &lt;a href=&quot;http://mustache.github.com/&quot;&gt;Mustache&lt;/a&gt; (to be honest, mainly because of the name) but founds myself butting up against the stringently 'logic-less' approach. I guess if you are stricter with your view-models it's less of an issue, but I just found it a little restrictive. &lt;a href=&quot;http://www.handlebarsjs.com/&quot;&gt;Handlebars&lt;/a&gt; is an evolution of Mustache from Yehuda Katz (of Rails fame), and appears to scratch the itches that Mustache leaves me with in addition to being a superset of the Mustache syntax. Also, the name is still cool.&lt;/p&gt;
&lt;p&gt;A quick note, before we get started. On my Mustache-based travels I stumbled across ICanHaz.js, which simplifies the process and has some really nice ideas. For example, on page load it grabs all of the templates and adds them to a globally available collection for ease of use. This becomes even more useful in Handlebars since it requires an additional compilation step. I ended up writing something very similar but considerably more primitive, and here it is:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;var&lt;/span&gt; BandleHars = {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;    templateCache : {},&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;    init : &lt;span class=&quot;kwrd&quot;&gt;function&lt;/span&gt;() {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;        var templateList = $(&lt;span class=&quot;str&quot;&gt;'script[type=&quot;text/html&quot;]'&lt;/span&gt;);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;        templateList.each(&lt;span class=&quot;kwrd&quot;&gt;function&lt;/span&gt;(index, value) { BandleHars.templateCache[value.id] = Handlebars.compile($(value).html()); });&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   6:  &lt;/span&gt;        templateList.remove();&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   7:  &lt;/span&gt;    },&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   8:  &lt;/span&gt;    render : &lt;span class=&quot;kwrd&quot;&gt;function&lt;/span&gt;(templateName, data) {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   9:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;.templateCache[templateName](data)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  10:  &lt;/span&gt;    }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  11:  &lt;/span&gt;};&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  12:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  13:  &lt;/span&gt;$(&lt;span class=&quot;kwrd&quot;&gt;function&lt;/span&gt;() { BandleHars.init(); });&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Right, let's get back to templating. First we need our data. I used a grab of the first few posts of this very site, pretty much as it's dumped out by &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx&quot;&gt;System.Web.Script.Serialization.JavaScriptSerializer&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;var&lt;/span&gt; data = [ &lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;  {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;Comments&quot;&lt;/span&gt; : [&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;        { &lt;span class=&quot;str&quot;&gt;&quot;Body&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;. . . the comment system.&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;CommentId&quot;&lt;/span&gt; : 1,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   6:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;DateCreated&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;/Date(1248627151247)/&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   7:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;GravatarUrl&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;http://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?d=identicon&amp;amp;s=64&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   8:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;Heading&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;Testing . . .&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   9:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;Poster&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;Tom&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  10:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;Website&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;http://monochromacy.net/&quot;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  11:  &lt;/span&gt;        },&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  12:  &lt;/span&gt;        { &lt;span class=&quot;str&quot;&gt;&quot;Body&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;n/t&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  13:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;CommentId&quot;&lt;/span&gt; : 2,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  14:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;DateCreated&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;/Date(1254127922440)/&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  15:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;GravatarUrl&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;http://www.gravatar.com/avatar/d41d8cd98f00b204e9800998ecf8427e?d=identicon&amp;amp;s=64&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  16:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;Heading&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;Notification Test&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  17:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;Poster&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;Test&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  18:  &lt;/span&gt;          &lt;span class=&quot;str&quot;&gt;&quot;Website&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  19:  &lt;/span&gt;        }&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  20:  &lt;/span&gt;      ],&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  21:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;DateCreated&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;/Date(1248624603550)/&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  22:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;DateLastTouched&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;/Date(1248624603550)/&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  23:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;Heading&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;Oh hai!&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  24:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;PostId&quot;&lt;/span&gt; : 1,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  25:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;Slug&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;Oh-hai&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  26:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;Summary&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;This weblog will be largely concerned with ASP.NET, C# and ...&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  27:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;Tags&quot;&lt;/span&gt; : [ &lt;span class=&quot;str&quot;&gt;&quot;Waffle&quot;&lt;/span&gt; ]&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  28:  &lt;/span&gt;  },&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  29:  &lt;/span&gt;  &lt;span class=&quot;rem&quot;&gt;/* SNIP */&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  30:  &lt;/span&gt;  { &lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  31:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;Comments&quot;&lt;/span&gt; : [  ],&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  32:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;DateCreated&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;/Date(1261657386630)/&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  33:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;DateLastTouched&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;/Date(1261657386630)/&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  34:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;Heading&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;Introducing Compares Favourably&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  35:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;PostId&quot;&lt;/span&gt; : 8,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  36:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;Slug&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;Introducing-Compares-Favourably&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  37:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;Summary&quot;&lt;/span&gt; : &lt;span class=&quot;str&quot;&gt;&quot;So I made a database schema comparison tool for MSSQL 2005.\nCompares Favourably\n&amp;lt;p ...&quot;&lt;/span&gt;,&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  38:  &lt;/span&gt;    &lt;span class=&quot;str&quot;&gt;&quot;Tags&quot;&lt;/span&gt; : [ &lt;span class=&quot;str&quot;&gt;&quot;ComparesFavourably&quot;&lt;/span&gt;, &lt;span class=&quot;str&quot;&gt;&quot;dotNet&quot;&lt;/span&gt;, &lt;span class=&quot;str&quot;&gt;&quot;Projects&quot;&lt;/span&gt; ]&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  39:  &lt;/span&gt;  },&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  40:  &lt;/span&gt;];&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  41:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  42:  &lt;/span&gt;var dataSet = &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; DataContainer(data, 3);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  43:  &lt;/span&gt;dataSet.update = &lt;span class=&quot;kwrd&quot;&gt;function&lt;/span&gt;() &lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  44:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  45:  &lt;/span&gt;    &lt;span class=&quot;rem&quot;&gt;// We'll come back to this . . .&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  46:  &lt;/span&gt;};&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  47:  &lt;/span&gt;dataSet.sortProperty = &lt;span class=&quot;str&quot;&gt;'DateCreated'&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  48:  &lt;/span&gt;$(&lt;span class=&quot;kwrd&quot;&gt;function&lt;/span&gt;() { dataSet.update(); });&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here I'm setting up the &lt;a href=&quot;/Post/Data-Wrangling-on-the-Client-with-Javascript.aspx&quot;&gt;DataContainer&lt;/a&gt; with three items to a page, sorted on the created data and then running the (currently empty) update function once the DOM has been loaded. Now it's time for some markup to display and manipulate our data.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Paging&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;horizontal&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;return dataSet.pageDown();&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Page down&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;return dataSet.pageUp();&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Page up&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   6:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   7:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Sort by&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   8:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;horizontal&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   9:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;return dataSet.setSortProperty('Heading');&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Heading&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  10:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;return dataSet.setSortProperty('Summary');&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Summary&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  11:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;return dataSet.setSortProperty('Slug');&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Slug&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  12:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;return dataSet.setSortProperty('DateCreated');&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Date Created&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;li&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  13:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Nice and simple. This will page the data up and down, allow us to change the sort criteria, and includes some bonus hey-that's-not-what-label-elements-are-for abuse. Sue me. I figure a tag filter would make sense in this context and since this is dependant on the data it will need to be templated. First we need a container for our filter buttons:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Tags&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;horizontal&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;tagsFilter&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And now a template for creating the filter links:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;tagsFilterTemplate&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;text/html&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;{{#each data}}&amp;lt;li&amp;gt;&amp;lt;a href=&lt;span class=&quot;str&quot;&gt;&quot;#&quot;&lt;/span&gt; onclick=&lt;span class=&quot;str&quot;&gt;&quot;return dataSet.addFilter('Tags', '{{this}}');&quot;&lt;/span&gt;&amp;gt;{{&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;}}&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;{{/each}}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;&amp;lt;li&amp;gt;&amp;lt;a href=&lt;span class=&quot;str&quot;&gt;&quot;#&quot;&lt;/span&gt; onclick=&lt;span class=&quot;str&quot;&gt;&quot;return dataSet.removeFilter('Tags');&quot;&lt;/span&gt;&amp;gt;remove&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The above Bandlehars code (I hate that name already) will fetch and compile this template on body load, so now we just need to add this to our DataContainer update function to include the template rendering:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;dataSet.update = &lt;span class=&quot;kwrd&quot;&gt;function&lt;/span&gt;() &lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;    &lt;span class=&quot;rem&quot;&gt;// There's still more to come!&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;    $(&lt;span class=&quot;str&quot;&gt;'#tagsFilter'&lt;/span&gt;).html(Bandlehars.render(&lt;span class=&quot;str&quot;&gt;'tagsFilterTemplate'&lt;/span&gt;, { data : dataSet.getPropertyValues(&lt;span class=&quot;str&quot;&gt;'Tags'&lt;/span&gt;) }));&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;};&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, once the page is loaded and then whenever it is filtered, the list of available tags will be updated. This means we can drill down further using additional filters. Worth noting is that we're wrapping our data in another object, since Handlebars doesn't accept raw arrays as a data context. So that's the filters sorted. But we still can't see the data itself. It's time for another container and another template.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;data&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;dataTemplate&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;text/html&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;{{#each data}}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;&amp;lt;div&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   6:  &lt;/span&gt;    &amp;lt;h2&amp;gt;&amp;lt;a href=&lt;span class=&quot;str&quot;&gt;&quot;http://monochromacy.net/Post/{{Slug}}.aspx&quot;&lt;/span&gt;&amp;gt;{{Heading}}&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   7:  &lt;/span&gt;    &amp;lt;p&amp;gt;&amp;lt;em&amp;gt;{{DateCreated}}&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   8:  &lt;/span&gt;    &amp;lt;p&amp;gt;{{Summary}}&amp;lt;/p&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   9:  &lt;/span&gt;    &amp;lt;label&amp;gt;Tags&amp;lt;/label&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  10:  &lt;/span&gt;    &amp;lt;ul &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;str&quot;&gt;&quot;horizontal&quot;&lt;/span&gt;&amp;gt;{{#each Tags}}&amp;lt;li&amp;gt;&amp;lt;a href=&lt;span class=&quot;str&quot;&gt;&quot;#&quot;&lt;/span&gt; onclick=&lt;span class=&quot;str&quot;&gt;&quot;return dataSet.addFilter('Tags', '{{this}}');&quot;&lt;/span&gt;&amp;gt;{{&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;}}&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;{{/each}}&amp;lt;/ul&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  11:  &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  12:  &lt;/span&gt;{{/each}}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  13:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now to add it to our DataContainer update function.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;dataSet.update = &lt;span class=&quot;kwrd&quot;&gt;function&lt;/span&gt;() &lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;{&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;    $(&lt;span class=&quot;str&quot;&gt;'#data'&lt;/span&gt;).html(Bandlehars.render(&lt;span class=&quot;str&quot;&gt;'dataTemplate'&lt;/span&gt;, { data : dataSet.getData() }));&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;    $(&lt;span class=&quot;str&quot;&gt;'#tagsFilter'&lt;/span&gt;).html(Bandlehars.render(&lt;span class=&quot;str&quot;&gt;'tagsFilterTemplate'&lt;/span&gt;, { data : dataSet.getPropertyValues(&lt;span class=&quot;str&quot;&gt;'Tags'&lt;/span&gt;) }));&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;};&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Well it's a start. What's next? How about comments.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;dataTemplate&quot;&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&quot;text/html&quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;{{#each data}}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;&amp;lt;div&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;    &amp;lt;h2&amp;gt;&amp;lt;a href=&lt;span class=&quot;str&quot;&gt;&quot;http://monochromacy.net/Post/{{Slug}}.aspx&quot;&lt;/span&gt;&amp;gt;{{Heading}}&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;    &amp;lt;p&amp;gt;&amp;lt;em&amp;gt;{{DateCreated}}&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   6:  &lt;/span&gt;    &amp;lt;p&amp;gt;{{Summary}}&amp;lt;/p&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   7:  &lt;/span&gt;    &amp;lt;label&amp;gt;Tags&amp;lt;/label&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   8:  &lt;/span&gt;    &amp;lt;ul &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;str&quot;&gt;&quot;horizontal&quot;&lt;/span&gt;&amp;gt;{{#each Tags}}&amp;lt;li&amp;gt;&amp;lt;a href=&lt;span class=&quot;str&quot;&gt;&quot;#&quot;&lt;/span&gt; onclick=&lt;span class=&quot;str&quot;&gt;&quot;return dataSet.addFilter('Tags', '{{this}}');&quot;&lt;/span&gt;&amp;gt;{{&lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;}}&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;{{/each}}&amp;lt;/ul&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   9:  &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  10:  &lt;/span&gt;&amp;lt;br /&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  11:  &lt;/span&gt;{{#&lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; Comments.length}}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  12:  &lt;/span&gt;&amp;lt;div &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;str&quot;&gt;&quot;comments&quot;&lt;/span&gt;&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  13:  &lt;/span&gt;    &amp;lt;h4&amp;gt;Comments&amp;lt;/h4&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  14:  &lt;/span&gt;    &amp;lt;ul&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  15:  &lt;/span&gt;{{#each Comments}}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  16:  &lt;/span&gt;        &amp;lt;li&amp;gt;{{Heading}} - {{Body}} - {{Poster}}&amp;lt;/li&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  17:  &lt;/span&gt;{{/each}}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  18:  &lt;/span&gt;    &amp;lt;/ul&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  19:  &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  20:  &lt;/span&gt;{{/&lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt;}}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  21:  &lt;/span&gt;&amp;lt;hr /&amp;gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  22:  &lt;/span&gt;{{/each}}&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;  23:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As you can see, we've got a conditional part of the template in there. This is the kind of thing that Mustache consciously avoids, but I personally find quite useful.&lt;/p&gt;
&lt;p&gt;A note about line 11 above. The Handlebars site says that the if block helper evaluates an empty array to false, and I also uncovered a &lt;a href=&quot;https://github.com/wycats/handlebars.js/pull/66&quot;&gt;pull request on Github&lt;/a&gt; mentioning this very thing that was merged on June 27. However, the latest download is the v1 beta-3 which was packaged on June 2, hence resorting to the .length trick. It looks like this won't be necessary after the next release.&lt;/p&gt;
&lt;p&gt;Finally, .NET has done something weird and unseemly to our date values, so we need some way to tweak those back into shape. Thankfully another feature of Handlebars is the ability to add custom helpers.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;Handlebars.registerHelper(&lt;span class=&quot;str&quot;&gt;&quot;dotNetDate&quot;&lt;/span&gt;, &lt;span class=&quot;kwrd&quot;&gt;function&lt;/span&gt;(context) {&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;var&lt;/span&gt; m = context.match(/^\/Date\((\d+)\)\/$/);&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;var&lt;/span&gt; date = &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;;&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (m)&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;        date = &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; Date(parseInt(m[1]));&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   6:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; date.toLocaleDateString();&lt;/pre&gt;
&lt;pre&gt;&lt;span class=&quot;lnum&quot;&gt;   7:  &lt;/span&gt;});&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And we can invoke it using this:&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;{{dotNetDate DateCreated}}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Giving us our final version, which you can see running here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/Resources/DataContainer/&quot;&gt;DataContainer + Handlebars.js Example&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The downsides? Unfortunately this is an SEO black hole since all of the real content is injected in via Javascript at page load. You'll need to render this on the server-side in order to receive any search engine attention at all. That said, there's &lt;a href=&quot;http://mustache.github.com/&quot;&gt;Mustache&lt;/a&gt; implementations in a tonne of viable server-side languages and while the few changes to Handlebars almost certainly increase the complexity . . . hmmm. Time for another weekend project?&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Data Wrangling on the Client with Javascript</title>
    <link href="http://monochromacy.net/Post/Data-Wrangling-on-the-Client-with-Javascript.aspx" />
    <id>tag:monochromacy.net,2011-10-24:/Posts/20111024212046</id>
    <updated>2011-10-24T20:20:46Z</updated>
    <content type="html">&lt;p&gt;Filtering, sorting and paging. These three operations are the bread and butter of data display. And it really is a display concern, so why not push it as far as possible into the presentation layer? When it comes to webapps that means the browser. So I wrote a data wrapper in Javascript as part of one of my &lt;a href=&quot;https://github.com/colourblind/StopWastingMyTime&quot;&gt;side projects&lt;/a&gt;. It goes by the highly uninspired name of &lt;a href=&quot;https://github.com/colourblind/StopWastingMyTime/blob/master/src/StopWastingMyTime/Static/Javascript/DataContainer.js&quot;&gt;DataContainer&lt;/a&gt;, because I was having an unoriginal day.&lt;/p&gt;
&lt;h3&gt;Setting up&lt;/h3&gt;
&lt;p&gt;Everything is contained in the DataContainer object, and the constructor takes the data itself as an array of objects, and the number of objects on each page.&lt;/p&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;var data = [
    {
        color: &quot;red&quot;,
        value: &quot;#f00&quot;,
        prime: true,
        rand: 1
    },
    {
        color: &quot;green&quot;,
        value: &quot;#0f0&quot;,
        prime: true,
        rand: 3
    },
    {
        color: &quot;blue&quot;,
        value: &quot;#00f&quot;,
        prime: true,
        rand: 1
    },
    {
        color: &quot;cyan&quot;,
        value: &quot;#0ff&quot;,
        prime: false,
        rand: 2
    },
    {
        color: &quot;magenta&quot;,
        value: &quot;#f0f&quot;,
        prime: false,
        rand: 1
    },
    {
        color: &quot;yellow&quot;,
        value: &quot;#ff0&quot;,
        prime: false,
        rand: 1
    },
    {
        color: &quot;black&quot;,
        value: &quot;#000&quot;,
        prime: false,
        rand: 3
    }
];

var pageSize = 10;
var dataSet = new DataContainer(data, pageSize);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As intimated above, there are three types of operations available in DataContainer - filtering, sorting and paging - and they are always performed in the following order.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Filtering&lt;/li&gt;
&lt;li&gt;Sorting&lt;/li&gt;
&lt;li&gt;Paging&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A call to &lt;span class=&quot;code&quot;&gt;getData&lt;/span&gt; takes the original dataset and then applies the filters, performs a sort and then splits the result onto the correct page and returns it. The most practical way of fetching data is through the use of callbacks. Whenever any operations are performed on the DataContainer which result in the resulting dataset changing the DataContainer's &lt;span class=&quot;code&quot;&gt;update&lt;/span&gt; function is called. If you want to update UI elements whenever the data is changed (and what else would you be using it for?) then simple pass the DataContainer a new &lt;span class=&quot;code&quot;&gt;update&lt;/span&gt; method with your own code. I'll be covering this in more detail in the next post - this is more about how to use the various DataContainer methods available.&lt;/p&gt;
&lt;h3&gt;Controls&lt;/h3&gt;
&lt;p&gt;Here's a brief rundown of the methods available on each DataContainer object.&lt;/p&gt;
&lt;h4&gt;Filtering&lt;/h4&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;dataSet.addFilter(property, value);
dataSet.removeFilter(property);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Filtering is done based on the properties of each object in the initial array. Given the above data, if you make the call &lt;span class=&quot;code&quot;&gt;dataSet.addFilter(&quot;primary&quot;, true)&lt;/span&gt; then subsequent calls to &lt;span class=&quot;code&quot;&gt;getData&lt;/span&gt; will return on only those objects with the primary property set to true. If the initial data contains complex objects, then you can drill down into the object hierarchy using dot notation, the same way you would in code.&lt;/p&gt;
&lt;p&gt;You can add multiple filters, allowing you filter the data more specifically. Also of note is the &lt;span class=&quot;code&quot;&gt;getPropertyValues&lt;/span&gt; method. When you pass this the name of a property it will apply the current filters to the dataset and then build a list of values of that property. The intent here is make building a drill-down UI nice and easy.&lt;/p&gt;
&lt;h4&gt;Sorting&lt;/h4&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;dataSet.toggleSortDir();
dataSet.setSortProperty(property);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can only sort by one property at a time. If you call the &lt;span class=&quot;code&quot;&gt;setSortProperty&lt;/span&gt; method a subsequent time with the same property name it will toggle the sort between ascending and descending.&lt;/p&gt;
&lt;h4&gt;Paging&lt;/h4&gt;
&lt;div class=&quot;code&quot;&gt;
&lt;pre&gt;dataSet.pageUp();
dataSet.pageDown();
dataSet.setPage(pageNum);&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;All pretty self explanatory. The pages are zero-indexed. You can also use the &lt;span class=&quot;code&quot;&gt;maxPage&lt;/span&gt; method to get the index of the final page.&lt;/p&gt;
&lt;h3&gt;Yay&lt;/h3&gt;
&lt;p&gt;There's real advantages to doing this stuff in the browser.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It means that your backend infrastructure can be swapped out easily. Wish to port from ASP.NET to Rails? It's not exactly free, but it's less work than it would be otherwise&lt;/li&gt;
&lt;li&gt;No more sorting, filtering and paging gunk in your controllers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However . . .&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Doesn't scale so good. For large datasets or crappy hosts you're going to kill the browser&lt;/li&gt;
&lt;li&gt;If you want a non-Javascript fallback you'll need to implement everything ye olde way anyway&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is going to get long and boring so I'll move the second half of this over to second post in a couple of weeks. The next post will show how to create a dynamic UI over the top of DataContainer using Javascript templating.&lt;/p&gt;
&lt;h5&gt;&lt;em&gt;Random burbling follows:&lt;/em&gt;&lt;/h5&gt;
&lt;p&gt;&lt;em&gt;In my professional life we need to target everything when it comes to browsers. Sales ride on it and you can't just clam the site up because users are a bunch of dirty, IE6-using, tech-ignorant peasants. While we can create sites that rely heavily on Javascript we still need a Javascript-free fallback, and so we end up doing the work twice, in two different languages and on two different sides of the client-server divide. Usually this means we shy away from too much Javascript due to our time budget. Since this was part of an intranet project it was nice to be able to get down and write some real JS code, safe in the knowledge that if someone isn't using a supporting browser I can just walk over to the other side of the office and slap them. That said I did a trawl through some sites recently and a good proportion of them in our target market sector (fashion), simply don't work without Javascript. Maybe the days of non-Javascript fallbacks are past. Man, that would be great.&lt;/em&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>I gone done a Rainmeter skin</title>
    <link href="http://monochromacy.net/Post/I-gone-done-a-Rainmeter-skin.aspx" />
    <id>tag:monochromacy.net,2011-09-17:/Posts/20110917133905</id>
    <updated>2011-09-17T12:39:05Z</updated>
    <content type="html">&lt;p&gt;I've been playing around with &lt;a href=&quot;http://rainmeter.net&quot; target=&quot;_blank&quot;&gt;Rainmeter&lt;/a&gt; recently and have nailed together my own skin.&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;a href=&quot;/Resources/Praxis.zip&quot;&gt;&lt;img alt=&quot;Praxis Rainmeter skins&quot; src=&quot;/Resources/rainmeter_0.png&quot; width=&quot;716&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click on the image above to download the skin files. It contains a clock, CPU and memory graphs, network in and out, disk usage, RSS reader, and some system info. And yes, the look is partially inspired by &lt;a href=&quot;http://deusex.com/&quot; target=&quot;_blank&quot;&gt;Deus Ex: Human Revolution&lt;/a&gt;, which may or may not be responsible for the slow rate of updates recently. Ahem.&lt;/p&gt;
&lt;p&gt;One thing to note is that the snapping will be buggy against the clock, since the automatic width and height of string meters doesn't take into account the transformation matrix. I found a link to one of the Rainmeter devs confirming this, but my Google-fu is weak and I can't find it now. Also, thanks to Oscar Del Ben for this &lt;a href=&quot;http://github-trends.oscardelben.com/&quot; target=&quot;_blank&quot;&gt;Github feeds&lt;/a&gt; and Eidos forum user f0xhound for his Deus Ex font.&lt;/p&gt;
&lt;p&gt;In other news:&lt;/p&gt;
&lt;p align=&quot;center&quot;&gt;&lt;img alt=&quot;.&quot; src=&quot;/Resources/y_u_upload.png&quot; width=&quot;482&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://addons.mozilla.org&quot; target=&quot;_blank&quot;&gt;addons.mozilla.org&lt;/a&gt; appears to be sucking the addons &lt;em&gt;right out of my browser&lt;/em&gt;. That's just mean.&lt;/p&gt;</content>
  </entry>
</feed>
