Messing with Mediathread's Mustache.js code

Mediathread's Mustache code used a clever 'update' construct as a way to update part of a template. This was useful, but it was some pretty fundamental functionality that was built into Mustache.js version 0.4.0. Porting these changes to the upstream version of Mustache would take lots of work with each new release.

Instead of porting these changes to standard Mustache.js v2, I've been converting the Mediathread code to use Mustache in the more typical way: call Mustache.render() with a Mustache template and some data, which returns the rendered template. I'm using jQuery to attach the rendered Mustache templates to the DOM.

Here's an example of the old code:

    Mustache.update('annotation-list', context, {
        pre: function(elt) {
            jQuery(elt).hide();
            jQuery('.accordion').accordion('destroy');
        },
        post: function(elt) {
            jQuery(elt).show();
            jQuery('li.annotation-listitem', elt)
                .each(self.decorateLink);
        }
    });
  

And the corresponding section of the template:

    {{#>>annotation-list}}
    <ul id="asset-details-annotations-list">
        {{#annotation_list}}
        <li class="annotation-group">
            {{#category}}
            <h4>
                <div class="color-box"
                     style="background-color:{{color}}">
                </div>
                {{title}}
            </h4>
            <div class="accordion">
                <!-- etc. ... -->
            </div>
        </li>
    </ul>
    {{#/>>annotation-list}}
  

The "{{#>>annotation-list}}" syntax isn't standard Mustache. If this was a "partial", you could do: {{> annotation-list }}, according to the manual. But in order to update this at runtime using jQuery, we just need a unique identifier for this part of the DOM. Since an element's ID is always unique, we can use #asset-details-annotations-list, and remove {{#>>annotation-list}} and {{#/>>annotation-list}}.

The updated template just looks like this:

    <ul id="asset-details-annotations-list"></ul>
  

And a new template called asset_annotation_list.mustache has the contents of this element:

    {{#annotation_list}}
    <li class="annotation-group">
        {{#category}}
        <h4>
            <div class="color-box"
                 style="background-color:{{color}}">
    <!-- etc. ... -->
  

Now we can update the code in asset.js to use standard Mustache.render(), attaching the results to #asset-details-annotations-list:

    var $elt = jQuery('#asset-details-annotations-list');
    $elt.hide();
    jQuery('.accordion').accordion('destroy');
    var rendered = Mustache2.render(
        MediaThread.templates.asset_annotation_list, context);
    $elt.html(rendered);
    $elt.show();
    jQuery('li.annotation-listitem', $elt).each(self.decorateLink);
    // etc...
  

This is how Mediathread's asset viewer can be updated to standard, upstream Mustache.js. In one case, I just got rid of the old Mustache "partial" and just updated the DOM with jQuery, since there was only one field being updated. This old Mediathread code just updates the asset's title:

    Mustache.update('asset-view-header', context);
  

We don't really need to load a Mustache template for this. I changed the code to do this instead:

    jQuery('.asset-view-title').text(context['asset-current'].title);
  

You could argue that the old code is clearer in both my examples. The old code is semantically clearer, but it's also harder to tell what's actually going on, since a lot is happening in Mustache.update(). Also, now we're on a maintained version of Mustache.js, and Mediathread is in a good place for more refactors of this type. Maybe we can unify some of the work this code is doing, using some lessons learned in the newer JavaScript frameworks like Ember and React.