;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o": ">", '"': '"', "'": ''' }; function escapeHTML(string) { return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) { return escapeMap[s] || s; }); } var regexCache = {}; var Renderer = function () {}; Renderer.prototype = { otag: "{{", ctag: "}}", pragmas: {}, buffer: [], pragmas_implemented: { "IMPLICIT-ITERATOR": true }, context: {}, render: function (template, context, partials, in_recursion) { // reset buffer & set context if (!in_recursion) { this.context = context; this.buffer = []; // TODO: make this non-lazy } // fail fast if (!this.includes("", template)) { if (in_recursion) { return template; } else { this.send(template); return; } } // get the pragmas together template = this.render_pragmas(template); // render the template var html = this.render_section(template, context, partials); // render_section did not find any sections, we still need to render the tags if (html === false) { html = this.render_tags(template, context, partials, in_recursion); } if (in_recursion) { return html; } else { this.sendLines(html); } }, /* Sends parsed lines */ send: function (line) { if (line !== "") { this.buffer.push(line); } }, sendLines: function (text) { if (text) { var lines = text.split("\n"); for (var i = 0; i < lines.length; i++) { this.send(lines[i]); } } }, /* Looks for %PRAGMAS */ render_pragmas: function (template) { // no pragmas if (!this.includes("%", template)) { return template; } var that = this; var regex = this.getCachedRegex("render_pragmas", function (otag, ctag) { return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g"); }); return template.replace(regex, function (match, pragma, options) { if (!that.pragmas_implemented[pragma]) { throw({message: "This implementation of mustache doesn't understand the '" + pragma + "' pragma"}); } that.pragmas[pragma] = {}; if (options) { var opts = options.split("="); that.pragmas[pragma][opts[0]] = opts[1]; } return ""; // ignore unknown pragmas silently }); }, /* Tries to find a partial in the curent scope and render it */ render_partial: function (name, context, partials) { name = trim(name); if (!partials || partials[name] === undefined) { throw({message: "unknown_partial '" + name + "'"}); } if (!context || typeof context[name] != "object") { return this.render(partials[name], context, partials, true); } return this.render(partials[name], context[name], partials, true); }, /* Renders inverted (^) and normal (#) sections */ render_section: function (template, context, partials) { if (!this.includes("#", template) && !this.includes("^", template)) { // did not render anything, there were no sections return false; } var that = this; var regex = this.getCachedRegex("render_section", function (otag, ctag) { // This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder return new RegExp( "^([\\s\\S]*?)" + // all the crap at the beginning that is not {{*}} ($1) otag + // {{ "(\\^|\\#)\\s*(.+)\\s*" + // #foo (# == $2, foo == $3) ctag + // }} "\n*([\\s\\S]*?)" + // between the tag ($2). leading newlines are dropped otag + // {{ "\\/\\s*\\3\\s*" + // /foo (backreference to the opening tag). ctag + // }} "\\s*([\\s\\S]*)$", // everything else in the string ($4). leading whitespace is dropped. "g"); }); // for each {{#foo}}{{/foo}} section do... return template.replace(regex, function (match, before, type, name, content, after) { // before contains only tags, no sections var renderedBefore = before ? that.render_tags(before, context, partials, true) : "", // after may contain both sections and tags, so use full rendering function renderedAfter = after ? that.render(after, context, partials, true) : "", // will be computed below renderedContent, value = that.find(name, context); if (type === "^") { // inverted section if (!value || Array.isArray(value) && value.length === 0) { // false or empty list, render it renderedContent = that.render(content, context, partials, true); } else { renderedContent = ""; } } else if (type === "#") { // normal section if (Array.isArray(value)) { // Enumerable, Let's loop! renderedContent = that.map(value, function (row) { return that.render(content, that.create_context(row), partials, true); }).join(""); } else if (that.is_object(value)) { // Object, Use it as subcontext! renderedContent = that.render(content, that.create_context(value), partials, true); } else if (typeof value == "function") { // higher order section renderedContent = value.call(context, content, function (text) { return that.render(text, context, partials, true); }); } else if (value) { // boolean section renderedContent = that.render(content, context, partials, true); } else { renderedContent = ""; } } return renderedBefore + renderedContent + renderedAfter; }); }, /* Replace {{foo}} and friends with values from our view */ render_tags: function (template, context, partials, in_recursion) { // tit for tat var that = this; var new_regex = function () { return that.getCachedRegex("render_tags", function (otag, ctag) { return new RegExp(otag + "(=|!|>|&|\\{|%)?([^#\\^]+?)\\1?" + ctag + "+", "g"); }); }; var regex = new_regex(); var tag_replace_callback = function (match, operator, name) { switch(operator) { case "!": // ignore comments return ""; case "=": // set new delimiters, rebuild the replace regexp that.set_delimiters(name); regex = new_regex(); return ""; case ">": // render partial return that.render_partial(name, context, partials); case "{": // the triple mustache is unescaped case "&": // & operator is an alternative unescape method return that.find(name, context); default: // escape the value return escapeHTML(that.find(name, context)); } }; var lines = template.split("\n"); for(var i = 0; i < lines.length; i++) { lines[i] = lines[i].replace(regex, tag_replace_callback, this); if (!in_recursion) { this.send(lines[i]); } } if (in_recursion) { return lines.join("\n"); } }, set_delimiters: function (delimiters) { var dels = delimiters.split(" "); this.otag = this.escape_regex(dels[0]); this.ctag = this.escape_regex(dels[1]); }, escape_regex: function (text) { // thank you Simon Willison if (!arguments.callee.sRE) { var specials = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\' ]; arguments.callee.sRE = new RegExp( '(\\' + specials.join('|\\') + ')', 'g' ); } return text.replace(arguments.callee.sRE, '\\$1'); }, /* find `name` in current `context`. That is find me a value from the view object */ find: function (name, context) { name = trim(name); // Checks whether a value is thruthy or false or 0 function is_kinda_truthy(bool) { return bool === false || bool === 0 || bool; } var value; // check for dot notation eg. foo.bar if (name.match(/([a-z_]+)\./ig)) { var childValue = this.walk_context(name, context); if (is_kinda_truthy(childValue)) { value = childValue; } } else { if (is_kinda_truthy(context[name])) { value = context[name]; } else if (is_kinda_truthy(this.context[name])) { value = this.context[name]; } } if (typeof value == "function") { return value.apply(context); } if (value !== undefined) { return value; } // silently ignore unkown variables return ""; }, walk_context: function (name, context) { var path = name.split('.'); // if the var doesn't exist in current context, check the top level context var value_context = (context[path[0]] != undefined) ? context : this.context; var value = value_context[path.shift()]; while (value != undefined && path.length > 0) { value_context = value; value = value[path.shift()]; } // if the value is a function, call it, binding the correct context if (typeof value == "function") { return value.apply(value_context); } return value; }, // Utility methods /* includes tag */ includes: function (needle, haystack) { return haystack.indexOf(this.otag + needle) != -1; }, // by @langalex, support for arrays of strings create_context: function (_context) { if (this.is_object(_context)) { return _context; } else { var iterator = "."; if (this.pragmas["IMPLICIT-ITERATOR"]) { iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator; } var ctx = {}; ctx[iterator] = _context; return ctx; } }, is_object: function (a) { return a && typeof a == "object"; }, /* Why, why, why? Because IE. Cry, cry cry. */ map: function (array, fn) { if (typeof array.map == "function") { return array.map(fn); } else { var r = []; var l = array.length; for(var i = 0; i < l; i++) { r.push(fn(array[i])); } return r; } }, getCachedRegex: function (name, generator) { var byOtag = regexCache[this.otag]; if (!byOtag) { byOtag = regexCache[this.otag] = {}; } var byCtag = byOtag[this.ctag]; if (!byCtag) { byCtag = byOtag[this.ctag] = {}; } var regex = byCtag[name]; if (!regex) { regex = byCtag[name] = generator(this.otag, this.ctag); } return regex; } }; return({ name: "mustache.js", version: "0.4.0", /* Turns a template and view into HTML */ to_html: function (template, view, partials, send_fun) { var renderer = new Renderer(); if (send_fun) { renderer.send = send_fun; } renderer.render(template, view || {}, partials); if (!send_fun) { return renderer.buffer.join("\n"); } } }); }(); /*! ICanHaz.js -- by @HenrikJoreteg */ /*global */ (function () { function trim(stuff) { if (''.trim) return stuff.trim(); else return stuff.replace(/^\s+/, '').replace(/\s+$/, ''); } // Establish the root object, `window` in the browser, or `global` on the server. var root = this; var ich = { VERSION: "0.10.2", templates: {}, // grab jquery or zepto if it's there $: (typeof window !== 'undefined') ? window.jQuery || window.Zepto || null : null, // public function for adding templates // can take a name and template string arguments // or can take an object with name/template pairs // We're enforcing uniqueness to avoid accidental template overwrites. // If you want a different template, it should have a different name. addTemplate: function (name, templateString) { if (typeof name === 'object') { for (var template in name) { this.addTemplate(template, name[template]); } return; } if (ich[name]) { console.error("Invalid name: " + name + "."); } else if (ich.templates[name]) { console.error("Template \"" + name + " \" exists"); } else { ich.templates[name] = templateString; ich[name] = function (data, raw) { data = data || {}; var result = Mustache.to_html(ich.templates[name], data, ich.templates); return (ich.$ && !raw) ? ich.$(trim(result)) : result; }; } }, // clears all retrieval functions and empties cache clearAll: function () { for (var key in ich.templates) { delete ich[key]; } ich.templates = {}; }, // clears/grabs refresh: function () { ich.clearAll(); ich.grabTemplates(); }, // grabs templates from the DOM and caches them. // Loop through and add templates. // Whitespace at beginning and end of all templates inside