From de4a9ff29166fefee2dd74e46a0313e6d7f866dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20G=C3=B3mez?= Date: Fri, 22 Nov 2013 02:22:41 +0000 Subject: [PATCH] Advanced a lot with "generic model editing" --- server/src/uds/REST/methods/transports.py | 12 +- server/src/uds/REST/mixins.py | 7 +- server/src/uds/static/adm/css/uds-admin.css | 11 +- server/src/uds/static/adm/js/api-templates.js | 45 +- server/src/uds/static/adm/js/gui-elements.js | 26 +- server/src/uds/static/adm/js/gui-fields.js | 34 +- server/src/uds/static/adm/js/gui.js | 30 + .../uds/static/adm/js/handlebars-v1.1.2.js | 2595 +++++++++++++++++ server/src/uds/templates/uds/admin/index.html | 28 +- .../uds/admin/tmpl/authenticators.html | 12 +- .../uds/admin/tmpl/connectivity.html | 11 +- .../uds/admin/tmpl/fld/checkbox.html | 9 + .../templates/uds/admin/tmpl/fld/choice.html | 11 + .../uds/admin/tmpl/fld/editlist.html | 5 + .../uds/admin/tmpl/fld/form-group.html | 9 + .../templates/uds/admin/tmpl/fld/hidden.html | 3 + .../uds/admin/tmpl/fld/multichoice.html | 5 + .../templates/uds/admin/tmpl/fld/numeric.html | 13 +- .../uds/admin/tmpl/fld/password.html | 2 + .../templates/uds/admin/tmpl/fld/text.html | 13 +- .../templates/uds/admin/tmpl/fld/textbox.html | 2 + .../uds/templates/uds/admin/tmpl/modal.html | 23 +- .../templates/uds/admin/tmpl/spreadsheet.html | 10 +- .../uds/templates/uds/admin/tmpl/table.html | 12 +- 24 files changed, 2837 insertions(+), 91 deletions(-) create mode 100644 server/src/uds/static/adm/js/handlebars-v1.1.2.js create mode 100644 server/src/uds/templates/uds/admin/tmpl/fld/form-group.html diff --git a/server/src/uds/REST/methods/transports.py b/server/src/uds/REST/methods/transports.py index 4db113f7e..4c61e008b 100644 --- a/server/src/uds/REST/methods/transports.py +++ b/server/src/uds/REST/methods/transports.py @@ -36,7 +36,7 @@ from django.utils.translation import ugettext_lazy as _ from uds.models import Transport from uds.core.transports import factory -from uds.REST import Handler, HandlerError +from uds.REST import Handler, NotFound from uds.REST.mixins import ModelHandlerMixin, ModelTypeHandlerMixin, ModelTableHandlerMixin import logging @@ -52,10 +52,11 @@ class Transports(ModelHandlerMixin, Handler): type_ = item.getType() return { 'id': item.id, 'name': item.name, + 'comments': item.comments, 'priority': item.priority, + 'nets_positive': item.nets_positive, 'deployed_count': item.deployedServices.count(), 'type': type_.type(), - 'comments': item.comments } class Types(ModelTypeHandlerMixin, Handler): @@ -63,6 +64,13 @@ class Types(ModelTypeHandlerMixin, Handler): def enum_types(self): return factory().providers().values() + + def getGui(self, type_): + try: + return factory().lookup(type_).guiDescription() + except: + raise NotFound('type not found') + class TableInfo(ModelTableHandlerMixin, Handler): path = 'transports' diff --git a/server/src/uds/REST/mixins.py b/server/src/uds/REST/mixins.py index 5b5092a76..ee5d15f2a 100644 --- a/server/src/uds/REST/mixins.py +++ b/server/src/uds/REST/mixins.py @@ -98,7 +98,12 @@ class ModelHandlerMixin(object): return self.processDetail() try: - return list(self.getItems(pk=self._args[0]))[0] + val = self.model.objects.get(pk=self._args[0]) + res = self.item_as_dict(val) + if hasattr(val, 'getInstance'): + for key, value in val.getInstance().valuesDict().iteritems(): + res[key] = value + return res except: raise NotFound('item not found') diff --git a/server/src/uds/static/adm/css/uds-admin.css b/server/src/uds/static/adm/css/uds-admin.css index 32af4fd0b..dec175f50 100644 --- a/server/src/uds/static/adm/css/uds-admin.css +++ b/server/src/uds/static/adm/css/uds-admin.css @@ -20,7 +20,6 @@ body { padding: 5px 15px; } - /* Custom */ .btn3d-tables { margin-top:0px; @@ -37,8 +36,8 @@ body { } /* collapsable && closeable pannels */ -.chevron:before { - content: "\f139"; +.chevron:before { + content: "\f139"; } .chevron.collapsed:before { content: "\f13a"; @@ -53,6 +52,12 @@ body { margin-bottom: 0.3em; } +.modal-dialog { + /* new custom width */ + width: 60%; + +} + /* Edit Below to Customize Widths > 768px */ @media (min-width:768px) { diff --git a/server/src/uds/static/adm/js/api-templates.js b/server/src/uds/static/adm/js/api-templates.js index 207391726..1b069f079 100644 --- a/server/src/uds/static/adm/js/api-templates.js +++ b/server/src/uds/static/adm/js/api-templates.js @@ -1,11 +1,26 @@ +/* jshint strict: true */ // ------------------------------- // Templates related // Inserted into api // for the admin app // ------------------------------- (function(api, $) { - api.templates = {}; + "use strict"; + // Registers Handlebar useful helpers + // Equal comparision (like if helper, but with comparation) + Handlebars.registerHelper('ifequals', function(context1, context2, options) { + console.log('Comparing ', context1, ' with ', context2); + if(context1 == context2) { + return options.fn(this); + } else { + return options.inverse(this); + } + }); + + + api.templates = {}; + // Now initialize templates api api.templates.cache = new api.cache('tmpls'); // Will cache templates locally. If name contains // '?', data will not be cached and always // re-requested. We do not care about lang, because page will reload on language change @@ -28,7 +43,7 @@ url : api.template_url + name, type : "GET", dataType : "text", - success : function(data) { + success : function(data) { var cachedId = 'tmpl_' + name; $this.cache.put('_' + cachedId, $this.evaluate(data)); $this.cache.put(name, cachedId); @@ -44,9 +59,8 @@ }); }; - // Simple JavaScript Templating - // Based on John Resig - http://ejohn.org/ - MIT Licensed - api.templates.evaluate = function (str, data) { + // Simple JavaScript Templating, using HandleBars + api.templates.evaluate = function (str, context) { // Figure out if we're getting a template, or if we need to // load the template - and be sure to cache the result. var cached; @@ -55,24 +69,9 @@ if( cached === undefined ) { cached = api.templates.evaluate(document.getElementById(str).innerHTML); this.cache.put('_'+str, cached); - } - + } } - // If cached, get cached first - var fn = cached || - // Generate a reusable function that will serve as a template - // generator (and which will be cached). - new Function("obj", "var p=[],print=function(){p.push.apply(p,arguments);};" + - - // Introduce the data as local variables using with(){} - "with(obj){p.push('" + - - // Convert the template into pure JavaScript - str.replace(/[\r\t\n]/g, " ").split("<%").join("\t").replace(/((^|%>)[^\t]*)'/g, "$1\r").replace( - /\t=(.*?)%>/g, "',$1,'").split("\t").join("');").split("%>").join("p.push('").split("\r").join( - "\\'") + "');}return p.join('');"); - - // Provide some basic currying to the user - return data ? fn(data) : fn; + var template = cached || Handlebars.compile(str); + return context ? template(context) : template; }; }(window.api = window.api || {}, jQuery)); diff --git a/server/src/uds/static/adm/js/gui-elements.js b/server/src/uds/static/adm/js/gui-elements.js index a93c77448..35b6c0015 100644 --- a/server/src/uds/static/adm/js/gui-elements.js +++ b/server/src/uds/static/adm/js/gui-elements.js @@ -33,7 +33,7 @@ gui.providers.link = function(event) { gui.appendToWorkspace(gui.breadcrumbs(gettext('Service Providers'))); var tableId = gui.providers.table({ - rowSelect : 'multi', + rowSelect : 'single', onEdit: function(value, event, table) { gui.providers.rest.gui(value.type, { success: function(data){ @@ -105,12 +105,7 @@ gui.authenticators.link = function(event) { gui.authenticators.rest.gui(value.type, { success: function(data){ var form = gui.fields(data); - gui.appendToWorkspace(gui.modal('edit_modal', gettext('Edit authenticator'), form)); - $('#edit_modal').modal() - .on('hidden.bs.modal', function () { - $('#edit_modal').remove(); - }) - ; + gui.launchModal(gettext('Edit authenticator')+' '+value.name, form); }, }); }, @@ -152,6 +147,23 @@ gui.connectivity.link = function(event) { rowSelect : 'multi', container : 'transports-placeholder', buttons : [ 'edit', 'delete', 'xls' ], + onEdit: function(value, event, table) { + gui.connectivity.transports.rest.gui(value.type, { + success: function(itemGui){ + gui.connectivity.transports.rest.get({ + id:value.id, + success: function(item) { + var form = gui.fields(itemGui, item); + gui.launchModal(gettext('Edit transport')+' '+value.name,form, function(form_selector) { + var fields = gui.fields.read(form_selector); + return false; + }); + }, + }); + }, + }); + }, + }); gui.connectivity.networks.table({ rowSelect : 'multi', diff --git a/server/src/uds/static/adm/js/gui-fields.js b/server/src/uds/static/adm/js/gui-fields.js index a547e252b..d685b89e2 100644 --- a/server/src/uds/static/adm/js/gui-fields.js +++ b/server/src/uds/static/adm/js/gui-fields.js @@ -3,15 +3,17 @@ "use strict"; // Returns a form that will manage a gui description (new or edit) - gui.fields = function(item_description) { - var form = '
'; - // item_description is expected to have fields sorted by .gui.order (REST api returns them sorted) - $.each(item_description, function(index, f){ - + gui.fields = function(itemGui, item) { + var editing = item !== undefined; // Locate real Editing + item = item || {id:''}; + var form = '' + + ''; + // itemGui is expected to have fields sorted by .gui.order (REST api returns them sorted) + $.each(itemGui, function(index, f){ gui.doLog(f); - var editing = false; // Locate real Editing + gui.doLog(item[f.name]); form += api.templates.evaluate('tmpl_fld_'+f.gui.type, { - value: f.value || f.gui.value || f.gui.defvalue, // If no value present, use default value + value: item[f.name] || f.gui.value || f.gui.defvalue, // If no value present, use default value values: f.gui.values, label: f.gui.label, length: f.gui.length, @@ -21,11 +23,29 @@ tooltip: f.gui.tooltip, type: f.gui.type, name: f.name, + css: 'modal_field_data', }); }); form += '
'; return form; }; + + // Reads fields from a form + gui.fields.read = function(formSelector) { + var res = {}; + $(formSelector + ' .modal_field_data').each(function(i, field) { + var $field = $(field); + if( $field.attr('name') ) { // Is a valid field + if( $field.attr('type') == 'checkbox') { + res[$field.attr('name')] = $field.is(':checked'); + } else { + res[$field.attr('name')] = $field.val(); + } + } + }); + gui.doLog(res); + return res; + }; }(window.gui = window.gui || {}, jQuery)); diff --git a/server/src/uds/static/adm/js/gui.js b/server/src/uds/static/adm/js/gui.js index bbf68ae4f..6c7052897 100644 --- a/server/src/uds/static/adm/js/gui.js +++ b/server/src/uds/static/adm/js/gui.js @@ -105,6 +105,36 @@ }); }; + gui.launchModal = function(title, content, onSuccess) { + var id = Math.random().toString().split('.')[1]; + gui.appendToWorkspace(gui.modal(id, title, content)); + id = '#' + id; // for jQuery + // For "beauty" switches, initialize them now + $(id + ' .make-switch').bootstrapSwitch(); + // Activate "cool" selects + $(id + ' .selectpicker').selectpicker(); + // TEST: cooller on mobile devices + if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) { + $(id + ' .selectpicker').selectpicker('mobile'); + } + // Activate tooltips + $(id + ' [data-toggle="tooltip"]').tooltip({delay: 500, placement: 'auto right'}); + // And catch "accept" (default is "Save" in fact) button click + $(id + ' .button-accept').click(function(){ + if( onSuccess ) { + if( onSuccess(id + ' form') === false ) // Some error may have ocurred, do not close dialog + return; + } + $(id).modal('hide'); + }); + + // Launch modal + $(id).modal() + .on('hidden.bs.modal', function () { + $(id).remove(); + }); + }; + gui.clearWorkspace = function() { $('#content').empty(); $('#minimized').empty(); diff --git a/server/src/uds/static/adm/js/handlebars-v1.1.2.js b/server/src/uds/static/adm/js/handlebars-v1.1.2.js new file mode 100644 index 000000000..ba717929a --- /dev/null +++ b/server/src/uds/static/adm/js/handlebars-v1.1.2.js @@ -0,0 +1,2595 @@ +/*! + + handlebars v1.1.2 + +Copyright (C) 2011 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +@license +*/ +var Handlebars = (function() { +// handlebars/safe-string.js +var __module4__ = (function() { + "use strict"; + var __exports__; + // Build out our basic SafeString type + function SafeString(string) { + this.string = string; + } + + SafeString.prototype.toString = function() { + return "" + this.string; + }; + + __exports__ = SafeString; + return __exports__; +})(); + +// handlebars/utils.js +var __module3__ = (function(__dependency1__) { + "use strict"; + var __exports__ = {}; + var SafeString = __dependency1__; + + var escape = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + + var badChars = /[&<>"'`]/g; + var possible = /[&<>"'`]/; + + function escapeChar(chr) { + return escape[chr] || "&"; + } + + function extend(obj, value) { + for(var key in value) { + if(value.hasOwnProperty(key)) { + obj[key] = value[key]; + } + } + } + + __exports__.extend = extend;var toString = Object.prototype.toString; + __exports__.toString = toString; + // Sourced from lodash + // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt + var isFunction = function(value) { + return typeof value === 'function'; + }; + // fallback for older versions of Chrome and Safari + if (isFunction(/x/)) { + isFunction = function(value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; + }; + } + var isFunction; + __exports__.isFunction = isFunction; + var isArray = Array.isArray || function(value) { + return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false; + }; + __exports__.isArray = isArray; + + function escapeExpression(string) { + // don't escape SafeStrings, since they're already safe + if (string instanceof SafeString) { + return string.toString(); + } else if (!string && string !== 0) { + return ""; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = "" + string; + + if(!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); + } + + __exports__.escapeExpression = escapeExpression;function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { + return false; + } + } + + __exports__.isEmpty = isEmpty; + return __exports__; +})(__module4__); + +// handlebars/exception.js +var __module5__ = (function() { + "use strict"; + var __exports__; + + var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + + function Exception(/* message */) { + var tmp = Error.prototype.constructor.apply(this, arguments); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (var idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } + } + + Exception.prototype = new Error(); + + __exports__ = Exception; + return __exports__; +})(); + +// handlebars/base.js +var __module2__ = (function(__dependency1__, __dependency2__) { + "use strict"; + var __exports__ = {}; + /*globals Exception, Utils */ + var Utils = __dependency1__; + var Exception = __dependency2__; + + var VERSION = "1.1.2"; + __exports__.VERSION = VERSION;var COMPILER_REVISION = 4; + __exports__.COMPILER_REVISION = COMPILER_REVISION; + var REVISION_CHANGES = { + 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it + 2: '== 1.0.0-rc.3', + 3: '== 1.0.0-rc.4', + 4: '>= 1.0.0' + }; + __exports__.REVISION_CHANGES = REVISION_CHANGES; + var isArray = Utils.isArray, + isFunction = Utils.isFunction, + toString = Utils.toString, + objectType = '[object Object]'; + + function HandlebarsEnvironment(helpers, partials) { + this.helpers = helpers || {}; + this.partials = partials || {}; + + registerDefaultHelpers(this); + } + + __exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = { + constructor: HandlebarsEnvironment, + + logger: logger, + log: log, + + registerHelper: function(name, fn, inverse) { + if (toString.call(name) === objectType) { + if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); } + Utils.extend(this.helpers, name); + } else { + if (inverse) { fn.not = inverse; } + this.helpers[name] = fn; + } + }, + + registerPartial: function(name, str) { + if (toString.call(name) === objectType) { + Utils.extend(this.partials, name); + } else { + this.partials[name] = str; + } + } + }; + + function registerDefaultHelpers(instance) { + instance.registerHelper('helperMissing', function(arg) { + if(arguments.length === 2) { + return undefined; + } else { + throw new Error("Missing helper: '" + arg + "'"); + } + }); + + instance.registerHelper('blockHelperMissing', function(context, options) { + var inverse = options.inverse || function() {}, fn = options.fn; + + if (isFunction(context)) { context = context.call(this); } + + if(context === true) { + return fn(this); + } else if(context === false || context == null) { + return inverse(this); + } else if (isArray(context)) { + if(context.length > 0) { + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + return fn(context); + } + }); + + instance.registerHelper('each', function(context, options) { + var fn = options.fn, inverse = options.inverse; + var i = 0, ret = "", data; + + if (isFunction(context)) { context = context.call(this); } + + if (options.data) { + data = createFrame(options.data); + } + + if(context && typeof context === 'object') { + if (isArray(context)) { + for(var j = context.length; i 0) { throw new Exception("Invalid path: " + original); } + else if (part === "..") { depth++; } + else { this.isScoped = true; } + } + else { dig.push(part); } + } + + this.original = original; + this.parts = dig; + this.string = dig.join('.'); + this.depth = depth; + + // an ID is simple if it only has one part, and that part is not + // `..` or `this`. + this.isSimple = parts.length === 1 && !this.isScoped && depth === 0; + + this.stringModeValue = this.string; + } + + __exports__.IdNode = IdNode;function PartialNameNode(name) { + this.type = "PARTIAL_NAME"; + this.name = name.original; + } + + __exports__.PartialNameNode = PartialNameNode;function DataNode(id) { + this.type = "DATA"; + this.id = id; + } + + __exports__.DataNode = DataNode;function StringNode(string) { + this.type = "STRING"; + this.original = + this.string = + this.stringModeValue = string; + } + + __exports__.StringNode = StringNode;function IntegerNode(integer) { + this.type = "INTEGER"; + this.original = + this.integer = integer; + this.stringModeValue = Number(integer); + } + + __exports__.IntegerNode = IntegerNode;function BooleanNode(bool) { + this.type = "BOOLEAN"; + this.bool = bool; + this.stringModeValue = bool === "true"; + } + + __exports__.BooleanNode = BooleanNode;function CommentNode(comment) { + this.type = "comment"; + this.comment = comment; + } + + __exports__.CommentNode = CommentNode; + return __exports__; +})(__module5__); + +// handlebars/compiler/parser.js +var __module9__ = (function() { + "use strict"; + var __exports__; + /* Jison generated parser */ + var handlebars = (function(){ + var parser = {trace: function trace() { }, + yy: {}, + symbols_: {"error":2,"root":3,"statements":4,"EOF":5,"program":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"inMustache":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"CLOSE_UNESCAPED":24,"OPEN_PARTIAL":25,"partialName":26,"partial_option0":27,"inMustache_repetition0":28,"inMustache_option0":29,"dataName":30,"param":31,"STRING":32,"INTEGER":33,"BOOLEAN":34,"hash":35,"hash_repetition_plus0":36,"hashSegment":37,"ID":38,"EQUALS":39,"DATA":40,"pathSegments":41,"SEP":42,"$accept":0,"$end":1}, + terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"CLOSE_UNESCAPED",25:"OPEN_PARTIAL",32:"STRING",33:"INTEGER",34:"BOOLEAN",38:"ID",39:"EQUALS",40:"DATA",42:"SEP"}, + productions_: [0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,4],[7,2],[17,3],[17,1],[31,1],[31,1],[31,1],[31,1],[31,1],[35,1],[37,3],[26,1],[26,1],[26,1],[30,2],[21,1],[41,3],[41,1],[27,0],[27,1],[28,0],[28,2],[29,0],[29,1],[36,1],[36,2]], + performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + + var $0 = $$.length - 1; + switch (yystate) { + case 1: return new yy.ProgramNode($$[$0-1]); + break; + case 2: return new yy.ProgramNode([]); + break; + case 3:this.$ = new yy.ProgramNode([], $$[$0-1], $$[$0]); + break; + case 4:this.$ = new yy.ProgramNode($$[$0-2], $$[$0-1], $$[$0]); + break; + case 5:this.$ = new yy.ProgramNode($$[$0-1], $$[$0], []); + break; + case 6:this.$ = new yy.ProgramNode($$[$0]); + break; + case 7:this.$ = new yy.ProgramNode([]); + break; + case 8:this.$ = new yy.ProgramNode([]); + break; + case 9:this.$ = [$$[$0]]; + break; + case 10: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; + break; + case 11:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0]); + break; + case 12:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0]); + break; + case 13:this.$ = $$[$0]; + break; + case 14:this.$ = $$[$0]; + break; + case 15:this.$ = new yy.ContentNode($$[$0]); + break; + case 16:this.$ = new yy.CommentNode($$[$0]); + break; + case 17:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0])); + break; + case 18:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0])); + break; + case 19:this.$ = {path: $$[$0-1], strip: stripFlags($$[$0-2], $$[$0])}; + break; + case 20:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0])); + break; + case 21:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0])); + break; + case 22:this.$ = new yy.PartialNode($$[$0-2], $$[$0-1], stripFlags($$[$0-3], $$[$0])); + break; + case 23:this.$ = stripFlags($$[$0-1], $$[$0]); + break; + case 24:this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]]; + break; + case 25:this.$ = [[$$[$0]], null]; + break; + case 26:this.$ = $$[$0]; + break; + case 27:this.$ = new yy.StringNode($$[$0]); + break; + case 28:this.$ = new yy.IntegerNode($$[$0]); + break; + case 29:this.$ = new yy.BooleanNode($$[$0]); + break; + case 30:this.$ = $$[$0]; + break; + case 31:this.$ = new yy.HashNode($$[$0]); + break; + case 32:this.$ = [$$[$0-2], $$[$0]]; + break; + case 33:this.$ = new yy.PartialNameNode($$[$0]); + break; + case 34:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0])); + break; + case 35:this.$ = new yy.PartialNameNode(new yy.IntegerNode($$[$0])); + break; + case 36:this.$ = new yy.DataNode($$[$0]); + break; + case 37:this.$ = new yy.IdNode($$[$0]); + break; + case 38: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2]; + break; + case 39:this.$ = [{part: $$[$0]}]; + break; + case 42:this.$ = []; + break; + case 43:$$[$0-1].push($$[$0]); + break; + case 46:this.$ = [$$[$0]]; + break; + case 47:$$[$0-1].push($$[$0]); + break; + } + }, + table: [{3:1,4:2,5:[1,3],8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[3]},{5:[1,16],8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[2,2]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{4:20,6:18,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{4:20,6:22,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],25:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],25:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],25:[2,15]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],25:[2,16]},{17:23,21:24,30:25,38:[1,28],40:[1,27],41:26},{17:29,21:24,30:25,38:[1,28],40:[1,27],41:26},{17:30,21:24,30:25,38:[1,28],40:[1,27],41:26},{17:31,21:24,30:25,38:[1,28],40:[1,27],41:26},{21:33,26:32,32:[1,34],33:[1,35],38:[1,28],41:26},{1:[2,1]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],25:[2,10]},{10:36,20:[1,37]},{4:38,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,7],22:[1,13],23:[1,14],25:[1,15]},{7:39,8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,6],22:[1,13],23:[1,14],25:[1,15]},{17:23,18:[1,40],21:24,30:25,38:[1,28],40:[1,27],41:26},{10:41,20:[1,37]},{18:[1,42]},{18:[2,42],24:[2,42],28:43,32:[2,42],33:[2,42],34:[2,42],38:[2,42],40:[2,42]},{18:[2,25],24:[2,25]},{18:[2,37],24:[2,37],32:[2,37],33:[2,37],34:[2,37],38:[2,37],40:[2,37],42:[1,44]},{21:45,38:[1,28],41:26},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],38:[2,39],40:[2,39],42:[2,39]},{18:[1,46]},{18:[1,47]},{24:[1,48]},{18:[2,40],21:50,27:49,38:[1,28],41:26},{18:[2,33],38:[2,33]},{18:[2,34],38:[2,34]},{18:[2,35],38:[2,35]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],25:[2,11]},{21:51,38:[1,28],41:26},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,3],22:[1,13],23:[1,14],25:[1,15]},{4:52,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,5],22:[1,13],23:[1,14],25:[1,15]},{14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],25:[2,23]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],25:[2,12]},{14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],25:[2,18]},{18:[2,44],21:56,24:[2,44],29:53,30:60,31:54,32:[1,57],33:[1,58],34:[1,59],35:55,36:61,37:62,38:[1,63],40:[1,27],41:26},{38:[1,64]},{18:[2,36],24:[2,36],32:[2,36],33:[2,36],34:[2,36],38:[2,36],40:[2,36]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],25:[2,17]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],25:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],25:[2,21]},{18:[1,65]},{18:[2,41]},{18:[1,66]},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],25:[1,15]},{18:[2,24],24:[2,24]},{18:[2,43],24:[2,43],32:[2,43],33:[2,43],34:[2,43],38:[2,43],40:[2,43]},{18:[2,45],24:[2,45]},{18:[2,26],24:[2,26],32:[2,26],33:[2,26],34:[2,26],38:[2,26],40:[2,26]},{18:[2,27],24:[2,27],32:[2,27],33:[2,27],34:[2,27],38:[2,27],40:[2,27]},{18:[2,28],24:[2,28],32:[2,28],33:[2,28],34:[2,28],38:[2,28],40:[2,28]},{18:[2,29],24:[2,29],32:[2,29],33:[2,29],34:[2,29],38:[2,29],40:[2,29]},{18:[2,30],24:[2,30],32:[2,30],33:[2,30],34:[2,30],38:[2,30],40:[2,30]},{18:[2,31],24:[2,31],37:67,38:[1,68]},{18:[2,46],24:[2,46],38:[2,46]},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],38:[2,39],39:[1,69],40:[2,39],42:[2,39]},{18:[2,38],24:[2,38],32:[2,38],33:[2,38],34:[2,38],38:[2,38],40:[2,38],42:[2,38]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],25:[2,22]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],25:[2,19]},{18:[2,47],24:[2,47],38:[2,47]},{39:[1,69]},{21:56,30:60,31:70,32:[1,57],33:[1,58],34:[1,59],38:[1,28],40:[1,27],41:26},{18:[2,32],24:[2,32],38:[2,32]}], + defaultActions: {3:[2,2],16:[2,1],50:[2,41]}, + parseError: function parseError(str, hash) { + throw new Error(str); + }, + parse: function parse(input) { + var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + this.yy.parser = this; + if (typeof this.lexer.yylloc == "undefined") + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + var ranges = this.lexer.options && this.lexer.options.ranges; + if (typeof this.yy.parseError === "function") + this.parseError = this.yy.parseError; + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + function lex() { + var token; + token = self.lexer.lex() || 1; + if (typeof token !== "number") { + token = self.symbols_[token] || token; + } + return token; + } + var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == "undefined") { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === "undefined" || !action.length || !action[0]) { + var errStr = ""; + if (!recovering) { + expected = []; + for (p in table[state]) + if (this.terminals_[p] && p > 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column}; + if (ranges) { + yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; + } + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; + } + }; + + + function stripFlags(open, close) { + return { + left: open[2] === '~', + right: close[0] === '~' || close[1] === '~' + }; + } + + /* Jison generated lexer */ + var lexer = (function(){ + var lexer = ({EOF:1, + parseError:function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, + setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + if (this.options.ranges) this.yylloc.range = [0,0]; + this.offset = 0; + return this; + }, + input:function () { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) this.yylloc.range[1]++; + + this._input = this._input.slice(1); + return ch; + }, + unput:function (ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length-len-1); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length-1); + this.matched = this.matched.substr(0, this.matched.length-1); + + if (lines.length-1) this.yylineno -= lines.length-1; + var r = this.yylloc.range; + + this.yylloc = {first_line: this.yylloc.first_line, + last_line: this.yylineno+1, + first_column: this.yylloc.first_column, + last_column: lines ? + (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length: + this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + return this; + }, + more:function () { + this._more = true; + return this; + }, + less:function (n) { + this.unput(this.match.slice(n)); + }, + pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, + upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, + showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, + next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + tempMatch, + index, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length}; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); + if (this.done && this._input) this.done = false; + if (token) return token; + else return; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, + lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, + begin:function begin(condition) { + this.conditionStack.push(condition); + }, + popState:function popState() { + return this.conditionStack.pop(); + }, + _currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, + topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, + pushState:function begin(condition) { + this.begin(condition); + }}); + lexer.options = {}; + lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + + + function strip(start, end) { + return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng-end); + } + + + var YYSTATE=YY_START + switch($avoiding_name_collisions) { + case 0: + if(yy_.yytext.slice(-2) === "\\\\") { + strip(0,1); + this.begin("mu"); + } else if(yy_.yytext.slice(-1) === "\\") { + strip(0,1); + this.begin("emu"); + } else { + this.begin("mu"); + } + if(yy_.yytext) return 14; + + break; + case 1:return 14; + break; + case 2: + if(yy_.yytext.slice(-1) !== "\\") this.popState(); + if(yy_.yytext.slice(-1) === "\\") strip(0,1); + return 14; + + break; + case 3:strip(0,4); this.popState(); return 15; + break; + case 4:return 25; + break; + case 5:return 16; + break; + case 6:return 20; + break; + case 7:return 19; + break; + case 8:return 19; + break; + case 9:return 23; + break; + case 10:return 22; + break; + case 11:this.popState(); this.begin('com'); + break; + case 12:strip(3,5); this.popState(); return 15; + break; + case 13:return 22; + break; + case 14:return 39; + break; + case 15:return 38; + break; + case 16:return 38; + break; + case 17:return 42; + break; + case 18:/*ignore whitespace*/ + break; + case 19:this.popState(); return 24; + break; + case 20:this.popState(); return 18; + break; + case 21:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 32; + break; + case 22:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 32; + break; + case 23:return 40; + break; + case 24:return 34; + break; + case 25:return 34; + break; + case 26:return 33; + break; + case 27:return 38; + break; + case 28:yy_.yytext = strip(1,2); return 38; + break; + case 29:return 'INVALID'; + break; + case 30:return 5; + break; + } + }; + lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s])))/,/^(?:false(?=([~}\s])))/,/^(?:-?[0-9]+(?=([~}\s])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/]; + lexer.conditions = {"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"INITIAL":{"rules":[0,1,30],"inclusive":true}}; + return lexer;})() + parser.lexer = lexer; + function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser; + return new Parser; + })();__exports__ = handlebars; + return __exports__; +})(); + +// handlebars/compiler/base.js +var __module8__ = (function(__dependency1__, __dependency2__) { + "use strict"; + var __exports__ = {}; + var parser = __dependency1__; + var AST = __dependency2__; + + __exports__.parser = parser; + + function parse(input) { + // Just return if an already-compile AST was passed in. + if(input.constructor === AST.ProgramNode) { return input; } + + parser.yy = AST; + return parser.parse(input); + } + + __exports__.parse = parse; + return __exports__; +})(__module9__, __module7__); + +// handlebars/compiler/javascript-compiler.js +var __module11__ = (function(__dependency1__) { + "use strict"; + var __exports__; + var COMPILER_REVISION = __dependency1__.COMPILER_REVISION; + var REVISION_CHANGES = __dependency1__.REVISION_CHANGES; + var log = __dependency1__.log; + + function Literal(value) { + this.value = value; + } + + function JavaScriptCompiler() {} + + JavaScriptCompiler.prototype = { + // PUBLIC API: You can override these methods in a subclass to provide + // alternative compiled forms for name lookup and buffering semantics + nameLookup: function(parent, name /* , type*/) { + var wrap, + ret; + if (parent.indexOf('depth') === 0) { + wrap = true; + } + + if (/^[0-9]+$/.test(name)) { + ret = parent + "[" + name + "]"; + } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { + ret = parent + "." + name; + } + else { + ret = parent + "['" + name + "']"; + } + + if (wrap) { + return '(' + parent + ' && ' + ret + ')'; + } else { + return ret; + } + }, + + appendToBuffer: function(string) { + if (this.environment.isSimple) { + return "return " + string + ";"; + } else { + return { + appendToBuffer: true, + content: string, + toString: function() { return "buffer += " + string + ";"; } + }; + } + }, + + initializeBuffer: function() { + return this.quotedString(""); + }, + + namespace: "Handlebars", + // END PUBLIC API + + compile: function(environment, options, context, asObject) { + this.environment = environment; + this.options = options || {}; + + log('debug', this.environment.disassemble() + "\n\n"); + + this.name = this.environment.name; + this.isChild = !!context; + this.context = context || { + programs: [], + environments: [], + aliases: { } + }; + + this.preamble(); + + this.stackSlot = 0; + this.stackVars = []; + this.registers = { list: [] }; + this.compileStack = []; + this.inlineStack = []; + + this.compileChildren(environment, options); + + var opcodes = environment.opcodes, opcode; + + this.i = 0; + + for(var l=opcodes.length; this.i 0) { + this.source[1] = this.source[1] + ", " + locals.join(", "); + } + + // Generate minimizer alias mappings + if (!this.isChild) { + for (var alias in this.context.aliases) { + if (this.context.aliases.hasOwnProperty(alias)) { + this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias]; + } + } + } + + if (this.source[1]) { + this.source[1] = "var " + this.source[1].substring(2) + ";"; + } + + // Merge children + if (!this.isChild) { + this.source[1] += '\n' + this.context.programs.join('\n') + '\n'; + } + + if (!this.environment.isSimple) { + this.pushSource("return buffer;"); + } + + var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"]; + + for(var i=0, l=this.environment.depths.list.length; i this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } + return this.topStackName(); + }, + topStackName: function() { + return "stack" + this.stackSlot; + }, + flushInline: function() { + var inlineStack = this.inlineStack; + if (inlineStack.length) { + this.inlineStack = []; + for (var i = 0, len = inlineStack.length; i < len; i++) { + var entry = inlineStack[i]; + if (entry instanceof Literal) { + this.compileStack.push(entry); + } else { + this.pushStack(entry); + } + } + } + }, + isInline: function() { + return this.inlineStack.length; + }, + + popStack: function(wrapped) { + var inline = this.isInline(), + item = (inline ? this.inlineStack : this.compileStack).pop(); + + if (!wrapped && (item instanceof Literal)) { + return item.value; + } else { + if (!inline) { + this.stackSlot--; + } + return item; + } + }, + + topStack: function(wrapped) { + var stack = (this.isInline() ? this.inlineStack : this.compileStack), + item = stack[stack.length - 1]; + + if (!wrapped && (item instanceof Literal)) { + return item.value; + } else { + return item; + } + }, + + quotedString: function(str) { + return '"' + str + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 + .replace(/\u2029/g, '\\u2029') + '"'; + }, + + setupHelper: function(paramSize, name, missingParams) { + var params = []; + this.setupParams(paramSize, params, missingParams); + var foundHelper = this.nameLookup('helpers', name, 'helper'); + + return { + params: params, + name: foundHelper, + callParams: ["depth0"].concat(params).join(", "), + helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ") + }; + }, + + // the params and contexts arguments are passed in arrays + // to fill in + setupParams: function(paramSize, params, useRegister) { + var options = [], contexts = [], types = [], param, inverse, program; + + options.push("hash:" + this.popStack()); + + inverse = this.popStack(); + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + if (!program) { + this.context.aliases.self = "this"; + program = "self.noop"; + } + + if (!inverse) { + this.context.aliases.self = "this"; + inverse = "self.noop"; + } + + options.push("inverse:" + inverse); + options.push("fn:" + program); + } + + for(var i=0; i + @@ -33,29 +34,32 @@ {% block menu %}{% include 'uds/admin/snippets/navbar.html' %}{% endblock %} - -
-
- {% block body %}{% endblock %} -
-
-
-
-
+ +
+
+ {% block body %}{% endblock %}
- -
-
+
+
+
+
+ + + + + + + diff --git a/server/src/uds/templates/uds/admin/tmpl/authenticators.html b/server/src/uds/templates/uds/admin/tmpl/authenticators.html index 27a4ff66b..241531427 100644 --- a/server/src/uds/templates/uds/admin/tmpl/authenticators.html +++ b/server/src/uds/templates/uds/admin/tmpl/authenticators.html @@ -1,19 +1,21 @@ -{% load i18n html5 static %} +{% load i18n %}
-

{% trans 'Authenticators' %} {% trans 'administration of authenticators' %}

+

{% trans 'Authenticators' %}

+{% verbatim %}
-
+
-
+
-
+
+{% endverbatim %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/connectivity.html b/server/src/uds/templates/uds/admin/tmpl/connectivity.html index 372f330bb..378a9941a 100644 --- a/server/src/uds/templates/uds/admin/tmpl/connectivity.html +++ b/server/src/uds/templates/uds/admin/tmpl/connectivity.html @@ -1,4 +1,4 @@ -{% load i18n html5 static %} +{% load i18n %}

{% trans 'Connectivity' %} {% trans 'overview' %}

@@ -7,10 +7,11 @@
- +{% verbatim %}
-
+
-
+
-
\ No newline at end of file +
+{% endverbatim %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/checkbox.html b/server/src/uds/templates/uds/admin/tmpl/fld/checkbox.html index e69de29bb..55a24b9b9 100644 --- a/server/src/uds/templates/uds/admin/tmpl/fld/checkbox.html +++ b/server/src/uds/templates/uds/admin/tmpl/fld/checkbox.html @@ -0,0 +1,9 @@ +{% extends "uds/admin/tmpl/fld/form-group.html" %} +{% load i18n %} +{% block field %} +
+ {% verbatim %} + +
+{% endverbatim %} +{% endblock %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/choice.html b/server/src/uds/templates/uds/admin/tmpl/fld/choice.html index e69de29bb..660d105df 100644 --- a/server/src/uds/templates/uds/admin/tmpl/fld/choice.html +++ b/server/src/uds/templates/uds/admin/tmpl/fld/choice.html @@ -0,0 +1,11 @@ +{% extends "uds/admin/tmpl/fld/form-group.html" %} +{% load i18n %} +{% block field %} +{% verbatim %} + +{% endverbatim %} +{% endblock %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/editlist.html b/server/src/uds/templates/uds/admin/tmpl/fld/editlist.html index e69de29bb..302d4b3b9 100644 --- a/server/src/uds/templates/uds/admin/tmpl/fld/editlist.html +++ b/server/src/uds/templates/uds/admin/tmpl/fld/editlist.html @@ -0,0 +1,5 @@ +{% extends "uds/admin/tmpl/fld/form-group.html" %} +{% load i18n %} + +{% verbatim %} +{% endverbatim %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/form-group.html b/server/src/uds/templates/uds/admin/tmpl/fld/form-group.html new file mode 100644 index 000000000..6fe2407e4 --- /dev/null +++ b/server/src/uds/templates/uds/admin/tmpl/fld/form-group.html @@ -0,0 +1,9 @@ +{% load i18n %} +{% verbatim %} +
+ +
+ {% endverbatim %} + {% block field %}EMPTY!!!{% endblock %} +
+
\ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/hidden.html b/server/src/uds/templates/uds/admin/tmpl/fld/hidden.html index e69de29bb..f0a4608d3 100644 --- a/server/src/uds/templates/uds/admin/tmpl/fld/hidden.html +++ b/server/src/uds/templates/uds/admin/tmpl/fld/hidden.html @@ -0,0 +1,3 @@ +{% verbatim %} + +{% endverbatim %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/multichoice.html b/server/src/uds/templates/uds/admin/tmpl/fld/multichoice.html index e69de29bb..302d4b3b9 100644 --- a/server/src/uds/templates/uds/admin/tmpl/fld/multichoice.html +++ b/server/src/uds/templates/uds/admin/tmpl/fld/multichoice.html @@ -0,0 +1,5 @@ +{% extends "uds/admin/tmpl/fld/form-group.html" %} +{% load i18n %} + +{% verbatim %} +{% endverbatim %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/numeric.html b/server/src/uds/templates/uds/admin/tmpl/fld/numeric.html index da63fc21d..a73d3c89c 100644 --- a/server/src/uds/templates/uds/admin/tmpl/fld/numeric.html +++ b/server/src/uds/templates/uds/admin/tmpl/fld/numeric.html @@ -1,6 +1,7 @@ -
- -
- -
-
+{% extends "uds/admin/tmpl/fld/form-group.html" %} +{% load i18n %} +{% block field %} +{% verbatim %} + +{% endverbatim %} +{% endblock %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/password.html b/server/src/uds/templates/uds/admin/tmpl/fld/password.html index e69de29bb..09f4a91e1 100644 --- a/server/src/uds/templates/uds/admin/tmpl/fld/password.html +++ b/server/src/uds/templates/uds/admin/tmpl/fld/password.html @@ -0,0 +1,2 @@ +{% verbatim %} +{% endverbatim %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/text.html b/server/src/uds/templates/uds/admin/tmpl/fld/text.html index 7de9c981c..6b0956f30 100644 --- a/server/src/uds/templates/uds/admin/tmpl/fld/text.html +++ b/server/src/uds/templates/uds/admin/tmpl/fld/text.html @@ -1,6 +1,7 @@ -
- -
- -
-
+{% extends "uds/admin/tmpl/fld/form-group.html" %} +{% load i18n %} +{% block field %} +{% verbatim %} + +{% endverbatim %} +{% endblock %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/fld/textbox.html b/server/src/uds/templates/uds/admin/tmpl/fld/textbox.html index e69de29bb..09f4a91e1 100644 --- a/server/src/uds/templates/uds/admin/tmpl/fld/textbox.html +++ b/server/src/uds/templates/uds/admin/tmpl/fld/textbox.html @@ -0,0 +1,2 @@ +{% verbatim %} +{% endverbatim %} \ No newline at end of file diff --git a/server/src/uds/templates/uds/admin/tmpl/modal.html b/server/src/uds/templates/uds/admin/tmpl/modal.html index d370edb75..a7731fcf4 100644 --- a/server/src/uds/templates/uds/admin/tmpl/modal.html +++ b/server/src/uds/templates/uds/admin/tmpl/modal.html @@ -1,17 +1,30 @@ {% load i18n %} -