More Fun with Handlebars.js

A bit more fun

by deanpeters

HTML

<script src="http://zeptojs.com/zepto.js"></script>
<script src="https://raw.github.com/wycats/handlebars.js/master/dist/handlebars.js"></script>
<h1>start demo</h1>
<div id="output"></div>
<script id="test-template" type="text/x-handlebars-template">  
<ul>
{{#each mainnav}}
    {{!-- note:
       -- for now, we're looking for an object item of @key.name
       -- perhaps a more resilient approach would be to write a plugin to check
       -- unless a @key == 'somevalue', etc ...
       --}}
    {{#if name}}
        <li>{{@key}} = {{name}} : {{url}} </li>
    {{else}}
        <li class="dropdown">
            <ol>
            {{#each this}}
                <li>{{{link dd-name href=dd-url alt="@key"}}}</li>
            {{/each}}
            </ol>
        </li>
    {{/if}}
{{/each}}
 </ul>    
</script>
<h2>end demo</h2>
<!-- ignore the JSFiddle warning about putting script in block below -->

CSS

li.dropdown {
    list-style-type:none;
    background-color: #e8e8e8;
}

JavaScript

/*
 * menu data object
 *
 * we'll create a plugin that has a default .json file, then updates via ajax
 *
 * NOTE: whle handlebars prefers arrays of objects, it can now handle objects of objects
 * see this thread for more info: 
 * https://github.com/wycats/handlebars.js/pull/272
 *
 * oh, for clarity, in the dropdown menus, I named the object keys
 * "dd-name" and "dd-url" ... this was only for example clarity
 * they could have just as easily been {"name":"foo", "url":bar"}
 */
var myMenuObject = {
    "mainnav" : {
        "home" : { "name":"Home", "url":"#home"},
        "first" : { "name":"1st Choice", "url": "#first"},
        "second" : { "name":"2nd  Choice", "url": "#second"},
        "third" : { "name":"3rd  Choice", "url": "#third"},
        "dropdown" : {
            "uno":{ "dd-name":"Uno (1)", "dd-url": "#dropdown_first"},
            "dos":{ "dd-name":"Dos (2)", "dd-url": "#dropdown_second"},
            "tres":{ "dd-name":"Tres (3)", "dd-url": "#dropdown_third"}        
        }
    }
};

/* a handlebars 'helper' to make hyperlinks neat-n-clean
 * see this page for more info:
 *    http://handlebarsjs.com/expressions.html#helpers
 */
Handlebars.registerHelper('link', function(text, options) {
  var attrs = [];

  for(var prop in options.hash) {
    attrs.push(prop + '="' + options.hash[prop] + '"');
  }

  return new Handlebars.SafeString(
    "<a " + attrs.join(" ") + ">" + text + "</a>"
  );
});

/* 
 *this is the actual code that compiles the 'template' into a method we call templateMethod
 *
 */
// compiling and displaying using built-in #each method
var templateSource = $("#test-template").html();         
var templateMethod = Handlebars.compile(templateSource); 
var outHTML = templateMethod(myMenuObject);
$("#output").append(outHTML);