From c6d4116cba7666d59fe73290cf7cad395f86925b Mon Sep 17 00:00:00 2001 From: Rufus Pollock Date: Sun, 27 May 2012 01:27:26 +0100 Subject: [PATCH] [#79,refactor][s]: switch from (old) jquery.mustache to latest mustache.js - fixes #79. * This mustache has support for nested values e.g. {{sub.x.y}} * Specifically mustache.js as of Fri Feb 24 09:58:31 2012 +0100 2f135e2e15dcc3c61385212261faaf00597bae10 --- app/index.html | 2 +- app/js/app.js | 2 +- src/view-graph.js | 4 +- src/view-grid.js | 8 +- src/view-map.js | 2 +- src/view-timeline.js | 2 +- src/view-transform-dialog.js | 4 +- src/view.js | 10 +- test/index.html | 2 +- vendor/jquery.mustache.js | 346 ----------------- vendor/mustache/0.5.0-dev/mustache.js | 536 ++++++++++++++++++++++++++ 11 files changed, 554 insertions(+), 364 deletions(-) delete mode 100755 vendor/jquery.mustache.js create mode 100644 vendor/mustache/0.5.0-dev/mustache.js diff --git a/app/index.html b/app/index.html index 6f52251e..818703a0 100644 --- a/app/index.html +++ b/app/index.html @@ -35,7 +35,7 @@ - + diff --git a/app/js/app.js b/app/js/app.js index b3ea3f22..f77375a0 100755 --- a/app/js/app.js +++ b/app/js/app.js @@ -102,7 +102,7 @@ var ExplorerApp = Backbone.View.extend({ function makeEmbedLink(state) { var link = self.makePermaLink(state); link = link + '&embed=true'; - var out = $.mustache('', {link: link}); + var out = Mustache.render('', {link: link}); return out; } explorer.state.bind('change', function() { diff --git a/src/view-graph.js b/src/view-graph.js index 78eb12d8..6b5374c4 100644 --- a/src/view-graph.js +++ b/src/view-graph.js @@ -120,7 +120,7 @@ my.Graph = Backbone.View.extend({ render: function() { var self = this; var tmplData = this.model.toTemplateJSON(); - var htmls = $.mustache(this.template, tmplData); + var htmls = Mustache.render(this.template, tmplData); $(this.el).html(htmls); this.$graph = this.el.find('.panel.graph'); @@ -375,7 +375,7 @@ my.Graph = Backbone.View.extend({ seriesName: String.fromCharCode(idx + 64 + 1), }, this.model.toTemplateJSON()); - var htmls = $.mustache(this.templateSeriesEditor, data); + var htmls = Mustache.render(this.templateSeriesEditor, data); this.el.find('.editor-series-group').append(htmls); return this; }, diff --git a/src/view-grid.js b/src/view-grid.js index ab8a2f39..fc9400b9 100644 --- a/src/view-grid.js +++ b/src/view-grid.js @@ -53,7 +53,7 @@ my.Grid = Backbone.View.extend({ {{#columns}} \
  • Show column: {{.}}
  • \ {{/columns}}'; - var tmp = $.mustache(tmpl, {'columns': this.state.get('hiddenFields')}); + var tmp = Mustache.render(tmpl, {'columns': this.state.get('hiddenFields')}); this.el.find('.root-header-menu .dropdown-menu').html(tmp); }, @@ -211,7 +211,7 @@ my.Grid = Backbone.View.extend({ field.set({width: width}); } }); - var htmls = $.mustache(this.template, this.toTemplateJSON()); + var htmls = Mustache.render(this.template, this.toTemplateJSON()); this.el.html(htmls); this.model.currentDocuments.forEach(function(doc) { var tr = $(''); @@ -308,7 +308,7 @@ my.GridRow = Backbone.View.extend({ render: function() { this.el.attr('data-id', this.model.id); - var html = $.mustache(this.template, this.toTemplateJSON()); + var html = Mustache.render(this.template, this.toTemplateJSON()); $(this.el).html(html); return this; }, @@ -336,7 +336,7 @@ my.GridRow = Backbone.View.extend({ $(e.target).addClass("hidden"); var cell = $(e.target).siblings('.data-table-cell-value'); cell.data("previousContents", cell.text()); - var templated = $.mustache(this.cellEditorTemplate, {value: cell.text()}); + var templated = Mustache.render(this.cellEditorTemplate, {value: cell.text()}); cell.html(templated); }, diff --git a/src/view-map.js b/src/view-map.js index 60be7bc4..412ab2c7 100644 --- a/src/view-map.js +++ b/src/view-map.js @@ -161,7 +161,7 @@ my.Map = Backbone.View.extend({ var self = this; - htmls = $.mustache(this.template, this.model.toTemplateJSON()); + htmls = Mustache.render(this.template, this.model.toTemplateJSON()); $(this.el).html(htmls); this.$map = this.el.find('.panel.map'); diff --git a/src/view-timeline.js b/src/view-timeline.js index 39962807..e3faca04 100644 --- a/src/view-timeline.js +++ b/src/view-timeline.js @@ -47,7 +47,7 @@ my.Timeline = Backbone.View.extend({ render: function() { var tmplData = {}; - var htmls = $.mustache(this.template, tmplData); + var htmls = Mustache.render(this.template, tmplData); this.el.html(htmls); }, diff --git a/src/view-transform-dialog.js b/src/view-transform-dialog.js index 6c69766b..e4bee9ae 100644 --- a/src/view-transform-dialog.js +++ b/src/view-transform-dialog.js @@ -76,7 +76,7 @@ my.ColumnTransform = Backbone.View.extend({ }, render: function() { - var htmls = $.mustache(this.template, + var htmls = Mustache.render(this.template, {name: this.state.currentColumn} ); this.el.html(htmls); @@ -163,7 +163,7 @@ my.ColumnTransform = Backbone.View.extend({ }); var previewData = costco.previewTransform(docs, editFunc, self.state.currentColumn); var $el = self.el.find('.expression-preview-container'); - var templated = $.mustache(self.editPreviewTemplate, {rows: previewData.slice(0,4)}); + var templated = Mustache.render(self.editPreviewTemplate, {rows: previewData.slice(0,4)}); $el.html(templated); } else { errors.text(editFunc.errorMessage); diff --git a/src/view.js b/src/view.js index 89b74edf..c49b6592 100644 --- a/src/view.js +++ b/src/view.js @@ -286,7 +286,7 @@ my.DataExplorer = Backbone.View.extend({ render: function() { var tmplData = this.model.toTemplateJSON(); tmplData.views = this.pageViews; - var template = $.mustache(this.template, tmplData); + var template = Mustache.render(this.template, tmplData); $(this.el).html(template); var $dataViewContainer = this.el.find('.data-view-container'); _.each(this.pageViews, function(view, pageName) { @@ -431,7 +431,7 @@ my.DataExplorer = Backbone.View.extend({ {{message}} \ '; } - var _templated = $($.mustache(_template, tmplData)); + var _templated = $(Mustache.render(_template, tmplData)); _templated = $(_templated).appendTo($('.recline-data-explorer .alert-messages')); if (!flash.persist) { setTimeout(function() { @@ -516,7 +516,7 @@ my.QueryEditor = Backbone.View.extend({ render: function() { var tmplData = this.model.toJSON(); tmplData.to = this.model.get('from') + this.model.get('size'); - var templated = $.mustache(this.template, tmplData); + var templated = Mustache.render(this.template, tmplData); this.el.html(templated); } }); @@ -584,7 +584,7 @@ my.FilterEditor = Backbone.View.extend({ value: filter.term[fieldId] }; }); - var out = $.mustache(this.template, tmplData); + var out = Mustache.render(this.template, tmplData); this.el.html(out); // are there actually any facets to show? if (this.model.get('filters').length > 0) { @@ -669,7 +669,7 @@ my.FacetViewer = Backbone.View.extend({ } return facet; }); - var templated = $.mustache(this.template, tmplData); + var templated = Mustache.render(this.template, tmplData); this.el.html(templated); // are there actually any facets to show? if (this.model.facets.length > 0) { diff --git a/test/index.html b/test/index.html index 04dd88a4..b5dac4c5 100644 --- a/test/index.html +++ b/test/index.html @@ -12,7 +12,7 @@ - + diff --git a/vendor/jquery.mustache.js b/vendor/jquery.mustache.js deleted file mode 100755 index 5aa67def..00000000 --- a/vendor/jquery.mustache.js +++ /dev/null @@ -1,346 +0,0 @@ -/* -Shameless port of a shameless port -@defunkt => @janl => @aq - -See http://github.com/defunkt/mustache for more info. -*/ - -;(function($) { - -/* - mustache.js — Logic-less templates in JavaScript - - See http://mustache.github.com/ for more info. -*/ - -var Mustache = function() { - 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; - } - } - - template = this.render_pragmas(template); - var html = this.render_section(template, context, partials); - if(in_recursion) { - return this.render_tags(html, context, partials, in_recursion); - } - - this.render_tags(html, context, partials, in_recursion); - }, - - /* - Sends parsed lines - */ - send: function(line) { - if(line != "") { - this.buffer.push(line); - } - }, - - /* - Looks for %PRAGMAS - */ - render_pragmas: function(template) { - // no pragmas - if(!this.includes("%", template)) { - return template; - } - - var that = this; - var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + - this.ctag); - 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 = this.trim(name); - if(!partials || partials[name] === undefined) { - throw({message: "unknown_partial '" + name + "'"}); - } - if(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)) { - return template; - } - - var that = this; - // CSW - Added "+?" so it finds the tighest bound, not the widest - var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag + - "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag + - "\\s*", "mg"); - - // for each {{#foo}}{{/foo}} section do... - return template.replace(regex, function(match, type, name, content) { - var value = that.find(name, context); - if(type == "^") { // inverted section - if(!value || that.is_array(value) && value.length === 0) { - // false or empty list, render it - return that.render(content, context, partials, true); - } else { - return ""; - } - } else if(type == "#") { // normal section - if(that.is_array(value)) { // Enumerable, Let's loop! - return 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! - return that.render(content, that.create_context(value), - partials, true); - } else if(typeof value === "function") { - // higher order section - return value.call(context, content, function(text) { - return that.render(text, context, partials, true); - }); - } else if(value) { // boolean section - return that.render(content, context, partials, true); - } else { - return ""; - } - } - }); - }, - - /* - 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 new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" + - that.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 - return that.find(name, context); - default: // escape the value - return that.escape(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 = this.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; - 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 ""; - }, - - // Utility methods - - /* includes tag */ - includes: function(needle, haystack) { - return haystack.indexOf(this.otag + needle) != -1; - }, - - /* - Does away with nasty characters - */ - escape: function(s) { - s = String(s === null ? "" : s); - return s.replace(/&(?!\w+;)|["<>\\]/g, function(s) { - switch(s) { - case "&": return "&"; - case "\\": return "\\\\"; - case '"': return '\"'; - case "<": return "<"; - case ">": return ">"; - default: return s; - } - }); - }, - - // 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"; - }, - - is_array: function(a) { - return Object.prototype.toString.call(a) === '[object Array]'; - }, - - /* - Gets rid of leading and trailing whitespace - */ - trim: function(s) { - return s.replace(/^\s*|\s*$/g, ""); - }, - - /* - 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; - } - } - }; - - return({ - name: "mustache.js", - version: "0.3.1-dev", - - /* - 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"); - } - }, - escape : function(text) { - return new Renderer().escape(text); - } - }); -}(); - - $.mustache = function(template, view, partials) { - return Mustache.to_html(template, view, partials); - }; - - $.mustache.escape = function(text) { - return Mustache.escape(text); - }; - -})(jQuery); diff --git a/vendor/mustache/0.5.0-dev/mustache.js b/vendor/mustache/0.5.0-dev/mustache.js new file mode 100644 index 00000000..641cebd5 --- /dev/null +++ b/vendor/mustache/0.5.0-dev/mustache.js @@ -0,0 +1,536 @@ +/*! + * mustache.js - Logic-less {{mustache}} templates with JavaScript + * http://github.com/janl/mustache.js + */ +var Mustache = (typeof module !== "undefined" && module.exports) || {}; + +(function (exports) { + + exports.name = "mustache.js"; + exports.version = "0.5.0-dev"; + exports.tags = ["{{", "}}"]; + exports.parse = parse; + exports.compile = compile; + exports.render = render; + exports.clearCache = clearCache; + + // This is here for backwards compatibility with 0.4.x. + exports.to_html = function (template, view, partials, send) { + var result = render(template, view, partials); + + if (typeof send === "function") { + send(result); + } else { + return result; + } + }; + + var _toString = Object.prototype.toString; + var _isArray = Array.isArray; + var _forEach = Array.prototype.forEach; + var _trim = String.prototype.trim; + + var isArray; + if (_isArray) { + isArray = _isArray; + } else { + isArray = function (obj) { + return _toString.call(obj) === "[object Array]"; + }; + } + + var forEach; + if (_forEach) { + forEach = function (obj, callback, scope) { + return _forEach.call(obj, callback, scope); + }; + } else { + forEach = function (obj, callback, scope) { + for (var i = 0, len = obj.length; i < len; ++i) { + callback.call(scope, obj[i], i, obj); + } + }; + } + + var spaceRe = /^\s*$/; + + function isWhitespace(string) { + return spaceRe.test(string); + } + + var trim; + if (_trim) { + trim = function (string) { + return string == null ? "" : _trim.call(string); + }; + } else { + var trimLeft, trimRight; + + if (isWhitespace("\xA0")) { + trimLeft = /^\s+/; + trimRight = /\s+$/; + } else { + // IE doesn't match non-breaking spaces with \s, thanks jQuery. + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; + } + + trim = function (string) { + return string == null ? "" : + String(string).replace(trimLeft, "").replace(trimRight, ""); + }; + } + + var escapeMap = { + "&": "&", + "<": "<", + ">": ">", + '"': '"', + "'": ''' + }; + + function escapeHTML(string) { + return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) { + return escapeMap[s] || s; + }); + } + + /** + * Adds the `template`, `line`, and `file` properties to the given error + * object and alters the message to provide more useful debugging information. + */ + function debug(e, template, line, file) { + file = file || "