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.