WIP: Thymoljs thymoljs
authorKai Moritz <kai@juplo.de>
Tue, 19 Jan 2016 17:39:50 +0000 (18:39 +0100)
committerKai Moritz <kai@juplo.de>
Tue, 19 Jan 2016 17:39:50 +0000 (18:39 +0100)
dist/js/thymol-full.js [new file with mode: 0644]
dist/js/thymol-lite.js [new file with mode: 0644]
dist/js/thymol-load.js [new file with mode: 0644]
dist/js/thymol-node.js [new file with mode: 0644]
dist/js/thymol-node.min.js [new file with mode: 0644]
dist/js/thymol.js [new file with mode: 0644]

diff --git a/dist/js/thymol-full.js b/dist/js/thymol-full.js
new file mode 100644 (file)
index 0000000..137fcc3
--- /dev/null
@@ -0,0 +1,8305 @@
+/*-------------------- Thymol - the flavour of Thymeleaf --------------------*
+
+   Thymol version 2.0.0 Copyright (C) 2012-2015 James J. Benson
+   jjbenson .AT. users.sf.net (http://www.thymoljs.org/)
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" basis,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ *---------------------------------------------------------------------------*/
+
+thymol = function() {
+    thymol.thVersion = "2.0.0";
+    thymol.thReleaseDate = "2015-03-31";
+    thymol.thURL = "http://www.thymoljs.org";
+    thymol.thAltURL = "http://www.thymeleaf.org";
+    thymol.thUsingNullPrefix = false;
+    thymol.thThymeleafPrefixList = [];
+    thymol.thThymeleafElementsList = [];
+    thymol.objects = {};
+    var textFuncSynonym = "~~~~", varRefExpr = /([$#]{.*?})/, literalTokenExpr = /^[a-zA-Z0-9\[\]\.\-_]*$/, startParserLevelCommentExpr = /^\s*\/\*\s*$/, endParserLevelCommentExpr = /^\s*\*\/\s*$/, startParserLevelCommentExpr2 = /^\/\*[^\/].*/, endParserLevelCommentExpr2 = /.*[^\/]\*\/$/, prototypeOnlyCommentEscpExpr = /\/\*\/(.*)\/\*\//, varExpr3 = /[\$\*#@]{1}\{(.*)\}$/, nonURLExpr = /[\$\*#]{1}\{(?:!?[^}]*)\}/, numericExpr = /^[+\-]?[0-9]*?[.]?[0-9]*?$/, varParExpr = /([^(]*)\s*[(]([^)]*?)[)]/, domSelectExpr = /([\/]{1,2})?([A-Za-z0-9_\-]*(?:[\(][\)])?)?([^\[]\S[A-Za-z0-9_\-]*(?:[\(][\)])?[\/]*(?:[\.\/#]?[^\[]\S[A-Za-z0-9_\-]*(?:[\(][\)])?[\/]*)*)?([\[][^\]]*?[\]])?/, litSubstExpr = /\.*?([\|][^\|]*?[\|])\.*?/;
+    function Thymol() {}
+    function isClientSide() {
+        if (typeof thymol.isServerSide !== "undefined" && !!thymol.isServerSide()) {
+            thymol.isClientSide = function() {
+                return false;
+            };
+            return false;
+        }
+        thymol.isClientSide = function() {
+            return true;
+        };
+        return true;
+    }
+    function execute(doc) {
+        if (typeof thymol.protocol === "undefined") {
+            thymol.protocol = "";
+        }
+        if (typeof thymol.root === "undefined") {
+            thymol.root = "";
+        }
+        if (typeof thymol.path === "undefined") {
+            thymol.path = "";
+        }
+        thymol.thDocument = doc;
+        var theWindow = thymol.thWindow;
+        if (typeof thymol.thWindow === "undefined") {
+            if (typeof doc.defaultView !== "undefined") {
+                theWindow = doc.defaultView;
+            } else if (typeof doc.parentWindow !== "undefined") {
+                theWindow = doc.parentWindow;
+            }
+        }
+        thymol.thWindow = theWindow;
+        var theTop = thymol.thTop;
+        if (typeof thymol.thTop === "undefined") {
+            if (typeof top !== "undefined") {
+                theTop = top;
+            }
+        }
+        thymol.thTop = theTop;
+        thymol.init();
+        var base = new ThNode(thymol.thDocument, false, null, null, null, thymol.thDocument.nodeName, "::", false, thymol.thDocument);
+        Thymol.prototype.process(base);
+        postExecute();
+        return thymol.thDocument;
+    }
+    function jqSetup(jq) {
+        jq.fn.extend({
+            getComments: function() {
+                return this.filter(function() {
+                    return this.nodeType === 8;
+                });
+            },
+            getThDecorated: function(thInst) {
+                var i, iAttrName, iLength, j, jLength, instances = [], result = null, expanded = false;
+                if (thInst.escpName !== null) {
+                    instances = this.filter(thInst.escpName);
+                }
+                if (thInst.escpSynonym !== null) {
+                    instances = instances.add(this.filter(thInst.escpSynonym));
+                }
+                for (i = 0, iLength = instances.length; i < iLength; i++) {
+                    if (instances[i]) {
+                        for (j = 0, jLength = instances[i].attributes.length; j < jLength; j++) {
+                            if (instances[i].attributes[j]) {
+                                iAttrName = instances[i].attributes[j].name;
+                                if (iAttrName && (thInst.name == iAttrName || thInst.synonym == iAttrName)) {
+                                    expanded = thymol.ThUtils.processElement(thInst.process, instances[i], instances[i].attributes[j], thInst);
+                                    if (expanded) {
+                                        if (result === null) {
+                                            result = [];
+                                        }
+                                        result.push(instances[i]);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                return result;
+            }
+        });
+    }
+    function ready(func) {
+        if (typeof thymolDeferredFunctions === "undefined" || thymolDeferredFunctions === null) {
+            thymolDeferredFunctions = [];
+        }
+        thymolDeferredFunctions.push(func);
+    }
+    function setupEnv() {
+        thymol.prefix = Thymol.prototype.getThParam("thPrefix", false, false, thymol.thDefaultPrefix);
+        thymol.dataPrefix = Thymol.prototype.getThParam("thDataPrefix", false, false, thymol.thDefaultDataPrefix);
+        thymol.messagePath = Thymol.prototype.getThParam("thMessagePath", false, true, thymol.thDefaultMessagePath);
+        thymol.resourcePath = Thymol.prototype.getThParam("thResourcePath", false, true, thymol.thDefaultResourcePath);
+        thymol.messagesBaseName = Thymol.prototype.getThParam("thMessagesBaseName", false, false, thymol.thDefaultMessagesBaseName);
+        thymol.relativeRootPath = Thymol.prototype.getThParam("thRelativeRootPath", false, true, thymol.thDefaultRelativeRootPath);
+        thymol.extendedMapping = Thymol.prototype.getThParam("thExtendedMapping", true, false, thymol.thDefaultExtendedMapping);
+        thymol.localMessages = Thymol.prototype.getThParam("thLocalMessages", true, false, thymol.thDefaultLocalMessages);
+        thymol.disableMessages = Thymol.prototype.getThParam("thDisableMessages", true, false, thymol.thDefaultDisableMessages);
+        thymol.templateSuffix = Thymol.prototype.getThParam("thTemplateSuffix", false, false, thymol.thDefaultTemplateSuffix);
+        thymol.scriptPath = "";
+        if (typeof thymol.thScriptPath !== "undefined") {
+            thymol.scriptPath = Thymol.prototype.getThParam("thScriptPath", false, true, thymol.thScriptPath);
+        }
+        thymol.absolutePath = "";
+        if (typeof thymol.thAbsolutePath !== "undefined") {
+            thymol.absolutePath = Thymol.prototype.getThParam("thAbsolutePath", false, true, thymol.thAbsolutePath);
+        }
+        thymol.useAbsolutePath = false;
+        if (typeof thymol.thUseAbsolutePath !== "undefined") {
+            thymol.useAbsolutePath = Thymol.prototype.getThParam("thUseAbsolutePath", true, false, thymol.thUseAbsolutePath);
+        }
+        thymol.useFullURLPath = true;
+        if (typeof thymol.thUseFullURLPath !== "undefined") {
+            thymol.useFullURLPath = Thymol.prototype.getThParam("thUseFullURLPath", true, false, thymol.thUseFullURLPath);
+        }
+        thymol.indexFile = Thymol.prototype.getThParam("thIndexFile", false, false, null);
+        thymol.debug = Thymol.prototype.getThParam("thDebug", true, false, false);
+        thymol.allowNullText = Thymol.prototype.getThParam("thAllowNullText", true, false, true);
+        thymol.location = thymol.thLocation;
+        if ("" !== thymol.relativeRootPath) {
+            thymol.root = thymol.location + thymol.relativeRootPath;
+            thymol.messagePath = thymol.root + thymol.messagePath;
+        } else {
+            if (typeof thymol.thMessagePath !== "undefined") {
+                thymol.messagePath = Thymol.prototype.getThParam("thMessagePath", false, true, thymol.thMessagePath);
+            }
+            if (typeof thymol.thRoot !== "undefined") {
+                thymol.root = Thymol.prototype.getThParam("thRoot", false, true, thymol.thRoot);
+            }
+        }
+        thymol.root = Thymol.prototype.getThParam("thRoot", false, true, thymol.root);
+        if (typeof thymol.thPath !== "undefined") {
+            thymol.path = Thymol.prototype.getThParam("thPath", false, true, thymol.thPath);
+        }
+        thymol.path = Thymol.prototype.getThParam("thPath", false, true, thymol.path);
+        thymol.protocol = thymol.thDocument.location.protocol;
+        if ("" == thymol.protocol) {
+            thymol.protocol = thymol.thDefaultProtocol;
+        } else {
+            thymol.protocol += "//";
+            if ("" == thymol.thDocument.location.host) {
+                thymol.protocol += "/";
+            }
+        }
+        thymol.protocol = Thymol.prototype.getThParam("thProtocol", false, false, thymol.protocol);
+        thymol.resourcePath = Thymol.prototype.getThParam("thResourcePath", false, true, thymol.resourcePath);
+    }
+    function updatePrefix(pref) {
+        thymol.prefix = pref;
+        thymol.thThymeleafPrefixList = [];
+        thymol.thThymeleafElementsList = [];
+    }
+    function init() {
+        this.messages = null;
+        this.mappings = null;
+        this.debug = null;
+        getLocations(this);
+        this.locale = new thymol.ThObject();
+        getLanguage();
+        var accessor = undefined, i, iLimit, j, jLimit;
+        if (typeof thVars !== "undefined") {
+            accessor = new thymol.ThVarsAccessor(thVars, "thVars");
+        }
+        this.applicationContext = thymol.makeContext("application", accessor);
+        this.sessionContext = thymol.makeContext("session", undefined);
+        this.sessionContext.persist = function() {
+            var save = this.serialise();
+            thymol.thTop.name = save;
+        };
+        this.requestContext = thymol.makeContext("request", undefined);
+        this.booleanAndNullTokens = new Array();
+        this.booleanAndNullTokens["null"] = this.applicationContext.createVariable("null", null);
+        this.booleanAndNullTokens["true"] = this.applicationContext.createVariable("true", true);
+        this.booleanAndNullTokens["false"] = this.applicationContext.createVariable("false", false);
+        this.allowNullText = null;
+        setupEnv();
+        this.thCache = {};
+        this.thExpressionObjects;
+        this.thDeferredFunctions;
+        this.thPreExecutionFunctions;
+        this.thPostExecutionFunctions;
+        if (typeof this.thExpressionObjects === "undefined" || this.thExpressionObjects === null) {
+            this.thExpressionObjects = {};
+        }
+        this.thExpressionObjects["#object"] = {};
+        this.thExpressionObjects["#locale"] = {};
+        this.thExpressionObjects["#ctx"] = [];
+        this.thExpressionObjects["#ctx"]["variables"] = {};
+        thymol.configureModule(thymol.objects.thHttpServletRequestObject);
+        thymol.configureModule(thymol.objects.thHttpSessionObject);
+        if (typeof thymol.thObjectsConfigureModules !== "undefined") {
+            thymol.thObjectsConfigureModules();
+        }
+        var scripts = thymol.thDocument.getElementsByTagName("script");
+        for (var i = 0, iLimit = scripts.length; i < iLimit; i++) {
+            var parameters = scripts[i].getAttribute("data-thymol-load");
+            if (!!parameters) {
+                var splits = parameters.split(",");
+                for (var j = 0, jLimit = splits.length; j < jLimit; j++) {
+                    thymol.ThUtils.loadScript(splits[j]);
+                }
+            }
+        }
+        setupEnv();
+        if (typeof thymol.thPreExecutionFunctions === "undefined" || thymol.thPreExecutionFunctions === null) {
+            thymol.thPreExecutionFunctions = [];
+        }
+        if (typeof thymol.thPostExecutionFunctions === "undefined" || thymol.thPostExecutionFunctions === null) {
+            thymol.thPostExecutionFunctions = [];
+        }
+        $.ajaxSetup({
+            async: false,
+            isLocal: true,
+            dataType: "text"
+        });
+        if (!(typeof thVars === "undefined")) {
+            for (i = 0, iLimit = thVars.length; i < iLimit; i++) {
+                this.applicationContext.createVariable(thVars[i][0], thVars[i][1]);
+            }
+        }
+        executeDeferred();
+        (function() {
+            var htmlTagAttrs = $("html")[0].attributes, tp = null, tu, nsspec;
+            $([ thymol.thURL, thymol.thAltURL ]).each(function() {
+                tu = this;
+                $(htmlTagAttrs).each(function() {
+                    if (this.value == tu) {
+                        nsspec = this.localName.split(":");
+                        if (nsspec.length > 0) {
+                            tp = nsspec[nsspec.length - 1];
+                            return false;
+                        }
+                    }
+                });
+                if (tp) {
+                    thymol.updatePrefix(tp);
+                    return false;
+                }
+            });
+        })();
+        var defaultScriptUrl = "";
+        if (!!thymol.thRequest) {
+            thymol.thWindow.location.search = thymol.thRequest;
+        }
+        (function(app, req) {
+            var e, f, a = /\+/g, r = /([^&=]+)=?([^&]*)/g, d = function(s) {
+                return decodeURIComponent(s.replace(a, " "));
+            }, q = thymol.thWindow.location.search.substring(1), surl, scriptUrl = defaultScriptUrl;
+            $("script").each(function() {
+                surl = this.src;
+                if (surl.indexOf(thymol.thScriptName) >= 0) {
+                    scriptUrl = d(surl);
+                    return false;
+                }
+            });
+            while (e = r.exec(scriptUrl)) {
+                f = e[1].split("?");
+                switch (f[1]) {
+                  case "thPrefix":
+                    thymol.prefix = e[2];
+                    break;
+
+                  case "thDataPrefix":
+                    thymol.dataPrefix = e[2];
+                    break;
+
+                  case "thMessagePath":
+                    thymol.messagePath = e[2];
+                    break;
+
+                  case "thResourcePath":
+                    thymol.resourcePath = e[2];
+                    break;
+
+                  case "thMessagesBaseName":
+                    thymol.messagesBaseName = e[2];
+                    break;
+
+                  case "thRelativeRootPath":
+                    thymol.relativeRootPath = e[2];
+                    break;
+
+                  case "thExtendedMapping":
+                    thymol.extendedMapping = e[2];
+                    break;
+
+                  case "thTemplateSuffix":
+                    thymol.templateSuffix = e[2];
+                    break;
+
+                  case "thLocalMessages":
+                    thymol.localMessages = e[2];
+                    break;
+
+                  case "thDisableMessages":
+                    thymol.disableMessages = e[2];
+                    break;
+
+                  case "thIndexFile":
+                    thymol.indexFile = e[2];
+                    break;
+
+                  case "thProtocol":
+                    thymol.protocol = e[2];
+                    break;
+
+                  case "thDebug":
+                    thymol.debug = e[2];
+                    break;
+
+                  case "thRoot":
+                    thymol.root = e[2];
+                    break;
+
+                  case "thPath":
+                    thymol.path = e[2];
+                    break;
+
+                  case "thAllowNullText":
+                    thymol.allowNullText = e[2];
+                    break;
+
+                  case "thLocale":
+                    thymol.locale.value = e[2];
+                    break;
+
+                  case "thDefaultPrecision":
+                    thymol.thDefaultPrecision = e[2];
+                    break;
+
+                  case "thDefaultPrecedence":
+                    thymol.thDefaultPrecedence = e[2];
+                    break;
+
+                  default:
+                    app.createVariable(e[1], e[2]);
+                }
+            }
+            while (e = r.exec(q)) {
+                req.createVariable(d(e[1]), e[2], true);
+            }
+        })(this.applicationContext, this.requestContext);
+        thymol.thInclude = new thymol.ThAttr("include", null, 100, null, thymol.prefix);
+        thymol.thReplace = new thymol.ThAttr("replace", null, 100, null, thymol.prefix);
+        thymol.thSubstituteby = new thymol.ThAttr("substituteby", null, 100, null, thymol.prefix);
+        thymol.thFragment = new thymol.ThAttr("fragment", null, 2e4, null, thymol.prefix);
+        thymol.thRemove = null;
+        thymol.thBlock = new thymol.ThElement("block", function(element) {
+            var i, limit = element.childNodes.length;
+            for (i = 0; i < limit; i++) {
+                if (element.childNodes[i].nodeType === 1) {
+                    element.childNodes[i].isBlockChild = true;
+                }
+            }
+        }, thymol.prefix);
+        this.applicationContext.resolveJSONReferences();
+        thymol.setupAttrList();
+        preExecute(this.applicationContext);
+        this.thExpressionObjects["#vars"] = this.applicationContext;
+        this.thExpressionObjects["#root"] = this.applicationContext;
+        this.sessionContext.init();
+        this.sessionContext.resolveJSONReferences();
+        this.requestContext.resolveJSONReferences();
+        this.thExpressionObjects["#ctx"]["variables"] = this.applicationContext;
+        this.thExpressionObjects["#ctx"]["requestParameters"] = this.requestContext;
+        this.thExpressionObjects["#ctx"]["servletContext"] = this.applicationContext;
+        this.thExpressionObjects["#ctx"]["httpServletRequest"] = this.thExpressionObjects["#httpServletRequest"];
+        this.thExpressionObjects["#ctx"]["httpSession"] = this.thExpressionObjects["#httpSession"];
+        this.protocol = Thymol.prototype.override("thProtocol", this.protocol);
+        this.debug = Thymol.prototype.override("thDebug", this.debug);
+        this.root = Thymol.prototype.override("thRoot", this.root);
+        if ("" !== this.relativeRootPath) {
+            var rootURI = thymol.thDocument.location.href;
+            var quePos = rootURI.indexOf("?");
+            if (quePos >= 0) {
+                rootURI = rootURI.substring(0, quePos);
+            }
+            var sepPos = rootURI.lastIndexOf("/");
+            if (sepPos >= 0) {
+                rootURI = rootURI.substring(0, sepPos + 1);
+            }
+            var newThRoot = rootURI + this.thLocation + this.relativeRootPath;
+            this.thRoot = Thymol.prototype.getThParam("thRoot", false, true, newThRoot);
+        }
+        this.path = Thymol.prototype.override("thPath", this.path);
+        this.allowNullText = Thymol.prototype.override("thAllowNullText", this.allowNullText);
+        this.locale.value = Thymol.prototype.override("thLocale", this.locale.value);
+        if (!(typeof thMappings === "undefined")) {
+            this.mappings = [];
+            for (j = 0, jLimit = thMappings.length; j < jLimit; j++) {
+                this.mappings.push([ thMappings[j][0], thMappings[j][1] ]);
+            }
+            this.mappings.sort(function(a, b) {
+                return a[0].length > b[0].length ? -1 : 1;
+            });
+        }
+        this.messages = {};
+        setLocaleValue();
+        if (!(typeof thMessages === "undefined")) {
+            this.messages[""] = [];
+            for (j = 0, jLimit = thMessages.length; j < jLimit; j++) {
+                this.messages[""][thMessages[j][0]] = thMessages[j][1];
+            }
+            for (var k in thMessages) {
+                if (thMessages.hasOwnProperty(k)) {
+                    if (!k.match(numericExpr)) {
+                        this.messages[k] = [];
+                        for (j = 0, jLimit = thMessages[k].length; j < jLimit; j++) {
+                            this.messages[k][thMessages[k][j][0]] = thMessages[k][j][1];
+                        }
+                    }
+                }
+            }
+        }
+        if (!(typeof thDisable === "undefined")) {
+            for (j = 0, jLimit = thDisable.length; j < jLimit; j++) {
+                Thymol.prototype.doDisable(thDisable[j]);
+            }
+        }
+        thymol.thRemove = Thymol.prototype.getThAttrByName("remove");
+    }
+    function getLocations(thiz) {
+        thiz.templateName = "";
+        thiz.templatePath = "";
+        if (!!thymol.thDocument.location.href) {
+            var templateName = templatePath = thymol.thDocument.location.href;
+            thiz.templateName = templateName.substring(0, templateName.indexOf(".") == -1 ? templateName.length : templateName.lastIndexOf("."));
+            thiz.templatePath = templatePath.substring(0, templatePath.indexOf("/") == -1 ? 0 : templatePath.lastIndexOf("/") + 1);
+        }
+    }
+    function getCtx() {
+        return thymol.thExpressionObjects["#ctx"];
+    }
+    function configureModule(module) {
+        if (typeof thymol.thExpressionObjects === "undefined" || thymol.thExpressionObjects === null) {
+            thymol.thExpressionObjects = {};
+        }
+        thymol.thExpressionObjects[module.thExpressionObjectName] = module;
+    }
+    function configureAttributeProcessor(prefix, suffix, func, prec, dataAttr) {
+        var p = prefix + ":";
+        if (p !== null) {
+            if (thymol.thThymeleafPrefixList.indexOf(p) < 0) {
+                thymol.thThymeleafPrefixList.push(p);
+            }
+        } else {
+            thymol.thUsingNullPrefix = true;
+        }
+        p = new thymol.ThAttr(suffix, func, prec, thymol.thThymeleafPrefixList, prefix, dataAttr);
+    }
+    function configureElementProcessor(prefix, suffix, func) {
+        var p = new thymol.ThElement(suffix, func, prefix);
+    }
+    function configurePreExecution(func) {
+        if (typeof thymol.thPreExecutionFunctions === "undefined" || thymol.thPreExecutionFunctions === null) {
+            thymol.thPreExecutionFunctions = [];
+        }
+        thymol.thPreExecutionFunctions.push(func);
+    }
+    function configurePostExecution(func) {
+        if (typeof thymol.thPostExecutionFunctions === "undefined" || thymol.thPostExecutionFunctions === null) {
+            thymol.thPostExecutionFunctions = [];
+        }
+        thymol.thPostExecutionFunctions.push(func);
+    }
+    function executeDeferred() {
+        if (typeof thymolDeferredFunctions !== "undefined" && thymolDeferredFunctions !== null) {
+            while (thymolDeferredFunctions.length > 0) {
+                var func = thymolDeferredFunctions.pop();
+                func();
+            }
+        }
+    }
+    function preExecute(context) {
+        while (thymol.thPreExecutionFunctions.length > 0) {
+            var func = thymol.thPreExecutionFunctions.pop();
+            func();
+            context.resolveJSONReferences();
+        }
+    }
+    function postExecute() {
+        while (thymol.thPostExecutionFunctions.length > 0) {
+            var func = thymol.thPostExecutionFunctions.pop();
+            func();
+        }
+    }
+    function preProcess(expr, element) {
+        var result = expr, fp, lp;
+        do {
+            fp = result.indexOf("__");
+            if (fp >= 0) {
+                lp = -1;
+                if (result.length > 4) {
+                    lp = result.lastIndexOf("__");
+                }
+                if (lp <= 0) {
+                    throw new thymol.ThError("Mismatched pre-processing indicators", element);
+                }
+                var head = result.substring(0, fp);
+                var centre = result.substring(fp + 2, lp);
+                centre = this.getParsedExpr(centre, element);
+                var tail = result.substring(lp + 2);
+                result = head + centre + tail;
+                fp = result.indexOf("__");
+            }
+        } while (fp >= 0);
+        result = result.replace(/\\_\\_/g, "__");
+        return result;
+    }
+    function substituteParam(argValue, mode, element) {
+        var result = argValue, varName = argValue, subs = null, msg, expo;
+        if (result) {
+            if (mode === 4) {
+                msg = thymol.getMessage(varName);
+                if (msg) {
+                    subs = msg;
+                }
+            } else if (mode === 6) {
+                subs = argValue;
+            } else {
+                var token = thymol.booleanAndNullTokens[result];
+                if (!(typeof token === "undefined")) {
+                    if (token === null) {
+                        subs = null;
+                    } else {
+                        subs = token.value;
+                    }
+                } else {
+                    if (varName.charAt(0) === "#") {
+                        if ("#object" === varName) {
+                            if (element.thObjectVar) {
+                                subs = element.thObjectVar;
+                            }
+                        } else {
+                            expo = thymol.thExpressionObjects[varName];
+                            if (typeof expo !== "undefined" && expo !== null) {
+                                subs = expo;
+                            }
+                        }
+                    }
+                    if ((typeof subs === "undefined" || subs == null) && element.thObjectVar) {
+                        subs = element.thObjectVar[varName];
+                    }
+                    if ((typeof subs === "undefined" || subs == null) && element.thLocalVars) {
+                        subs = element.thLocalVars[varName];
+                    }
+                    if (typeof subs === "undefined" || subs == null) {
+                        subs = thymol.ThUtils.getParameter(varName);
+                    }
+                    if (typeof subs === "undefined" || subs == null) {
+                        if ("param" === varName) {
+                            subs = thymol.requestContext;
+                        }
+                        if ("session" === varName) {
+                            subs = thymol.sessionContext;
+                        }
+                        if ("application" === varName) {
+                            subs = thymol.applicationContext;
+                        }
+                    }
+                    if (mode === 2 && (typeof subs === "undefined" || subs == null)) {
+                        subs = argValue;
+                    }
+                }
+            }
+            result = subs;
+            if (subs instanceof thymol.ThParam) {
+                result = subs.value;
+            }
+        }
+        return result;
+    }
+    function getStandardURL(initial) {
+        var result = initial.trim(), mapped, head;
+        mapped = thymol.getMapped(result, thymol.extendedMapping);
+        if (mapped) {
+            result = mapped;
+        }
+        if ("/" === result && !!thymol.indexFile) {
+            result += thymol.indexFile;
+        }
+        if (!/.*:\/\/.*/.test(result)) {
+            if (/^~?\/.*$/.test(result)) {
+                if (/^~.*$/.test(result)) {
+                    result = result.substring(1);
+                }
+                if (!/^\/\/.*$/.test(result)) {
+                    if (thymol.useFullURLPath) {
+                        head = thymol.root + thymol.resourcePath;
+                        if (head != "") {
+                            if (head.charAt(head.length - 1) !== "/") {
+                                head = head + "/";
+                            }
+                            if (result.charAt(0) === "/") {
+                                result = head + result.substring(1);
+                            } else {
+                                result = head + result;
+                            }
+                        }
+                    } else {
+                        result = thymol.resourcePath + result;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    function getExpression(argValue, element) {
+        var result = argValue, subst = false, initial, shortCut, args, negate, token, lsp;
+        if (typeof argValue === "string") {
+            initial = argValue.trim();
+            result = initial;
+            if (result) {
+                shortCut = thymol.ThUtils.getParameter(result);
+                if (!shortCut) {
+                    args = result.match(varExpr3);
+                    if (args) {
+                        if (args[1] && args[1].length > 0) {
+                            shortCut = thymol.ThUtils.getParameter(args[1]);
+                        }
+                    }
+                }
+                if (shortCut) {
+                    if (shortCut instanceof thymol.ThParam) {
+                        result = shortCut.value;
+                    } else {
+                        result = shortCut;
+                    }
+                    if (typeof result === "string" && result.match(numericExpr)) {
+                        result = parseInt(result);
+                    }
+                } else {
+                    initial = thymol.ThUtils.unParenthesise(result);
+                    negate = false;
+                    if (initial.charAt(0) == "!") {
+                        negate = true;
+                        initial = initial.substring(1, initial.length);
+                        initial = thymol.ThUtils.unParenthesise(initial);
+                    }
+                    if (literalTokenExpr.test(initial)) {
+                        token = thymol.booleanAndNullTokens[initial];
+                        if (!(typeof token === "undefined")) {
+                            result = token.value;
+                            subst = true;
+                        }
+                    }
+                    lsp = null;
+                    if (!subst) {
+                        lsp = initial.match(litSubstExpr);
+                        if (lsp && lsp.length > 0) {
+                            if (thymol.ThUtils.charOcurrences(lsp[1], "'") < 2) {
+                                initial = Thymol.prototype.doLiteralSubstExpr(initial, lsp[1]);
+                            }
+                        }
+                        result = "";
+                        if (initial != "") {
+                            initial = thymol.ThUtils.unParenthesise(initial);
+                            initial = thymol.preProcess(initial, element);
+                            result = thymol.getParsedExpr(initial, element, true);
+                        }
+                    }
+                    if (result == initial && typeof result == typeof initial) {
+                        result = null;
+                    } else if (typeof result === "string") {
+                        if (!lsp) {
+                            result = result.replace(/[\\][\\]/g, "\\");
+                        }
+                        result = result.replace(/&#39;/g, "'").replace(/&apos;/gi, "'");
+                    }
+                    if (negate) {
+                        if (typeof result === "boolean") {
+                            result = !result;
+                        } else if (typeof result === "number") {
+                            result = result == 0;
+                        } else if (typeof result === "string") {
+                            result = !thymol.ThUtils.testLiteralFalse(result);
+                        }
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    function getMapped(uri, extended) {
+        var mapped = null, i, iLimit, key;
+        if (uri && typeof uri === "string") {
+            if (thymol.mappings) {
+                for (i = 0, iLimit = thymol.mappings.length; i < iLimit; i++) {
+                    key = thymol.mappings[i][0];
+                    if (uri == key) {
+                        mapped = thymol.mappings[i][1];
+                        break;
+                    } else if (extended) {
+                        if (uri.indexOf(key) == 0) {
+                            mapped = uri.substring(key.length);
+                            mapped = thymol.mappings[i][1] + mapped;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        return mapped;
+    }
+    function substitute(initial, element, lenient) {
+        var argValue = initial, result, args, token, re, subs, saved;
+        if (typeof argValue === "string") {
+            argValue = argValue.trim();
+        }
+        result = argValue;
+        args = "";
+        while (args != null) {
+            args = argValue.match(/.*([$\*#@]{(!?[^}]*)}).*/);
+            if (args != null && args.length > 0) {
+                if (args.length == 3) {
+                    token = args[1];
+                    token = token.replace(/[$]/g, "[$]").replace(/[*]/g, "[*]").replace(/[\']/g, "[']").replace(/[+]/g, "[+]").replace(/[\(]/g, "[(]").replace(/[\)]/g, "[)]");
+                    re = new RegExp(token);
+                    subs = this.getExpression(args[2], element);
+                    if (subs != args[2]) {
+                        result = result.replace(re, subs, "g");
+                        if (result == "null") {
+                            result = null;
+                        }
+                    } else {
+                        subs = "";
+                        if (thymol.debug && !lenient) {
+                            thymol.thWindow.alert('thymol variable substitution failed: "' + initial + '"');
+                        }
+                    }
+                    saved = argValue;
+                    argValue = argValue.replace(re, subs, "g");
+                    if (saved == argValue) {
+                        argValue = "";
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    function getWith(element, content) {
+        var argValue = content.trim(), argCount = 0;
+        if (argValue) {
+            do {
+                var argsExpr = thymol.ThParser.parse(argValue, true, false);
+                var identifier = argsExpr.tokens.shift();
+                if (identifier.type_ === 3) {
+                    var result = argsExpr.evaluate(element);
+                    var varName = identifier.index_;
+                    if (!!varName) {
+                        argCount++;
+                        if (!element.thLocalVars) {
+                            element.thLocalVars = {};
+                        }
+                        element.thLocalVars[varName] = result;
+                    }
+                    argValue = argValue.substring(argsExpr.position);
+                } else {
+                    break;
+                }
+            } while (argValue.length > 0);
+        }
+        return argCount;
+    }
+    function getParsedExpr(initial, element, preprocessed) {
+        var expr, result = initial;
+        expr = thymol.ThParser.parse(result, false, preprocessed);
+        expr = expr.simplify();
+        result = expr.evaluate(element);
+        if (typeof result === "number") {
+            result = thymol.ThUtils.getToPrecision(result, expr.precision);
+        }
+        return result;
+    }
+    function getBooleanValue(param) {
+        var flag = false, val, args;
+        if (param != null) {
+            if (typeof param === "boolean") {
+                flag = param;
+            } else if (typeof param === "number") {
+                flag = param != 0;
+            } else {
+                val = param;
+                if (Object.prototype.toString.call(val) === "[object Array]") {
+                    if (val.length === 1) {
+                        val = val[0];
+                    } else {
+                        val = true;
+                    }
+                }
+                if (typeof val === "boolean") {
+                    flag = val;
+                } else if (typeof val === "number") {
+                    flag = val != 0;
+                } else if (typeof val === "string") {
+                    args = val.match(nonURLExpr);
+                    if (args) {
+                        val = args[1];
+                        flag = this.testParam(val);
+                    } else {
+                        flag = !thymol.ThUtils.testLiteralFalse(val);
+                    }
+                } else if (val instanceof thymol.ThParam) {
+                    flag = val.getBooleanValue();
+                } else {
+                    flag = typeof val !== "undefined" && val !== null;
+                }
+            }
+        }
+        return flag;
+    }
+    function isFragmentChild(element) {
+        var result = false, parent = element.parentElement;
+        while (parent) {
+            if (parent.getAttribute(thymol.thFragment.name) || parent.getAttribute(thymol.thFragment.synonym)) {
+                result = true;
+                break;
+            }
+            parent = parent.parentElement;
+        }
+        return result;
+    }
+    function setLocale(locValue) {
+        thymol.locale.value = locValue;
+        setLocaleValue();
+    }
+    function getLocale() {
+        return thymol.locale.value;
+    }
+    function getLanguage() {
+        if (!thymol.locale.value) {
+            if (typeof navigator !== "undefined" && !!navigator) {
+                var userLang = navigator.language || navigator.userLanguage || navigator.browserLanguage || navigator.systemLanguage;
+                if (!!userLang) {
+                    thymol.locale.value = userLang.replace(/\-/g, "_");
+                }
+            }
+        }
+    }
+    function setLocaleValue() {
+        if (!thymol.locale.value) {
+            thymol.locale.value = thymol.thDefaultLocale;
+        }
+        var sepPos;
+        var locale = thymol.locale.value.replace(/\-/g, "_");
+        var level = thymol.locale.value;
+        var levels = [];
+        var part, parts = [];
+        do {
+            levels.push(level);
+            sepPos = locale.lastIndexOf("_");
+            if (sepPos >= 0) {
+                part = locale.substring(sepPos + 1);
+                parts.push(part);
+                locale = locale.substring(0, sepPos);
+                level = level.substring(0, sepPos);
+            }
+        } while (sepPos >= 0);
+        thymol.locale.language = level;
+        if (!!parts) {
+            parts.reverse();
+            for (var i = 0, iLimit = parts.length; i < iLimit; i++) {
+                if (i === 0) {
+                    thymol.locale.country = parts[i];
+                } else if (i === 1) {
+                    thymol.locale.variant = parts[i];
+                }
+            }
+        }
+        thymol.locale.levels = levels;
+        thymol.thExpressionObjects["#ctx"]["locale"] = thymol.locale;
+        thymol.thExpressionObjects["#locale"] = thymol.locale;
+    }
+    function getMessage(varName, parameters, returnStringAlways) {
+        if (thymol.disableMessages) {
+            return undefined;
+        }
+        var msgKey = null;
+        var locale;
+        if (!!thymol.locale.levels) {
+            var prefix = "$";
+            var ident, section, jLower = thymol.localMessages ? 0 : 1;
+            for (var j = jLower; j < 2; j++) {
+                for (var i = 0, iLimit = thymol.locale.levels.length; i < iLimit + 1; i++) {
+                    ident = prefix;
+                    if (i < iLimit) {
+                        locale = thymol.locale.levels[i];
+                    } else {
+                        locale = "";
+                    }
+                    ident = ident + locale;
+                    section = thymol.messages[ident];
+                    if (!section) {
+                        if (j < 1) {
+                            section = getLocalMessages(locale);
+                        } else {
+                            section = getDefaultMessages(locale);
+                        }
+                    }
+                    if (!!section) {
+                        thymol.messages[ident] = section;
+                        msgKey = section[varName];
+                        if (!!msgKey) {
+                            break;
+                        }
+                    }
+                }
+                if (!!msgKey) {
+                    break;
+                }
+                prefix += "$";
+            }
+        }
+        if (!msgKey) {
+            for (var i = 0, iLimit = thymol.locale.levels.length; i <= iLimit; i++) {
+                if (i < iLimit) {
+                    locale = thymol.locale.levels[i];
+                } else {
+                    locale = "";
+                }
+                if (!!thymol.messages[locale]) {
+                    msgKey = thymol.messages[locale][varName];
+                    if (!!msgKey) {
+                        break;
+                    }
+                }
+            }
+        }
+        if (!!msgKey) {
+            if (typeof parameters === "undefined") {
+                return msgKey;
+            } else {
+                return thymol.ThUtils.renderMessage(msgKey, parameters);
+            }
+        } else if (returnStringAlways !== undefined && returnStringAlways) {
+            return "??" + varName + "_" + thymol.locale.value + "??";
+        }
+        return null;
+    }
+    function getProperties(propFile) {
+        var props = null;
+        var messages = [];
+        $.get(propFile, function(textContent, status) {
+            var err = null;
+            try {
+                if ("success" == status) {
+                    props = textContent;
+                } else if (thymol.debug) {
+                    thymol.thWindow.alert("read failed: " + propFile);
+                }
+            } catch (err) {
+                if (thymol.debug) {
+                    thymol.thWindow.alert("properties file read failed: " + propFile + " error: " + err);
+                }
+            }
+        }, "text");
+        if (props !== null) {
+            var splits = props.split("\n");
+            if (splits.length > 0) {
+                for (var i = 0, iLimit = splits.length; i < iLimit; i++) {
+                    var line = splits[i].trim();
+                    if (line.charAt(0) !== "#") {
+                        var p = line.split("=");
+                        if (p.length > 1) {
+                            messages[p[0].trim()] = thymol.ThUtils.unicodeUnescape(p[1].trim());
+                        }
+                    }
+                }
+            }
+        }
+        return messages;
+    }
+    function getLocalMessages(locale) {
+        var messages = [];
+        if (!!thymol.thDocument.location.href) {
+            var propsFile = thymol.templateName;
+            if (!!locale && locale !== "") {
+                propsFile += "_" + locale;
+            }
+            propsFile += ".properties";
+            messages = getProperties(propsFile);
+        }
+        return messages;
+    }
+    function getDefaultMessages(locale) {
+        var messages = null;
+        var propsPath = "";
+        if (thymol.useAbsolutePath) {
+            propsPath += thymol.protocol + thymol.root + thymol.path;
+        }
+        propsPath += thymol.messagePath;
+        if (propsPath !== "") {
+            propsPath += "/";
+        }
+        var propsFile = propsPath + thymol.messagesBaseName;
+        if (!!locale && locale !== "") {
+            propsFile += "_" + locale;
+        }
+        propsFile += ".properties";
+        messages = getProperties(propsFile);
+        return messages;
+    }
+    Thymol.prototype = {
+        process: function(rootNode) {
+            var n = rootNode;
+            try {
+                while (n.thDoc) {
+                    this.getChildren(n);
+                    if (n.firstChild && n.firstChild.thDoc && !n.visited) {
+                        n.visited = true;
+                        n = n.firstChild;
+                    } else {
+                        if (n.element != n.thDoc) {
+                            this.doReplace(n.isNode, n.element, n.thDoc);
+                            if (!n.isNode) {
+                                n.thDoc = n.element;
+                            }
+                        }
+                        if (n.nextSibling && n.nextSibling.thDoc) {
+                            n = n.nextSibling;
+                        } else {
+                            if (n == rootNode) {
+                                break;
+                            }
+                            n = n.parentDoc;
+                        }
+                    }
+                }
+                this.processChildren(rootNode);
+            } catch (err) {
+                if (thymol.debug) {
+                    if (err instanceof thymol.ThError) {
+                        if (!err.suppress) {
+                            thymol.thWindow.alert(err);
+                        }
+                    } else {
+                        thymol.thWindow.alert(err);
+                    }
+                }
+            }
+        },
+        getChildren: function(rootNode) {
+            var count = 0, last = null, changed = false, child, froot, fstar, fchildren, i, iLimit, j, jLimit, element, matches, theAttr;
+            if (!rootNode.visited) {
+                this.processComments(rootNode);
+                var rnd = this.getContentRoot(rootNode);
+                froot = $(rnd);
+                fstar = $(froot).add(froot.find("*"));
+                fchildren = fstar.filter(thymol.thInclude.escpName).add(fstar.filter(thymol.thInclude.escpSynonym)).add(fstar.filter(thymol.thReplace.escpName)).add(fstar.filter(thymol.thReplace.escpSynonym)).add(fstar.filter(thymol.thSubstituteby.escpName)).add(fstar.filter(thymol.thSubstituteby.escpSynonym));
+                for (i = 0, iLimit = fchildren.length; i < iLimit; i++) {
+                    element = fchildren[i], matches = [];
+                    for (j = 0, jLimit = element.attributes.length; j < jLimit; j++) {
+                        theAttr = element.attributes[j];
+                        if (thymol.thInclude.name == theAttr.name || thymol.thInclude.synonym == theAttr.name || thymol.thReplace.name == theAttr.name || thymol.thReplace.synonym == theAttr.name || thymol.thSubstituteby.name == theAttr.name || thymol.thSubstituteby.synonym == theAttr.name) {
+                            matches.push(theAttr);
+                        }
+                    }
+                    for (j = 0, jLimit = matches.length; j < jLimit; j++) {
+                        child = this.processImport(element, rootNode, matches[j]);
+                        if (child != null) {
+                            changed = true;
+                            if (count == 0) {
+                                rootNode.firstChild = child;
+                            } else {
+                                last.nextSibling = child;
+                            }
+                            last = child;
+                            count++;
+                        }
+                    }
+                }
+            }
+            return changed;
+        },
+        processChildren: function(rootNode) {
+            var i, iLimit, j, jLimit, k, kLimit;
+            var elements = rootNode.thDoc.getElementsByTagName("*");
+            for (k = 0, kLimit = elements.length; k < kLimit; k++) {
+                var element = elements[k];
+                for (j = 0, jLimit = thymol.thThymeleafElementsList.length; j < jLimit; j++) {
+                    if (element.localName == thymol.thThymeleafElementsList[j].name || element.localName == thymol.thThymeleafElementsList[j].synonym) {
+                        var updated = thymol.thThymeleafElementsList[j].process(element);
+                        if (updated) {
+                            elements = rootNode.thDoc.getElementsByTagName("*");
+                            k--;
+                            kLimit = elements.length;
+                        }
+                        break;
+                    }
+                }
+                var allAttributes = element.attributes;
+                if (allAttributes && allAttributes.length > 0) {
+                    var attributes = [], aii = 0;
+                    if (!thymol.thUsingNullPrefix) {
+                        for (i = 0, iLimit = allAttributes.length; i < iLimit; i++) {
+                            var ai = allAttributes[i];
+                            if (ai) {
+                                for (j = 0, jLimit = thymol.thThymeleafPrefixList.length; j < jLimit; j++) {
+                                    var attrName = ai.name.toString();
+                                    if (attrName.length > thymol.thThymeleafPrefixList[j].length) {
+                                        attrName = attrName.substring(0, thymol.thThymeleafPrefixList[j].length);
+                                        if (attrName === thymol.thThymeleafPrefixList[j]) {
+                                            ai.order = i;
+                                            attributes[aii++] = ai;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    } else {
+                        attributes = allAttributes;
+                    }
+                    if (attributes.length > 0) {
+                        attributes.sort(function(a, b) {
+                            return b.order - a.order;
+                        });
+                        var matchedAttributes = [];
+                        for (i = 0, iLimit = attributes.length; i < iLimit; i++) {
+                            var splits = attributes[i].name.toString().split(":");
+                            if (splits && splits.length > 0) {
+                                var prefix = "", name;
+                                if (splits.length > 1) {
+                                    prefix = splits[0];
+                                    name = splits[1];
+                                } else {
+                                    name = splits[0];
+                                    var hpos = name.lastIndexOf("-");
+                                    if (hpos >= 0) {
+                                        prefix = name.substring(0, hpos + 1);
+                                    }
+                                }
+                                var attrList = thymol.thThymeleafPrefixList[prefix];
+                                if (splits.length > 1) {
+                                    prefix += ":";
+                                }
+                                if (attrList) {
+                                    for (j = 0, jLimit = attrList.length; j < jLimit; j++) {
+                                        var matched = false;
+                                        if (name === attrList[j].suffix || name === attrList[j].synonym) {
+                                            matched = true;
+                                        } else if (attrList[j].regex !== null) {
+                                            var fqn = prefix + name;
+                                            matched = attrList[j].regex.test(fqn);
+                                        }
+                                        if (matched) {
+                                            var matchedAttribute = {};
+                                            matchedAttribute.attr = attrList[j];
+                                            matchedAttribute.elementAttr = attributes[i];
+                                            matchedAttributes.push(matchedAttribute);
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (matchedAttributes.length > 0) {
+                            matchedAttributes.sort(function(a, b) {
+                                return a.attr.precedence - b.attr.precedence;
+                            });
+                            var updated = false;
+                            for (i = 0, iLimit = matchedAttributes.length; i < iLimit; i++) {
+                                var exp = thymol.ThUtils.processElement(matchedAttributes[i].attr.process, element, matchedAttributes[i].elementAttr, matchedAttributes[i].attr, 1);
+                                updated = exp || updated;
+                            }
+                            if (updated) {
+                                elements = rootNode.thDoc.getElementsByTagName("*");
+                                k--;
+                                kLimit = elements.length;
+                            }
+                        }
+                    }
+                }
+            }
+            elements = rootNode.thDoc.getElementsByTagName("*");
+            var kc = 0;
+            for (k = 0, kLimit = elements.length; k < kLimit; k++) {
+                var element = elements[kc];
+                var elName = element.nodeName.toLowerCase();
+                if (elName == thymol.thBlock.name || elName == thymol.thBlock.synonym) {
+                    thymol.ThUtils.removeTag(element);
+                    elements = rootNode.thDoc.getElementsByTagName("*");
+                } else {
+                    kc++;
+                }
+            }
+        },
+        override: function(paramName, paramValue) {
+            var param = paramValue, thv;
+            thv = thymol.thWindow[paramName];
+            if (typeof thv === "undefined") {
+                thv = thymol.applicationContext.javascriptify(paramName);
+            }
+            if (thv) {
+                if (thv instanceof thymol.ThParam) {
+                    param = thv.value;
+                } else {
+                    param = thv;
+                }
+            }
+            thv = thymol.applicationContext[paramName];
+            if (thv) {
+                if (thv instanceof thymol.ThParam) {
+                    param = thv.value;
+                } else {
+                    param = thv;
+                }
+            }
+            thv = thymol.requestContext[paramName];
+            if (thv) {
+                if (thv instanceof thymol.ThParam) {
+                    param = thv.value;
+                } else {
+                    param = thv;
+                }
+            }
+            return param;
+        },
+        doDisable: function(attrName) {
+            var tha = this.getThAttrByName(attrName);
+            if (tha !== null) {
+                tha.disable();
+            } else {
+                if (thymol.debug) {
+                    thymol.thWindow.alert('cannot disable unknown attribute "' + attrName + '"');
+                }
+            }
+        },
+        getThAttrByName: function(name) {
+            var attrList = thymol.thThymeleafPrefixList[thymol.prefix];
+            attrList.push(thymol.thInclude);
+            attrList.push(thymol.thReplace);
+            attrList.push(thymol.thSubstituteby);
+            attrList.push(thymol.thFragment);
+            var i, iLimit = attrList.length;
+            for (i = 0; i < iLimit; i++) {
+                if (name === attrList[i].suffix) {
+                    return attrList[i];
+                }
+            }
+            return null;
+        },
+        getContents: function(rootNode) {
+            var rnd = this.getContentRoot(rootNode);
+            var froot = $(rnd);
+            var fstar = froot.find("*");
+            return fstar;
+        },
+        getContentRoot: function(rn) {
+            var rnd = rn.thDoc;
+            if (rnd.nodeName !== "#document") {
+                rnd = rnd.childNodes;
+            }
+            return rnd;
+        },
+        processComments: function(rootNode) {
+            var comments = null, fstar, changed, i, iLimit, startComment, parent, startValue, pointer, nextPointer;
+            do {
+                fstar = this.getContents(rootNode);
+                comments = fstar.contents().getComments();
+                changed = false;
+                for (i = 0, iLimit = comments.length; i < iLimit; i++) {
+                    startComment = comments[i];
+                    parent = startComment.parentNode;
+                    startValue = startComment.nodeValue.trim();
+                    if (startParserLevelCommentExpr.test(startValue)) {
+                        pointer = startComment;
+                        while (pointer != null) {
+                            if (endParserLevelCommentExpr.test(pointer.nodeValue)) {
+                                changed = parent.removeChild(pointer) != null;
+                                break;
+                            }
+                            nextPointer = pointer.nextSibling;
+                            changed = parent.removeChild(pointer) != null;
+                            pointer = nextPointer;
+                        }
+                    } else if (startParserLevelCommentExpr2.test(startValue) && endParserLevelCommentExpr2.test(startValue)) {
+                        parent.removeChild(startComment);
+                        changed = true;
+                    }
+                }
+            } while (changed);
+            this.processPrototypeOnlyComments(rootNode);
+        },
+        processPrototypeOnlyComments: function(rootNode) {
+            var comments = null, fstar, changed, indexOfLast, i, iLimit, j, jLimit, k, kLimit, startComment, parent, deletions, res, fullText, innerNodes, done, next, commentText, res2, blockElement, blockDoc, blockDocBody, blockBase, newNode, newDoc;
+            do {
+                fstar = this.getContents(rootNode);
+                comments = fstar.contents().getComments();
+                changed = false;
+                indexOfLast = comments.length - 1;
+                for (i = 0, iLimit = comments.length; i < iLimit; i++) {
+                    startComment = comments[i];
+                    parent = startComment.parentNode;
+                    if (parent != null) {
+                        startValue = startComment.nodeValue.trim();
+                        deletions = [];
+                        deletions.push(startComment);
+                        startValue = startValue.replace(/\n/g, "");
+                        res = startValue.match(prototypeOnlyCommentEscpExpr);
+                        if (res) {
+                            fullText = startValue;
+                            if (parent.localName == "table" || parent.localName == "tbody") {
+                                if (startValue.indexOf(thymol.thBlock.name) >= 0 || startValue.indexOf(thymol.thBlock.synonym) >= 0) {
+                                    if (startValue.indexOf(thymol.thBlock.endName) < 0 || startValue.indexOf(thymol.thBlock.endSynonym) < 0) {
+                                        fullText = fullText.replace(res[0], res[1]);
+                                        innerNodes = [];
+                                        done = false;
+                                        next = startComment;
+                                        do {
+                                            next = next.nextSibling;
+                                            if (next != null) {
+                                                deletions.push(next);
+                                                if (i < indexOfLast) {
+                                                    if (next == comments[i + 1]) {
+                                                        commentText = next.nodeValue;
+                                                        if (commentText.indexOf(thymol.thBlock.endName) >= 0 || commentText.indexOf(thymol.thBlock.endSynonym) >= 0) {
+                                                            res2 = commentText.match(prototypeOnlyCommentEscpExpr);
+                                                            if (res2) {
+                                                                commentText = commentText.replace(res2[0], res2[1]);
+                                                                fullText = fullText + commentText;
+                                                            }
+                                                            done = true;
+                                                        }
+                                                    } else {
+                                                        innerNodes.push(next);
+                                                    }
+                                                }
+                                            } else {
+                                                done = true;
+                                            }
+                                        } while (!done);
+                                        blockElement = null;
+                                        blockDoc = new thymol.thDomParser().parseFromString(fullText, "text/html");
+                                        blockDocBody = $(blockDoc).find("body")[0];
+                                        for (j = 0, jLimit = blockDocBody.childNodes.length; j < jLimit; j++) {
+                                            if (blockDocBody.childNodes[j].localName == thymol.thBlock.name || blockDocBody.childNodes[j].localName == thymol.thBlock.synonym) {
+                                                blockElement = blockDocBody.childNodes[j];
+                                                for (k = 0, kLimit = innerNodes.length; k < kLimit; k++) {
+                                                    newNode = blockDoc.importNode(innerNodes[k], true);
+                                                    blockElement.appendChild(newNode);
+                                                }
+                                            }
+                                        }
+                                        if (blockElement != null) {
+                                            blockBase = new ThNode(blockDoc, false, null, null, null, blockDoc.nodeName, "::", false, blockDoc);
+                                            this.processChildren(blockBase);
+                                            changed = this.insertUncommented(blockBase.thDoc, deletions, parent);
+                                        } else {
+                                            parent.removeChild(startComment);
+                                            changed = true;
+                                        }
+                                    } else {
+                                        parent.removeChild(startComment);
+                                        changed = true;
+                                    }
+                                }
+                            } else {
+                                startValue = startValue.substring(3, startValue.length - 3);
+                                newDoc = new thymol.thDomParser().parseFromString(startValue, "text/html");
+                                changed = this.insertUncommented(newDoc, deletions, parent);
+                            }
+                        }
+                    }
+                }
+            } while (changed);
+        },
+        insertUncommented: function(doc, deletions, parent) {
+            var docBody = $(doc).find("body")[0], i, iLimit, newNode;
+            for (i = 0, iLimit = docBody.childNodes.length; i < iLimit; i++) {
+                if (parent.ownerDocument === doc) {
+                    newNode = docBody.childNodes[i].cloneNode(true);
+                } else {
+                    newNode = parent.ownerDocument.importNode(docBody.childNodes[i], true);
+                    newNode.parentNode = parent;
+                }
+                parent.insertBefore(newNode, deletions[0]);
+            }
+            for (i = 0, iLimit = deletions.length; i < iLimit; i++) {
+                parent.removeChild(deletions[i]);
+            }
+            return true;
+        },
+        getList: function(element, content) {
+            var argValue = content.trim(), argsCount = 0, argsList = [], assigs, i, iLimit, val;
+            if (argValue) {
+                assigs = argValue.split(",");
+                for (i = 0, iLimit = assigs.length; i < iLimit; i++) {
+                    val = thymol.getExpression(assigs[i], element);
+                    argsList[i] = val;
+                }
+                if (!element.thLocalVars) {
+                    element.thLocalVars = {};
+                }
+                element.thLocalVars["..."] = argsList;
+                argsCount = argsList.length;
+            }
+            return argsCount;
+        },
+        testParam: function(param) {
+            var initial = param, result = false, theParam = null, negate = false;
+            if (typeof initial === "boolean") {
+                result = initial;
+            } else {
+                theParam = null;
+                negate = false;
+                if (typeof initial === "object" && initial instanceof thymol.ThParam) {
+                    theParam = initial;
+                } else {
+                    initial = initial.valueOf();
+                    if (initial.charAt(0) == "!") {
+                        negate = true;
+                        initial = initial.substring(1);
+                    }
+                }
+                theParam = thymol.applicationContext[initial];
+                if (theParam != null) {
+                    result = theParam.getBooleanValue();
+                }
+                if (negate) {
+                    result = !result;
+                }
+            }
+            return result ? true : false;
+        },
+        processImport: function(element, rootNode, attr) {
+            var importNode = null, filePart, fragmentPart, names, parts, fragmentArgsList, isNode, fragment, fileName, content, importError;
+            filePart = null;
+            if (attr.value.indexOf("::") < 0) {
+                filePart = attr.value;
+                fragmentPart = "::";
+            } else {
+                names = attr.value.split("::");
+                filePart = names[0].trim();
+                fragmentPart = names[1].trim();
+            }
+            if ("this" === filePart) {
+                filePart = "";
+            } else {
+                filePart = this.getFilePath(filePart, element);
+            }
+            if (filePart != null) {
+                parts = filePart.match(varParExpr);
+                fragmentArgsList = null;
+                if (parts) {
+                    if (parts.length > 1) {
+                        filePart = parts[1].trim();
+                    }
+                    if (parts.length > 2) {
+                        fragmentArgsList = parts[2].trim();
+                    }
+                }
+                if (filePart != "" || !isFragmentChild(element)) {
+                    isNode = thymol.thReplace.name == attr.localName || thymol.thReplace.synonym == attr.localName || thymol.thSubstituteby.name == attr.localName || thymol.thSubstituteby.synonym == attr.localName;
+                    if (thymol.thCache[filePart] != null && thymol.thCache[filePart][fragmentPart] != null) {
+                        isNode = isNode || fragmentPart == "::";
+                        importNode = new ThNode(thymol.thCache[filePart][fragmentPart], false, rootNode, null, null, filePart, fragmentPart, isNode, element);
+                    } else {
+                        fragment = null;
+                        importError = null;
+                        if (filePart != "") {
+                            fileName = filePart + thymol.templateSuffix;
+                            $.get(fileName, function(textContent, status) {
+                                try {
+                                    if ("success" == status) {
+                                        content = new thymol.thDomParser().parseFromString(textContent, "text/html");
+                                        fragment = Thymol.prototype.getImportNode(element, filePart, fragmentPart, fragmentArgsList, content);
+                                    } else if (thymol.debug) {
+                                        thymol.thWindow.alert("thymol.processImport file read failed: " + filePart + " fragment: " + fragmentPart);
+                                    }
+                                } catch (err) {
+                                    importError = err;
+                                }
+                            }, "text");
+                        } else {
+                            fragment = this.getImportNode(element, filePart, fragmentPart, fragmentArgsList, thymol.thDocument);
+                        }
+                        if (fragment == null) {
+                            if (importError !== null) {
+                                throw importError;
+                            }
+                            if (thymol.debug) {
+                                thymol.thWindow.alert("thymol.processImport fragment import failed: " + filePart + " fragment: " + fragmentPart);
+                            }
+                        } else {
+                            importNode = new ThNode(fragment, false, rootNode, null, null, filePart, fragmentPart, isNode, element);
+                        }
+                    }
+                }
+            }
+            element.removeAttribute(attr.name);
+            return importNode;
+        },
+        getImportNode: function(element, filePart, fragmentArg, fragmentArgsList, content) {
+            var result = null, fragmentName = fragmentArg.trim(), fragmentPart = fragmentName, parts, argsCount, matched, fragment, htmlContent, fragArray, i, iLimit, j, jLimit, k, clean, bare, vlParts, vlArgs, argsList, varName, newElement;
+            fragmentName = fragmentName.replace(/text\(\)/g, textFuncSynonym);
+            parts = fragmentName.match(varParExpr);
+            if (parts == null && fragmentArgsList != null) {
+                parts = [];
+                parts[1] = fragmentName;
+                parts[2] = fragmentArgsList;
+            }
+            argsCount = 0;
+            if (parts) {
+                if (parts.length > 1) {
+                    fragmentName = parts[1].trim();
+                    if (parts.length > 2) {
+                        if (parts[2].indexOf("=") > 0) {
+                            argsCount = thymol.getWith(element, parts[2]);
+                        } else {
+                            argsCount = this.getList(element, parts[2]);
+                        }
+                    }
+                }
+            }
+            if (thymol.thCache[filePart] == null) {
+                thymol.thCache[filePart] = new Object();
+            }
+            matched = false;
+            fragment = null;
+            if (fragmentName == "::") {
+                htmlContent = $("html", content)[0];
+                result = htmlContent;
+                matched = true;
+            } else {
+                fragArray = $(thymol.thFragment.escpName, content);
+                for (i = 0, iLimit = fragArray.length; i < iLimit; i++) {
+                    fragment = fragArray[i];
+                    for (j = 0, jLimit = fragment.attributes.length; j < jLimit; j++) {
+                        clean = fragment.attributes[j];
+                        clean = clean.value.replace(/\s/g, "");
+                        bare = null;
+                        vlParts = clean.match(varParExpr);
+                        if (vlParts) {
+                            if (vlParts.length > 1) {
+                                bare = vlParts[1].trim();
+                            }
+                        }
+                        if (fragmentName == bare && argsCount > 0) {
+                            if (vlParts.length > 2) {
+                                vlArgs = vlParts[2].trim().split(",");
+                                if (vlArgs) {
+                                    if (vlArgs.length == argsCount) {
+                                        argsList = element.thLocalVars["..."];
+                                        if (argsList != null) {
+                                            for (k = 0; k < argsCount; k++) {
+                                                varName = vlArgs[k].trim();
+                                                element.thLocalVars[varName] = argsList[k];
+                                            }
+                                            element.thLocalVars["..."] = null;
+                                        }
+                                        matched = true;
+                                        break;
+                                    } else if (vlArgs.length > argsCount) {
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        if (fragmentName == clean || fragmentPart == clean || fragmentName == bare) {
+                            matched = true;
+                            break;
+                        }
+                    }
+                    if (matched) {
+                        result = fragment;
+                        break;
+                    }
+                }
+            }
+            if (!matched) {
+                fragment = this.getDOMSelection(fragmentName, content);
+                if (fragment) {
+                    matched = true;
+                    result = fragment;
+                } else {
+                    if (!element.isBlockChild) {
+                        throw new thymol.ThError('getImportNode cannot match fragment: "' + fragmentName + '"', element);
+                    }
+                }
+            }
+            thymol.thCache[filePart][fragmentPart] = result;
+            if (matched) {
+                newElement = result.cloneNode(true);
+                if (newElement.nodeType == 1) {
+                    newElement.removeAttribute(thymol.thFragment.name);
+                    newElement.removeAttribute(thymol.thFragment.synonym);
+                }
+                result = newElement;
+                result.thLocalVars = element.thLocalVars;
+            }
+            return result;
+        },
+        getDOMSelection: function(initial, content) {
+            var spec = initial, result = null, scope = "", query = new Array(), parts = "", innr = thymol.ThUtils.unBracket(spec), i, iLimit, j, jLimit, k, kLimit, m, mLimit, token, indx, saved, indxed, start, selection, descend, subQuery, exprFrags, classSpecs, qTerms, subSelect, partial, html, newNode;
+            if (spec != innr && innr.charAt(innr.length - 1) == "]") {
+                spec = innr;
+            }
+            while (spec != "") {
+                parts = spec.match(domSelectExpr);
+                if (parts != null && parts.length > 1) {
+                    for (i = 1, iLimit = parts.length; i < iLimit; i++) {
+                        if (parts[i] != null) {
+                            token = parts[i];
+                            indx = null;
+                            innr = thymol.ThUtils.unBracket(token);
+                            if (token != innr) {
+                                if (innr.match(numericExpr)) {
+                                    indx = innr;
+                                }
+                            }
+                            saved = spec;
+                            spec = spec.replace(token, "");
+                            if (saved == spec) {
+                                spec = "";
+                            }
+                            if (indx) {
+                                token = query[query.length - 1];
+                                indxed = new String(token);
+                                indxed.indx = indx;
+                                query[query.length - 1] = indxed;
+                            } else {
+                                query.push(token.trim());
+                            }
+                            break;
+                        }
+                    }
+                } else {
+                    break;
+                }
+            }
+            start = 0;
+            if (query.length > 0 && query[0] != "" && query[0].charAt(0) == "/") {
+                scope = query[0];
+                start = 1;
+            }
+            selection = [];
+            selection.push(content);
+            descend = false;
+            for (i = start, iLimit = query.length; i < iLimit; i++) {
+                subQuery = query[i];
+                innr = thymol.ThUtils.unBracket(subQuery);
+                if (subQuery != innr) {
+                    innr = innr.replace(/[']/g, '"');
+                    subQuery = "";
+                    exprFrags = innr.split(/\s{1}\s*((?:and)|(?:or))\s{1}\s*/);
+                    for (j = 0, jLimit = exprFrags.length; j < jLimit; j++) {
+                        if (exprFrags[j] != "and" && exprFrags[j] != "or") {
+                            classSpecs = exprFrags[j].match(/[@]?\s*(?:class)\s*(\W?[=])\s*[\"]((?:\w*[\-_]*)*)[\"]/);
+                            if (classSpecs && classSpecs.length > 0) {
+                                if (classSpecs[1] == "=") {
+                                    subQuery = subQuery + "[class~='" + classSpecs[2] + "']";
+                                }
+                                if (classSpecs[1] == "^=") {
+                                    subQuery = subQuery + "[class^='" + classSpecs[2] + "'],[class*=' " + classSpecs[2] + "']";
+                                }
+                            } else {
+                                subQuery = subQuery + "[" + exprFrags[j] + "]";
+                            }
+                        } else if (exprFrags[j] == "or") {
+                            subQuery = subQuery + ",";
+                        }
+                    }
+                }
+                qTerms = subQuery.split("/");
+                for (j = 0, jLimit = qTerms.length; j < jLimit; j++) {
+                    if (qTerms[j] != "") {
+                        qTerms[j] = qTerms[j].replace(/[@]/g, "");
+                        if (subQuery.indx != null) {
+                            qTerms[j] = qTerms[j] + ":eq(" + subQuery.indx + ")";
+                        }
+                        subSelect = [];
+                        for (k = 0, kLimit = selection.length; k < kLimit; k++) {
+                            partial = null;
+                            if (qTerms[j] == textFuncSynonym) {
+                                partial = $(selection[k]).contents().filter(function() {
+                                    return this.nodeType === 3;
+                                });
+                            } else if (descend) {
+                                partial = $(selection[k]).children(qTerms[j]);
+                            } else if (j == 0) {
+                                if (scope == "/") {
+                                    html = $("html", selection[k]);
+                                    if (html.length > 0) {
+                                        selection[k] = html;
+                                    }
+                                    partial = $(selection[k]).children("body").children(qTerms[j]);
+                                    scope = "";
+                                } else {
+                                    if (i == 0 || scope == "//") {
+                                        partial = $(selection[k]).find(qTerms[j]);
+                                        scope = "";
+                                    } else {
+                                        partial = $(selection[k]).filter(qTerms[j]);
+                                    }
+                                }
+                            } else {
+                                partial = $(selection[k]).children(qTerms[j]);
+                            }
+                            if (partial != null) {
+                                for (m = 0, mLimit = partial.length; m < mLimit; m++) {
+                                    subSelect.push(partial[m]);
+                                }
+                            }
+                        }
+                        selection = subSelect;
+                    }
+                }
+                descend = qTerms[qTerms.length - 1] == "";
+            }
+            result = selection;
+            if (result != null && !(result.length === undefined)) {
+                if (result.length > 1) {
+                    newNode = thymol.thDocument.createDocumentFragment();
+                    for (i = 0, iLimit = result.length; i < iLimit; i++) {
+                        var newChild = thymol.thDocument.importNode(result[i], true);
+                        newNode.appendChild(newChild);
+                    }
+                    result = newNode;
+                } else {
+                    result = result[0];
+                }
+            }
+            return result;
+        },
+        getFilePath: function(part, element) {
+            var result = thymol.substitute(part, element), mapped = null, slashpos;
+            if (result) {
+                if (thymol.mappings) {
+                    mapped = thymol.getMapped(result, false);
+                }
+            }
+            if (mapped) {
+                result = mapped;
+            } else {
+                var dotFirst = result.charAt(0) === ".";
+                if (result && (thymol.useAbsolutePath || !dotFirst)) {
+                    slashpos = result.indexOf("/");
+                    if (thymol.useAbsolutePath || slashpos >= 0) {
+                        if (slashpos == 0 && !thymol.useAbsolutePath) {
+                            result = result.substring(1);
+                        }
+                        var proto = "";
+                        if (thymol.useAbsolutePath) {
+                            proto = thymol.protocol;
+                        }
+                        if (thymol.useAbsolutePath && !!thymol.absolutePath) {
+                            result = proto + thymol.absolutePath + result;
+                        } else {
+                            if (dotFirst) {
+                                result = thymol.templatePath + result;
+                            } else {
+                                result = proto + thymol.root + thymol.path + result;
+                            }
+                        }
+                    }
+                }
+            }
+            return result;
+        },
+        doLiteralSubstExpr: function(param, primary) {
+            var result = param.trim(), term, subst, lsp;
+            if (thymol.ThUtils.isLiteralSubst(result)) {
+                result = this.decodeLiteralSubst(result);
+            } else {
+                term = primary;
+                while (term != null) {
+                    if (thymol.ThUtils.isLiteralSubst(term)) {
+                        subst = this.decodeLiteralSubst(term);
+                        result = result.replace(term, subst);
+                        lsp = result.match(litSubstExpr);
+                        if (lsp && lsp.length > 0) {
+                            term = lsp[1];
+                        } else {
+                            break;
+                        }
+                    } else {
+                        break;
+                    }
+                }
+            }
+            return result;
+        },
+        decodeLiteralSubst: function(param) {
+            var result = param, parts, rep, i, iLimit;
+            result = result.trim();
+            result = result.substring(1, result.length - 1);
+            result = result.replace(/[\']/g, "&#39;");
+            parts = result.split(varRefExpr);
+            if (parts && parts.length > 0) {
+                rep = "";
+                for (i = 0, iLimit = parts.length; i < iLimit; i++) {
+                    if (parts[i] != "") {
+                        if (!parts[i].match(varRefExpr)) {
+                            parts[i] = "'" + parts[i] + "'";
+                        }
+                        if (rep == "") {
+                            rep = parts[i];
+                        } else {
+                            rep = rep + "+" + parts[i];
+                        }
+                    }
+                }
+                result = rep;
+            }
+            return result;
+        },
+        doReplace: function(isNode, element, content) {
+            if (isNode) {
+                var parent = element.parentNode;
+                if (content.nodeName.toLowerCase() == "html") {
+                    this.doInsertion(element, content, function(e, n) {
+                        if (n.nodeType == 1) {
+                            n.removeAttribute(thymol.thFragment.name);
+                            n.removeAttribute(thymol.thFragment.synonym);
+                        }
+                        e.parentNode.insertBefore(n, e);
+                    });
+                    parent.removeChild(element);
+                } else {
+                    var node = this.doClone(content, parent.ownerDocument);
+                    if (node.nodeType == 1) {
+                        node.removeAttribute(thymol.thFragment.name);
+                        node.removeAttribute(thymol.thFragment.synonym);
+                    }
+                    parent.replaceChild(node, element);
+                    node.parentNode = parent;
+                }
+            } else {
+                try {
+                    while (element.firstChild != null) {
+                        element.removeChild(element.firstChild);
+                        if (element.firstChild == null) {
+                            break;
+                        }
+                    }
+                    this.doInsertion(element, content, function(e, n) {
+                        if (n.nodeType == 1) {
+                            n.removeAttribute(thymol.thFragment.name);
+                            n.removeAttribute(thymol.thFragment.synonym);
+                        }
+                        e.appendChild(n);
+                    });
+                } catch (err) {
+                    element.innerHTML = content.innerHTML;
+                }
+            }
+        },
+        doClone: function(old, targetDoc) {
+            var node, cNodes, i, iNode, aNode;
+            if (!!old.parentNode && old.parentNode.ownerDocument === targetDoc) {
+                node = old.cloneNode(false);
+            } else {
+                node = targetDoc.importNode(old, false);
+            }
+            if (node !== null) {
+                if (node.nodeType == 1) {
+                    if (old.thLocalVars !== null) {
+                        node.thLocalVars = old.thLocalVars;
+                    }
+                }
+                if (old.childNodes !== null) {
+                    cNodes = old.childNodes.length;
+                    if (cNodes > 0) {
+                        for (i = 0; i < cNodes; i++) {
+                            iNode = old.childNodes[i];
+                            if (iNode !== null) {
+                                aNode = this.doClone(iNode, targetDoc);
+                                if (aNode !== null) {
+                                    node.appendChild(aNode);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            return node;
+        },
+        doInsertion: function(element, content, func) {
+            var topLevel = true, parent = element.parentElement, i, iLimit, iNode, elementName, j, jLimit, jNode, cJNode, cINode;
+            if (parent != null) {
+                topLevel = element.parentElement.nodeName.toLowerCase() == "html";
+            }
+            for (i = 0, iLimit = content.childNodes.length; i < iLimit; i++) {
+                iNode = content.childNodes[i];
+                if (iNode) {
+                    if (!topLevel) {
+                        elementName = iNode.nodeName.toLowerCase();
+                        if (elementName != "head") {
+                            if (elementName == "body") {
+                                for (j = 0, jLimit = iNode.childNodes.length; j < jLimit; j++) {
+                                    jNode = iNode.childNodes[j];
+                                    if (jNode) {
+                                        cJNode = this.doClone(jNode, parent.ownerDocument);
+                                        func(element, cJNode);
+                                    }
+                                }
+                            } else {
+                                cINode = this.doClone(iNode, parent.ownerDocument);
+                                func(element, cINode);
+                            }
+                        }
+                    } else {
+                        cINode = this.doClone(iNode, parent.ownerDocument);
+                        func(element, cINode);
+                    }
+                }
+            }
+        },
+        getThParam: function(paramName, isBoolean, isPath, defaultValue) {
+            var localValue = defaultValue, globalValue = thymol.thWindow[paramName], theParam = thymol.ThUtils.getParameter(paramName);
+            if (typeof globalValue === "undefined") {
+                globalValue = thymol.applicationContext.javascriptify(paramName);
+            }
+            if (!!theParam) {
+                if (theParam instanceof ThParam) {
+                    if (theParam.globalValue !== globalValue) {
+                        theParam.globalValue = globalValue;
+                        theParam.value = globalValue;
+                        localValue = globalValue;
+                    }
+                }
+                if (isBoolean) {
+                    localValue = theParam.getBooleanValue();
+                }
+            } else {
+                if (!(typeof globalValue === "undefined")) {
+                    if (globalValue != null) {
+                        if (isBoolean) {
+                            localValue = globalValue == true;
+                        } else {
+                            localValue = globalValue;
+                        }
+                    }
+                }
+            }
+            if (!isBoolean && isPath && localValue.length > 0 && localValue.charAt(localValue.length - 1) != "/") {
+                localValue = localValue + "/";
+            }
+            thymol.applicationContext.createVariable(paramName, localValue);
+            return localValue;
+        }
+    };
+    function addDialect(spec) {
+        var i, iLimit, prec = thymol.thDefaultPrecedence;
+        if (spec !== null && typeof spec !== "undefined") {
+            if (spec.attributeProcessors !== null && typeof spec.attributeProcessors !== "undefined") {
+                for (i = 0, iLimit = spec.attributeProcessors.length; i < iLimit; i++) {
+                    if (spec.attributeProcessors[i].precedence !== null && typeof spec.attributeProcessors[i].precedence !== "undefined") {
+                        prec = spec.attributeProcessors[i].precedence;
+                    } else {
+                        prec = thymol.thDefaultPrecedence;
+                    }
+                    configureAttributeProcessor(spec.prefix, spec.attributeProcessors[i].name, spec.attributeProcessors[i].processor, prec, null);
+                }
+            }
+            if (spec.elementProcessors !== null && typeof spec.elementProcessors !== "undefined") {
+                for (i = 0, iLimit = spec.elementProcessors.length; i < iLimit; i++) {
+                    configureElementProcessor(spec.prefix, spec.elementProcessors[i].name, spec.elementProcessors[i].processor);
+                }
+            }
+            if (spec.objects !== null && typeof spec.objects !== "undefined") {
+                for (i = 0, iLimit = spec.objects.length; i < iLimit; i++) {
+                    if (spec.objects[i].name !== null && typeof spec.objects[i].name !== "undefined") {
+                        spec.objects[i].object.thExpressionObjectName = spec.objects[i].name;
+                        configureModule(spec.objects[i].object);
+                    } else {
+                        configureModule(spec.objects[i]);
+                    }
+                }
+            }
+        }
+    }
+    function ThNode(thDocParam, visitedParam, parentDocParam, firstChildParam, nextSiblingParam, fileNameParam, fragNameParam, isNodeParam, elementParam) {
+        this.thDoc = thDocParam;
+        this.visited = visitedParam;
+        this.parentDoc = parentDocParam;
+        this.firstChild = firstChildParam;
+        this.nextSibling = nextSiblingParam;
+        this.fileName = fileNameParam;
+        this.fragName = fragNameParam;
+        this.isNode = isNodeParam;
+        this.element = elementParam;
+    }
+    function ThError(message, element, source) {
+        this.name = "ThError";
+        this.message = message || "Default Message";
+        if (element !== null && typeof element !== "undefined" && element.isBlockChild) {
+            this.suppress = true;
+        } else {
+            this.element = element || {};
+            this.suppress = false;
+        }
+        if (!!source) {
+            if (!!source.stack) {
+                this.stack = source.stack;
+            }
+        }
+    }
+    ThError.prototype = new Error();
+    ThError.prototype.constructor = ThError;
+    function ThParam(valueArg) {
+        this.value = valueArg;
+        this.globalValue;
+        this["class"] = new thymol.ThClass("Thymol.ThParam");
+        this.getBooleanValue = function() {
+            return !thymol.ThUtils.testLiteralFalse(this.value);
+        };
+        this.toString = function() {
+            return this.value;
+        };
+        this.getNumericValue = function() {
+            return Number(this.value);
+        };
+    }
+    function ThAttr(suffix, func, prec, list, pref, dataAttr) {
+        var prefix = "", dataPrefix = null, escpPrefix = "";
+        if (typeof pref !== "undefined" && pref !== null) {
+            prefix = pref + ":";
+            if (thymol.thThymeleafPrefixList.indexOf(prefix) < 0) {
+                thymol.thThymeleafPrefixList.push(prefix);
+            }
+            escpPrefix = pref + "\\:";
+            if (typeof dataAttr === "undefined" || dataAttr === null) {
+                dataPrefix = thymol.dataPrefix + "-" + pref + "-";
+                if (thymol.thThymeleafPrefixList.indexOf(dataPrefix) < 0) {
+                    thymol.thThymeleafPrefixList.push(dataPrefix);
+                }
+            } else {
+                dataPrefix = dataAttr;
+            }
+        }
+        this.suffix = suffix;
+        this.name = prefix + suffix;
+        this.regex = null;
+        if (suffix.indexOf("*") >= 0 || suffix.indexOf("?") >= 0 || suffix.indexOf("+") >= 0 || suffix.indexOf("\\") >= 0 || suffix.indexOf("|") >= 0 || suffix.indexOf("[") >= 0 || suffix.indexOf("]") >= 0 || suffix.indexOf("{") >= 0 || suffix.indexOf("}") >= 0) {
+            if ("*" === suffix) {
+                suffix = ".*";
+            }
+            suffix = prefix + suffix;
+            this.regex = new RegExp(suffix);
+        }
+        this.escpName = "[" + escpPrefix + suffix + "]";
+        if (dataPrefix !== null) {
+            this.synonym = dataPrefix + suffix;
+            this.escpSynonym = "[" + this.synonym + "]";
+        } else {
+            this.synonym = null;
+            this.escpSynonym = null;
+        }
+        if (typeof prec !== "undefined" && prec !== null) {
+            this.precedence = prec;
+        } else {
+            this.precedence = thymol.thDefaultPrecedence;
+        }
+        if (!!list) {
+            var attrList = list[pref];
+            if (!attrList) {
+                attrList = [];
+                list[pref] = attrList;
+                if (dataPrefix !== null) {
+                    list[dataPrefix] = attrList;
+                }
+            }
+            attrList.push(this);
+        }
+        this.process = function() {
+            thymol.thWindow.alert('unsupported processing function for attribute "' + this.name + '"');
+        };
+        if (!(typeof func === "undefined")) {
+            this.process = func;
+        }
+        this.disable = function() {
+            this.name = null;
+            this.escpName = null;
+            this.escpSynonym = null;
+            this.process = function() {};
+        };
+    }
+    function ThElement(suffix, func, pref) {
+        var tha = new thymol.ThAttr(suffix, null, 0, null, pref);
+        this.name = tha.name;
+        this.synonym = tha.synonym;
+        this.endName = "/" + tha.name;
+        this.endSynonym = "/" + tha.synonym;
+        this.process = function() {
+            thymol.thWindow.alert('unsupported processing function for element "' + this.name + '"');
+        };
+        if (!(typeof func === "undefined")) {
+            this.process = func;
+        }
+        this.disable = function() {
+            this.name = null;
+            this.synonym = null;
+            this.endName = null;
+            this.endSynonym = null;
+            this.process = null;
+        };
+        thymol.thThymeleafElementsList.push(this);
+    }
+    function ThSet() {
+        this.that = this;
+        this.setSize = 0;
+        this.isContent = function(k) {
+            return this.hasOwnProperty(k) && typeof this[k] !== "function" && k !== "that" && k !== "setSize";
+        };
+        this.add = function(k) {
+            var contained = typeof this[k] !== "undefined";
+            this[k] = k;
+            if (contained !== (typeof this[k] !== "undefined")) {
+                this.setSize++;
+            }
+        };
+        this.addAll = function(other) {
+            var k = null, value;
+            for (k in other) {
+                if (other.hasOwnProperty(k)) {
+                    value = other[k];
+                    if (typeof value !== "function") {
+                        add(value);
+                    }
+                }
+            }
+        };
+        this.clear = function() {
+            for (var k in this) {
+                if (this.hasOwnProperty(k)) {
+                    delete this[k];
+                }
+            }
+            setSize = 0;
+        };
+        this.contains = function(k) {
+            return typeof this[k] !== "undefined";
+        };
+        this.containsAll = function(keys) {
+            var keySet = keys, k = null;
+            if (typeof keys === "Array" || Object.prototype.toString.call(keys) === "[object Array]") {
+                keySet = ThSet.prototype.fromArray(keys);
+            }
+            for (k in keySet) {
+                if (keySet.hasOwnProperty(k)) {
+                    if (typeof this[k] === "undefined") {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        };
+        this.isEmpty = function() {
+            return this.setSize === 0;
+        };
+        this.size = function() {
+            return this.setSize;
+        };
+        this.remove = function(k) {
+            var contained = typeof this[k] !== "undefined";
+            delete this[k];
+            if (contained !== (typeof this[k] !== "undefined")) {
+                this.setSize--;
+            }
+        };
+        this.toArray = function() {
+            return getArray(this);
+        };
+        this.toString = function() {
+            var array = getArray();
+            return array.toString();
+        };
+        function getArray(obj) {
+            var array = [], k = null, value;
+            for (k in obj) {
+                if (obj.hasOwnProperty(k) && k !== "that" && k !== "setSize") {
+                    value = obj[k];
+                    if (typeof value !== "function") {
+                        array.push(value);
+                    }
+                }
+            }
+            return array;
+        }
+    }
+    ThSet.prototype.fromArray = function(array) {
+        var set = new thymol.ThSet(), i, iLimit;
+        for (i = 0, iLimit = array.length; i < iLimit; i++) {
+            set.add(array[i]);
+        }
+        return set;
+    };
+    function ThMap() {
+        ThSet.apply(this);
+        this.containsKey = function(k) {
+            return this.contains(k);
+        };
+        this.containsValue = function(target) {
+            var k = null, value;
+            for (k in this.that) {
+                if (this.that.hasOwnProperty(k) && k !== "that") {
+                    value = this.that[k];
+                    if (value === target) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        };
+        this.entrySet = function() {
+            return this.that;
+        };
+        this.get = function(k) {
+            return this.that[k];
+        };
+        this.keySet = function() {
+            return this.that;
+        };
+        this.put = function(k, v) {
+            var contained = typeof this[k] !== "undefined";
+            this.that[k] = v;
+            if (contained !== (typeof this[k] !== "undefined")) {
+                this.setSize++;
+            }
+        };
+        this.putAll = function(t) {
+            for (var k in t) {
+                put(k, t[k]);
+            }
+        };
+        this.values = function() {
+            return this.that;
+        };
+    }
+    ThMap.prototype = new ThSet();
+    ThMap.prototype.constructor = ThMap;
+    function ThObject(dolly) {
+        for (prop in dolly) {
+            if (dolly.hasOwnProperty(prop)) {
+                if (prop) {
+                    if (!this[prop]) {
+                        this[prop] = dolly[prop];
+                    }
+                }
+            }
+        }
+        this["class"] = new thymol.ThClass("Thymol.ThObject");
+        this.toNonThObject = function() {
+            var plain = {};
+            for (prop in this) {
+                if (this.hasOwnProperty(prop)) {
+                    if (prop) {
+                        if (!plain[prop]) {
+                            if (prop !== "toNonThObject") {
+                                if (prop !== "class" || prop === "class" && this[prop] !== null && this[prop].name !== "Thymol.ThObject") {
+                                    plain[prop] = this[prop];
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            return plain;
+        };
+    }
+    function ThVarsAccessor(storeArg, storeNameArg) {
+        this.store = storeArg;
+        this.arrayName = storeNameArg;
+        this.length = function() {
+            return this.store.length;
+        };
+        this.get = function(name) {
+            return this.store[name];
+        };
+        this.set = function(name, value) {
+            this.store[name] = value;
+        };
+    }
+    function ThClass(nValue) {
+        this.name = nValue;
+    }
+    return {
+        Thymol: Thymol,
+        ThError: ThError,
+        ThParam: ThParam,
+        ThAttr: ThAttr,
+        ThElement: ThElement,
+        ThSet: ThSet,
+        ThMap: ThMap,
+        ThObject: ThObject,
+        ThVarsAccessor: ThVarsAccessor,
+        ThClass: ThClass,
+        thDomParser: thymol.thDomParser,
+        thDocument: thymol.thDocument,
+        thWindow: thymol.thWindow,
+        thTop: thymol.thTop,
+        thRequest: thymol.thRequest,
+        thVersion: thymol.thVersion,
+        thReleaseDate: thymol.thReleaseDate,
+        thURL: thymol.thURL,
+        thAltURL: thymol.thAltURL,
+        thInclude: thymol.thInclude,
+        thReplace: thymol.thReplace,
+        thSubstituteby: thymol.thSubstituteby,
+        thFragment: thymol.thFragment,
+        thRemove: thymol.thRemove,
+        thBlock: thymol.thBlock,
+        thScriptName: thymol.thScriptName,
+        thDefaultPrefix: thymol.thDefaultPrefix,
+        thDefaultDataPrefix: thymol.thDefaultDataPrefix,
+        thDefaultPrecision: thymol.thDefaultPrecision,
+        thDefaultProtocol: thymol.thDefaultProtocol,
+        thDefaultLocale: thymol.thDefaultLocale,
+        thDefaultPrecedence: thymol.thDefaultPrecedence,
+        thDefaultMessagePath: thymol.thDefaultMessagePath,
+        thDefaultResourcePath: thymol.thDefaultResourcePath,
+        thDefaultMessagesBaseName: thymol.thDefaultMessagesBaseName,
+        thDefaultRelativeRootPath: thymol.thDefaultRelativeRootPath,
+        thDefaultExtendedMapping: thymol.thDefaultExtendedMapping,
+        thDefaultLocalMessages: thymol.thDefaultLocalMessages,
+        thDefaultDisableMessages: thymol.thDefaultDisableMessages,
+        thDefaultTemplateSuffix: thymol.thDefaultTemplateSuffix,
+        thThymeleafPrefixList: thymol.thThymeleafPrefixList,
+        thThymeleafElementsList: thymol.thThymeleafElementsList,
+        thLocation: thymol.thLocation,
+        messagePath: thymol.messagePath,
+        resourcePath: thymol.resourcePath,
+        relativeRootPath: thymol.relativeRootPath,
+        messagesBaseName: thymol.messagesBaseName,
+        extendedMapping: thymol.extendedMapping,
+        scriptPath: thymol.scriptPath,
+        absolutePath: thymol.absolutePath,
+        useAbsolutePath: thymol.useAbsolutePath,
+        useFullURLPath: thymol.useFullURLPath,
+        localMessages: thymol.localMessages,
+        indexFile: thymol.indexFile,
+        disableMessages: thymol.disableMessages,
+        templateSuffix: thymol.templateSuffix,
+        prefix: thymol.prefix,
+        dataPrefix: thymol.dataPrefix,
+        templateName: thymol.templateName,
+        templatePath: thymol.templatePath,
+        objects: thymol.objects,
+        jqSetup: jqSetup,
+        isClientSide: isClientSide,
+        execute: execute,
+        updatePrefix: updatePrefix,
+        init: init,
+        ready: ready,
+        addDialect: addDialect,
+        isFragmentChild: isFragmentChild,
+        preProcess: preProcess,
+        substitute: substitute,
+        substituteParam: substituteParam,
+        configureModule: configureModule,
+        configureAttributeProcessor: configureAttributeProcessor,
+        configureElementProcessor: configureElementProcessor,
+        configurePreExecution: configurePreExecution,
+        configurePostExecution: configurePostExecution,
+        getStandardURL: getStandardURL,
+        getMessage: getMessage,
+        getExpression: getExpression,
+        getWith: getWith,
+        getParsedExpr: getParsedExpr,
+        getLocale: getLocale,
+        getMapped: getMapped,
+        getBooleanValue: getBooleanValue,
+        setLocale: setLocale
+    };
+}();
+
+thymol.makeContext = function(contextNameParam, varAccessorParam) {
+    var jsonDeclSpec = "(?:\\W*([\\'][A-Za-z]+(?:\\w|[$])*[\\'])\\s*[:])?\\s*([#][A-Za-z]+(?:\\w|[$])*)(?:\\W|[^$])*", jsonDeclExpr = new RegExp(jsonDeclSpec), context = new Array();
+    context.contextName = contextNameParam;
+    context.varAccessor = varAccessorParam;
+    context.varStore = [];
+    context.varNamePrefix = "";
+    if (typeof varAccessorParam === "undefined") {
+        context.varAccessor = new thymol.ThVarsAccessor(context.varStore, "varStore");
+    }
+    context.varNamePrefix = context.varAccessor.arrayName + "[";
+    context.getJSONView = function(param, rootVal) {
+        var pType = typeof param, view = "", objType;
+        if (pType === "string") {
+            view = view + "'" + param + "'";
+        } else if (pType === "number" || pType === "boolean") {
+            view = view + param;
+        } else if (pType === "object") {
+            if (param instanceof Object) {
+                objType = Object.prototype.toString.call(param);
+                if ("[object Array]" === objType) {
+                    view = this.getJSONViewArray(param, false);
+                } else if ("[object Object]" === objType) {
+                    view = this.getJSONViewObject(param, false);
+                }
+                view = "#" + view;
+            }
+        }
+        return view;
+    };
+    context.init = function() {
+        var persisted = thymol.thTop.name, paramRow, paramName, params, i, iLimit, paramValue;
+        if (persisted && persisted !== "") {
+            params = this.javascriptify(persisted);
+            if (params && params.length > 0) {
+                for (i = 0, iLimit = params.length; i < iLimit; i++) {
+                    paramRow = params[i];
+                    if (paramRow) {
+                        paramName = paramRow[0];
+                        if (paramName) {
+                            paramValue = paramRow[1];
+                            this.createVariable(paramName, paramValue);
+                        }
+                    }
+                }
+            }
+        }
+    };
+    context.getJSONViewObject = function(param, rootVal) {
+        var isRoot = true, key = null, view = "{", value, identifier, definition, suffix, instanceNamePrefix, isTaken, i, iLimit, instanceValue;
+        if (typeof rootVal === "boolean") {
+            isRoot = rootVal;
+        }
+        for (key in param) {
+            if (key) {
+                value = param[key];
+                if (typeof value !== "function") {
+                    if (view != "{") {
+                        view = view + ",";
+                    }
+                    identifier = this.getJSONView(key, false);
+                    definition = this.getJSONView(value, false);
+                    view = view + identifier + ":";
+                    if (!isRoot && typeof value === "object") {
+                        suffix = 1;
+                        instanceNamePrefix = key + "$";
+                        instanceName = null;
+                        isTaken = false;
+                        do {
+                            instanceName = instanceNamePrefix + suffix++;
+                            instanceValue = context[instanceName];
+                            if (instanceValue === null || typeof instanceValue === "undefined") {
+                                isTaken = false;
+                                for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
+                                    if (instanceName === varStore[i][0]) {
+                                        isTaken = true;
+                                        break;
+                                    }
+                                }
+                                if (!isTaken) {
+                                    this.addAttribute(instanceName, definition);
+                                }
+                            }
+                        } while (isTaken);
+                        if (instanceName !== null) {
+                            view = view + "#" + instanceName;
+                        }
+                    } else {
+                        view = view + definition;
+                    }
+                }
+            }
+        }
+        view = view + "}";
+        return view;
+    };
+    context.getJSONViewArray = function(param, rootVal) {
+        var view = "[", i;
+        for (i = 0; i < param.length; i++) {
+            view = view + this.getJSONView(param[i], false);
+            if (i < param.length - 1) {
+                view = view + ",";
+            }
+        }
+        view = view + "]";
+        return view;
+    };
+    context.getAttribute = function(name) {
+        return context[name];
+    };
+    context.addAttribute = function(name, value) {
+        var entry = [];
+        entry[0] = name;
+        entry[1] = value;
+        varStore.push(entry);
+    };
+    context.serialise = function() {
+        varStore = [];
+        var serialised = "[", key = null, value, cn, view, name, i, iLimit;
+        for (key in context) {
+            if (key) {
+                value = context[key];
+                if (value != null && typeof value === "object") {
+                    cn = Object.prototype.toString.call(value);
+                    if ("[object Array]" !== cn && !(value instanceof thymol.ThClass) && !(value instanceof thymol.ThVarsAccessor)) {
+                        if (serialised !== "[") {
+                            serialised = serialised + ",";
+                        }
+                        view = this.getJSONView(value, true);
+                        serialised = serialised + "[";
+                        serialised = serialised + '"' + key + '"';
+                        serialised = serialised + ",";
+                        serialised = serialised + '"' + view + '"';
+                        serialised = serialised + "]";
+                    }
+                }
+            }
+        }
+        for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
+            name = varStore[i][0];
+            view = varStore[i][1];
+            serialised = serialised + ",[";
+            serialised = serialised + '"' + name + '"';
+            serialised = serialised + ",";
+            serialised = serialised + '"' + view + '"';
+            serialised = serialised + "]";
+        }
+        serialised = serialised + "]";
+        return serialised;
+    };
+    context.javascriptify = function(fn) {
+        try {
+            return new Function("return " + fn)();
+        } catch (err) {
+            return undefined;
+        }
+    };
+    context.createVariable = function(name, valParam, isReq) {
+        var value = valParam, param, tt, literalBoolean, strValue, initial, existing, newArray;
+        param = value;
+        if (!(value instanceof thymol.ThParam)) {
+            tt = typeof valParam;
+            if (tt !== "function" && tt !== "object") {
+                if (tt === "string") {
+                    try {
+                        value = isReq ? decodeURIComponent(value) : decodeURI(value);
+                    } catch (err) {}
+                }
+                if (tt === "boolean" || tt === "number") {
+                    param = new thymol.ThParam(value);
+                } else if (value || value === "") {
+                    literalBoolean = thymol.ThUtils.testLiteralFalse(value);
+                    if (literalBoolean) {
+                        param = false;
+                    } else {
+                        strValue = new String(value);
+                        initial = strValue.trim();
+                        if (initial.charAt(0) === "#") {
+                            initial = initial.substring(1);
+                            try {
+                                param = this.createJSONVariable(initial);
+                            } catch (err) {
+                                if (err instanceof ReferenceError) {}
+                                if (err instanceof EvalError) {}
+                                if (param == null || isReq) {
+                                    param = new thymol.ThParam(value);
+                                }
+                            }
+                        } else {
+                            param = new thymol.ThParam(strValue.toString());
+                        }
+                    }
+                }
+            }
+        }
+        if (isReq) {
+            existing = context[name];
+            if (typeof existing !== "undefined" && existing !== null) {
+                if (Object.prototype.toString.call(existing) === "[object Array]") {
+                    existing.push(param);
+                } else {
+                    if (thymol.debug) {
+                        thymol.thWindow.alert('request parameters should be of type string array "' + name + '"');
+                    }
+                }
+            } else {
+                newArray = new Array();
+                newArray["class"] = {};
+                newArray["class"]["name"] = "[Thymol.ThParam]";
+                newArray.push(param);
+                context[name] = newArray;
+            }
+        } else {
+            context[name] = param;
+        }
+        return param;
+    };
+    context.createJSONVariable = function(initial) {
+        var current = initial.trim(), parts = " ", substIndex, token, re, vName, obj, result;
+        substIndex = this.varAccessor.length() + 1;
+        while (parts) {
+            parts = current.match(jsonDeclExpr);
+            if (parts && parts.length > 2) {
+                token = parts[2];
+                token = token.replace(/[\']/g, "[']").replace(/[$]/g, "[$]");
+                re = new RegExp(token);
+                vName = this.varNamePrefix + substIndex + "]";
+                obj = new Object();
+                obj.name = parts[2].substring(1);
+                this.varAccessor.set(substIndex, obj);
+                substIndex = substIndex + 1;
+                current = current.replace(re, "'" + vName + "'", "g");
+            }
+        }
+        current = current.replace(/[\']/g, '"');
+        result = $.parseJSON(current);
+        if ("[object Array]" !== Object.prototype.toString.call(result)) {
+            result = new thymol.ThObject(result);
+        }
+        return result;
+    };
+    context.resolveJSONReferences = function() {
+        var key = null, param, prop = null, val, ref, subst, isReq = "request" === this.contextName;
+        for (key in context) {
+            if (key) {
+                param = context[key];
+                if (param != null && typeof param === "object") {
+                    if (!(param instanceof thymol.ThVarsAccessor) && !(param instanceof thymol.ThClass)) {
+                        if (!(param instanceof thymol.ThParam)) {
+                            if (isReq && Object.prototype.toString.call(param) === "[object Array]") {
+                                for (var i = 0, iLimit = param.length; i < iLimit; i++) {
+                                    var pi = param[i];
+                                    if (!!pi && typeof pi.value === "string" && pi.value.charAt(0) == "#") {
+                                        var pv = thymol.ThUtils.getParameter(pi.value.substring(1));
+                                        param[i] = pv;
+                                    }
+                                }
+                            } else {
+                                for (prop in param) {
+                                    if (prop) {
+                                        val = param[prop];
+                                        if (typeof val === "string") {
+                                            if (val.indexOf(this.varNamePrefix) == 0) {
+                                                subst = null;
+                                                if (prop.match(/\d*/)) {
+                                                    ref = val.substring(this.varNamePrefix.length, val.length - 1);
+                                                    ref = this.varAccessor.get(ref);
+                                                    subst = context[ref.name];
+                                                } else {
+                                                    subst = context[prop];
+                                                }
+                                                param[prop] = subst;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        } else if (typeof param.value === "string" && param.value.charAt(0) == "#") {
+                            subst = context[param.value.substring(1)];
+                            context[key] = subst;
+                        }
+                    }
+                }
+            }
+        }
+    };
+    return context;
+};
+
+thymol.ThUtils = function() {
+    function mergeVars(thiz, other) {
+        var current = thiz, prop = null;
+        if (!current) {
+            current = {};
+        }
+        for (prop in other) {
+            if (other.hasOwnProperty(prop)) {
+                if (prop) {
+                    if (!current[prop]) {
+                        current[prop] = other[prop];
+                    }
+                }
+            }
+        }
+        return current;
+    }
+    function processElement(func, element, arg, obj) {
+        var result = null, parent = element.parentElement;
+        if (!thymol.isFragmentChild(element)) {
+            if (!element.thObjectVar) {
+                parent = element.parentElement;
+                while (parent) {
+                    if (parent.thObjectVar) {
+                        element.thObjectVar = parent.thObjectVar;
+                        break;
+                    }
+                    parent = parent.parentElement;
+                }
+            }
+            parent = element.parentElement;
+            while (parent) {
+                if (parent.thLocalVars) {
+                    element.thLocalVars = mergeVars(element.thLocalVars, parent.thLocalVars);
+                    break;
+                }
+                parent = parent.parentElement;
+            }
+            result = func(element, arg, obj);
+        }
+        return result;
+    }
+    function unQuote(param) {
+        var par = param, pared;
+        if (par) {
+            if (typeof par === "string") {
+                par = par.trim();
+                if (par.charAt(0) == '"') {
+                    if (par.charAt(par.length - 1) == '"') {
+                        pared = par.substring(1, par.length - 1);
+                        if (pairParity(pared, '"', '"') == 0) {
+                            par = pared;
+                        }
+                    }
+                } else if (par.charAt(0) == "'") {
+                    if (par.charAt(par.length - 1) == "'") {
+                        pared = par.substring(1, par.length - 1);
+                        if (pairParity(pared, "'", "'") == 0) {
+                            par = pared;
+                        }
+                    }
+                }
+            }
+        }
+        return par;
+    }
+    function unParenthesise(param) {
+        var par = param, pared;
+        if (par) {
+            if (typeof par === "string") {
+                par = par.trim();
+                if (par.charAt(0) == "(") {
+                    if (par.charAt(par.length - 1) == ")") {
+                        pared = par.substring(1, par.length - 1).trim();
+                        if (pairParity(pared, "(", ")") == 0) {
+                            par = pared;
+                        }
+                    }
+                }
+            }
+        }
+        return par;
+    }
+    function pairParity(str, left, right) {
+        var i, ch, strLength = str.length, parity = 0;
+        for (i = 0; i < strLength; i++) {
+            ch = str.charAt(i);
+            if (ch == left) {
+                parity++;
+            } else if (ch == right) {
+                parity--;
+                if (parity < 0) {
+                    break;
+                }
+            }
+        }
+        return parity;
+    }
+    function unBracket(param) {
+        var par = param, pared;
+        if (typeof par === "string") {
+            par = par.trim();
+        }
+        if (par) {
+            if (par.charAt(0) == "[") {
+                if (par.charAt(par.length - 1) == "]") {
+                    pared = par.substring(1, par.length - 1);
+                    if (pairParity(pared, "[", "]") == 0) {
+                        par = pared;
+                    }
+                }
+            }
+        }
+        return par;
+    }
+    function getToPrecision(n, p) {
+        if (typeof p === "undefined") {
+            return n;
+        }
+        var up = thymol.thDefaultPrecision, ndp = 0, s, sl, dp, v;
+        if (p > up) {
+            up = p;
+        } else {
+            s = n.toString();
+            sl = s.length;
+            dp = s.indexOf(".");
+            if (dp >= 0) {
+                ndp = sl - 1 - dp;
+            }
+            if (ndp > up) {
+                v = n.toPrecision(ndp + 1);
+                v = truncateDecimals(v);
+                s = v.toString();
+                sl = s.length;
+                if (dp >= 0) {
+                    ndp = sl - 1 - dp;
+                }
+            }
+            if (p > ndp) {
+                up = p;
+            } else if (ndp < up) {
+                up = ndp;
+            }
+        }
+        v = parseFloat(n);
+        v = v.toFixed(up);
+        if (p === 0) {
+            v = Number(v);
+        }
+        return v;
+    }
+    function truncateDecimals(valp) {
+        var val = valp, iLimit = valp.length - 1, i;
+        for (i = iLimit; i >= 0; i--) {
+            if (val.charAt(i) === "0") {
+                val = val.substr(0, i);
+            } else {
+                break;
+            }
+        }
+        return val;
+    }
+    function getDecimalDigits(val) {
+        var digits = 0, s, dp;
+        s = val.toString();
+        dp = s.indexOf(".") + 1;
+        if (dp > 0) {
+            digits = s.length - dp;
+        }
+        return digits;
+    }
+    function testLiteralFalse(initial) {
+        var result = false, val;
+        if (typeof initial === "string") {
+            val = initial.toLowerCase();
+            result = val == "false" || val == "off" || val == "no";
+        } else if (typeof initial === "boolean") {
+            result = !initial;
+        }
+        return result;
+    }
+    function renderMessage(msg, values) {
+        var result = msg, i, iLimit;
+        if (Object.prototype.toString.call(values) == "[object Array]") {
+            for (i = 0, iLimit = values.length; i < iLimit; i++) {
+                result = renderMessageArg(result, i, values[i]);
+            }
+        } else {
+            result = renderMessageArg(msg, 0, values);
+        }
+        return result;
+    }
+    function renderMessageArg(msg, index, value) {
+        var result = msg, splits, i, iLimit, iUpper;
+        splits = msg.split("{" + index + "}");
+        if (splits.length > 0) {
+            result = "";
+            for (i = 0, iLimit = splits.length, iUpper = iLimit - 1; i < iLimit; i++) {
+                result += splits[i];
+                if (i < iUpper) {
+                    result += value;
+                }
+            }
+        }
+        return result;
+    }
+    function getParameter(name) {
+        var result, tor;
+        result = thymol.requestContext[name];
+        tor = typeof result;
+        if (tor === "undefined") {
+            result = thymol.sessionContext[name];
+            if (typeof result === "undefined") {
+                result = thymol.applicationContext[name];
+            }
+        } else if (tor === "object") {
+            if (Object.prototype.toString.call(result) === "[object Array]") {
+                if (result.length === 1) {
+                    result = result[0];
+                }
+            }
+        }
+        return result;
+    }
+    function charOcurrences(str, chr) {
+        var count = 0, i = 0, iLimit = str.length;
+        for (;i < iLimit; i++) {
+            if (str.charAt(i) === chr) {
+                count++;
+            }
+        }
+        return count;
+    }
+    function isLiteral(val) {
+        var first, last;
+        if (typeof val === "string") {
+            first = val.charAt(0);
+            last = val.charAt(val.length - 1);
+            if (first == "'" && last == "'") {
+                return true;
+            }
+            if (first == '"' && last == '"') {
+                return true;
+            }
+        }
+        return false;
+    }
+    function isLiteralSubst(param) {
+        var result = false, par = param;
+        if (typeof par === "string") {
+            par = par.trim();
+        }
+        if (par) {
+            if (par.charAt(0) == "|") {
+                if (par.charAt(par.length - 1) == "|") {
+                    result = true;
+                }
+            }
+        }
+        return result;
+    }
+    function loadScript(file) {
+        var script = thymol.Thymol.prototype.getFilePath(file);
+        var status = "";
+        var jqxhr = $.ajax({
+            type: "GET",
+            url: script,
+            dataType: "script",
+            cache: true,
+            async: false
+        }).done(function() {
+            status = "success";
+        }).fail(function() {
+            status = "error";
+        });
+    }
+    function unescape(text) {
+        var result = text, i, iLimit, iUpper, c, cc;
+        if (text !== null && typeof text !== "undefined") {
+            result = "";
+            iLimit = text.length;
+            iUpper = iLimit - 3;
+            for (i = 0; i < iLimit; i++) {
+                c = text.charAt(i);
+                if (i < iUpper) {
+                    if (c === "&") {
+                        cc = text.charAt(i + 1).toLowerCase();
+                        if ((cc === "g" || cc === "l") && text.charAt(i + 2).toLowerCase() === "t" && text.charAt(i + 3) === ";") {
+                            i += 3;
+                            if (cc === "g") {
+                                c = ">";
+                            } else {
+                                c = "<";
+                            }
+                        } else if (i < iUpper - 1 && cc === "a" && text.charAt(i + 2).toLowerCase() === "m" && text.charAt(i + 3).toLowerCase() === "p" && text.charAt(i + 4) === ";") {
+                            i += 4;
+                        } else if (i < iUpper - 2) {
+                            if (cc === "q" && text.charAt(i + 2).toLowerCase() === "u" && text.charAt(i + 3).toLowerCase() === "o" && text.charAt(i + 4).toLowerCase() === "t" && text.charAt(i + 5) === ";") {
+                                i += 5;
+                                c = '"';
+                            } else if (cc === "a" && text.charAt(i + 2).toLowerCase() === "p" && text.charAt(i + 3).toLowerCase() === "o" && text.charAt(i + 4).toLowerCase() === "s" && text.charAt(i + 5) === ";") {
+                                i += 5;
+                                c = "'";
+                            }
+                        }
+                    }
+                }
+                result += c;
+            }
+        }
+        return result;
+    }
+    function unicodeUnescape(initial) {
+        var result = initial.replace(/\\u([\da-f]{4})/gi, function(match, grp) {
+            return String.fromCharCode(parseInt(grp, 16));
+        });
+        result = unescape(result);
+        return result;
+    }
+    function removeTag(element) {
+        var parent = element.parentNode, i, iLimit, savedObject = element.thObjectVar, savedLocals = element.thLocalVars;
+        if (!!parent) {
+            for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
+                var newNode = element.childNodes[i].cloneNode(true);
+                if (newNode.nodeType === 1) {
+                    if (!!savedObject) {
+                        newNode.thObjectVar = savedObject;
+                    }
+                    if (!!savedLocals) {
+                        newNode.thLocalVars = savedLocals;
+                    }
+                }
+                parent.insertBefore(newNode, element);
+            }
+            parent.removeChild(element);
+        }
+    }
+    function getRequestEncoded(initial) {
+        var result = initial;
+        result = encodeURIComponent(result);
+        result = result.replace(/%20/g, "+");
+        result = result.replace(/%26/g, "&");
+        result = result.replace(/%3A/g, ":");
+        result = result.replace(/!/g, "%21");
+        result = result.replace(/'/g, "%27");
+        result = result.replace(/\(/g, "%28");
+        result = result.replace(/\)/g, "%29");
+        result = result.replace(/\*/g, "%2A");
+        result = result.replace(/~/g, "%7E");
+        return result;
+    }
+    return {
+        getParameter: getParameter,
+        processElement: processElement,
+        unQuote: unQuote,
+        unParenthesise: unParenthesise,
+        unBracket: unBracket,
+        getToPrecision: getToPrecision,
+        getDecimalDigits: getDecimalDigits,
+        testLiteralFalse: testLiteralFalse,
+        renderMessage: renderMessage,
+        charOcurrences: charOcurrences,
+        isLiteral: isLiteral,
+        isLiteralSubst: isLiteralSubst,
+        loadScript: loadScript,
+        unescape: unescape,
+        unicodeUnescape: unicodeUnescape,
+        removeTag: removeTag,
+        getRequestEncoded: getRequestEncoded
+    };
+}();
+
+thymol.ThParser = function(scope) {
+    function object(o) {
+        function F() {}
+        F.prototype = o;
+        return new F();
+    }
+    function NullReturn(varName) {
+        this.varName = varName;
+    }
+    var TNUMBER = 0;
+    var TOP1 = 1;
+    var TOP2 = 2;
+    var TVAR = 3;
+    var TFUNCALL = 4;
+    var MSGSUBST = 5;
+    var ARGLIST = 6;
+    function Token(type_p, index_p, prio_p, number_p, mode_p, meta_p) {
+        this.type_ = type_p;
+        this.index_ = index_p || 0;
+        this.prio_ = prio_p || 0;
+        this.number_ = number_p !== undefined && number_p !== null ? number_p : 0;
+        this.mode_ = mode_p !== undefined && mode_p !== null ? mode_p : 0;
+        this.meta_ = meta_p;
+        this.toString = function() {
+            switch (this.type_) {
+              case TNUMBER:
+                return this.number_;
+
+              case TOP1:
+              case TOP2:
+              case TVAR:
+                return this.index_;
+
+              case TFUNCALL:
+              case MSGSUBST:
+              case ARGLIST:
+                return "CALL";
+
+              default:
+                return "Invalid Token";
+            }
+        };
+    }
+    function Expression(tokens, ops1, ops2, functions, precision, position) {
+        this.tokens = tokens;
+        this.ops1 = ops1;
+        this.ops2 = ops2;
+        this.functions = functions;
+        this.precision = precision;
+        this.position = position;
+    }
+    Expression.prototype = {
+        simplify: function(valuesParam) {
+            var values = valuesParam || {};
+            var nstack = [];
+            var newexpression = [];
+            var n1;
+            var n2;
+            var f;
+            var L = this.tokens.length;
+            var item;
+            var i = 0;
+            for (i = 0; i < L; i++) {
+                item = this.tokens[i];
+                var type_ = item.type_;
+                if (type_ === TNUMBER) {
+                    nstack.push(item);
+                } else if (type_ === TVAR && !(item.index_ in new Object()) && item.index_ in values) {
+                    item = new Token(TNUMBER, 0, 0, values[item.index_]);
+                    nstack.push(item);
+                } else if (type_ === TOP2 && nstack.length > 1) {
+                    f = this.ops2[item.index_];
+                    if (!!f) {
+                        n2 = nstack.pop();
+                        n1 = nstack.pop();
+                        item = new Token(TNUMBER, 0, 0, f(n1.number_, n2.number_));
+                    }
+                    nstack.push(item);
+                } else if (type_ === TOP1 && nstack.length > 0) {
+                    if ("{" == item.index_) {
+                        if (item.mode_ == 2) {
+                            nstack.push(item);
+                        }
+                    } else {
+                        n1 = nstack.pop();
+                        f = this.ops1[item.index_];
+                        item = new Token(TNUMBER, 0, 0, f(n1.number_));
+                        nstack.push(item);
+                    }
+                } else {
+                    while (nstack.length > 0) {
+                        newexpression.push(nstack.shift());
+                    }
+                    newexpression.push(item);
+                }
+            }
+            while (nstack.length > 0) {
+                newexpression.push(nstack.shift());
+            }
+            var res = new Expression(newexpression, object(this.ops1), object(this.ops2), object(this.functions), this.precision);
+            return res;
+        },
+        evaluate: function(element) {
+            var nstack = [];
+            var n1;
+            var n2;
+            var f;
+            var res = null;
+            var L = this.tokens.length;
+            var item;
+            var i = 0;
+            var result;
+            for (i = 0; i < L; i++) {
+                item = this.tokens[i];
+                if (i === 0 && thymol.disableMessages && item.mode_ === 4) {
+                    var nullReturn = new thymol.ThClass();
+                    nullReturn.abort = true;
+                    return nullReturn;
+                }
+                var type_ = item.type_;
+                if (type_ === TNUMBER) {
+                    nstack.push(item.number_);
+                    if (i == L - 1) {
+                        break;
+                    }
+                } else if (type_ === TOP2) {
+                    n2 = nstack.pop();
+                    if (typeof n2 === "undefined" || n2 instanceof NullReturn) {
+                        n2 = null;
+                    }
+                    n1 = nstack.pop();
+                    if (typeof n1 === "undefined" || n1 instanceof NullReturn) {
+                        n1 = null;
+                    }
+                    f = this.ops2[item.index_];
+                    var pathMatch = false;
+                    try {
+                        if (item.mode_ === 6) {
+                            if (f === dot) {
+                                res = n1 + "[" + n2 + "]";
+                            } else if (f === append) {
+                                if (!!item.meta_) {
+                                    if (!!item.meta_.paths) {
+                                        var values = item.meta_.paths[n1];
+                                        if (!!values) {
+                                            values.push(n2);
+                                            pathMatch = true;
+                                            res = null;
+                                        }
+                                    }
+                                }
+                                if (!pathMatch) {
+                                    if (!item.meta_) {
+                                        item.meta_ = {};
+                                    }
+                                    if (!item.meta_.params) {
+                                        item.meta_.params = [];
+                                    }
+                                    var values = item.meta_.params[n1];
+                                    if (!values) {
+                                        values = [];
+                                        item.meta_.params[n1] = values;
+                                    }
+                                    values.push(n2);
+                                    pathMatch = true;
+                                }
+                            } else {
+                                res = n2;
+                                nstack.push(n1);
+                            }
+                        } else {
+                            if (f === dot && "class" === n2 && !!n1 && !n1["class"]) {
+                                var tn2 = typeof n2;
+                                if (tn2 === "object" && n2 instanceof thymol.ThParam) {
+                                    res = f(n1, n2);
+                                } else {
+                                    res = new thymol.ThClass("JavaScript:" + tn2);
+                                }
+                            } else {
+                                res = f(n1, n2);
+                                if (typeof res === "function") {
+                                    if (L - 1 > i) {
+                                        next = this.tokens[i + 1];
+                                        if (next.type_ === TNUMBER && Object.prototype.toString.call(next.number_) == "[object Array]" && next.number_.length == 0) {
+                                            i += 1;
+                                            nstack.push(res);
+                                            n1.isDirect = true;
+                                            res = n1;
+                                        }
+                                    }
+                                }
+                            }
+                            if (f !== append) {
+                                if (Object.prototype.toString.call(res) == "[object Array]") {
+                                    res.arrayResult = true;
+                                }
+                            }
+                        }
+                    } catch (err) {
+                        if (!element.isBlockChild) {
+                            var aValue = n1 == null ? "null" : n1;
+                            var bValue = n2 == null ? "null" : n2;
+                            var message = "while evaluating expression: " + this.tokens[i - 2].index_ + ": " + aValue + ", " + this.tokens[i - 1].index_ + ": " + bValue;
+                            throw new thymol.ThError(message, element, err);
+                        }
+                    }
+                    if (!pathMatch) {
+                        nstack.push(res);
+                    }
+                } else if (type_ === TVAR) {
+                    var next = null, pushed = nstack.length;
+                    if (item.index_ != null) {
+                        if (L - 1 > i) {
+                            next = this.tokens[i + 1];
+                            if (next.type_ === TOP2 && next.index_ === ".") {
+                                nstack.push(item.index_);
+                            }
+                        }
+                        if (pushed === nstack.length) {
+                            var val = thymol.substituteParam(item.index_, item.mode_, element);
+                            if (Object.prototype.toString.call(val) == "[object Array]") {
+                                val.arrayResult = true;
+                            }
+                            this.updatePrecision(val);
+                            if (val === null) {
+                                val = new NullReturn(item.index_);
+                            }
+                            nstack.push(val);
+                        }
+                    } else if (pushed === nstack.length && item.index_ in this.functions) {
+                        nstack.push(this.functions[item.index_]);
+                    } else {
+                        if (!element.isBlockChild) {
+                            throw new thymol.ThError("Exception undefined variable: " + item.index_, element);
+                        }
+                    }
+                } else if (type_ === TOP1) {
+                    n1 = nstack.pop();
+                    if (typeof n1 === "undefined" || n1 instanceof NullReturn) {
+                        if (item.mode_ === 2) {
+                            n1 = "";
+                        } else {
+                            n1 = null;
+                        }
+                    }
+                    res = n1;
+                    if ("{" === item.index_) {
+                        var prev = this.tokens[i - 1];
+                        if (prev.mode_ == 7) {
+                            if (thymol.conversionService) {
+                                n1 = thymol.conversionService(n1);
+                                res = n1;
+                            }
+                        }
+                        if (typeof n1 === "string") {
+                            if (item.mode_ === 2) {
+                                res = thymol.getStandardURL(n1);
+                            } else {
+                                var subst = thymol.substituteParam(n1, item.mode_, element);
+                                if (subst != null) {
+                                    this.updatePrecision(subst);
+                                    res = subst;
+                                }
+                            }
+                        }
+                    } else {
+                        f = this.ops1[item.index_];
+                        try {
+                            res = f(n1);
+                        } catch (err) {
+                            if (!element.isBlockChild) {
+                                var aValue = n1 == null ? "null" : n1;
+                                var message = "while evaluating expression: " + this.tokens[i - 2].index_ + ": " + aValue;
+                                throw new thymol.ThError(message, element, err);
+                            }
+                        }
+                    }
+                    if (Object.prototype.toString.call(res) == "[object Array]") {
+                        res.arrayResult = true;
+                    }
+                    nstack.push(res);
+                } else if (type_ === TFUNCALL || type_ === MSGSUBST || type_ === ARGLIST) {
+                    n1 = nstack.pop();
+                    f = nstack.pop();
+                    if (type_ === MSGSUBST) {
+                        if (f instanceof NullReturn) {
+                            res = "??" + f.varName + "_" + thymol.locale.value + "??";
+                        } else {
+                            res = thymol.ThUtils.renderMessage(f, n1);
+                        }
+                        nstack.push(res);
+                    } else if (type_ === ARGLIST) {
+                        var pathMatch = false;
+                        n2 = nstack.pop();
+                        if (typeof n2 === "undefined") {
+                            n2 = f;
+                            f = n1;
+                            n1 = "";
+                        }
+                        if (!!item.meta_) {
+                            if (!!item.meta_.paths) {
+                                var values = item.meta_.paths[f];
+                                if (!!values) {
+                                    values.push(n1);
+                                    pathMatch = true;
+                                }
+                                for (var j in item.meta_.paths) {
+                                    if (item.meta_.paths.hasOwnProperty(j)) {
+                                        var values = item.meta_.paths[j];
+                                        var isReq = n2.indexOf("?") >= 0;
+                                        if (!!values && values.length > 0) {
+                                            var pathVar = "{" + j + "}";
+                                            var repReg = new RegExp(pathVar, "g");
+                                            var rep = "";
+                                            values.reverse();
+                                            for (var k = 0, kLimit = values.length; k < kLimit; k++) {
+                                                if (rep.length > 0) {
+                                                    rep = rep + ",";
+                                                }
+                                                if (isReq) {
+                                                    rep = rep + thymol.ThUtils.getRequestEncoded(values[k]);
+                                                } else {
+                                                    rep = rep + encodeURIComponent(values[k]);
+                                                }
+                                            }
+                                            n2 = n2.replace(repReg, rep);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (pathMatch) {
+                            res = n2;
+                        } else {
+                            if (typeof f === "undefined" || f instanceof NullReturn) {
+                                f = "";
+                            } else {
+                                f = f.toString();
+                            }
+                            f = thymol.ThUtils.getRequestEncoded(f);
+                            f = "?" + f;
+                            n1 = n1.toString();
+                            if (f != "?" && n1 != "") {
+                                f = f + "=";
+                            }
+                            if (n1 != "") {
+                                n1 = thymol.ThUtils.getRequestEncoded(n1);
+                                f = f + n1;
+                            }
+                            if (typeof n2 === "undefined" || n2 instanceof NullReturn) {
+                                n2 = "";
+                            } else {
+                                n2 = n2.toString();
+                            }
+                            res = n2 + f;
+                        }
+                        if (!!item.meta_) {
+                            var separator = res.indexOf("?") >= 0 ? "&" : "?";
+                            for (var j in item.meta_.params) {
+                                if (item.meta_.params.hasOwnProperty(j)) {
+                                    var values = item.meta_.params[j];
+                                    if (!!values && values.length > 0) {
+                                        for (var k = 0, kLimit = values.length; k < kLimit; k++) {
+                                            res = res + separator + thymol.ThUtils.getRequestEncoded(j) + "=" + thymol.ThUtils.getRequestEncoded(values[k]);
+                                            if (k == 0) {
+                                                separator = "&";
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                            if (!!item.meta_.urlFragment) {
+                                res = res + item.meta_.urlFragment;
+                            }
+                        }
+                        nstack.push(res);
+                    } else if (f.apply && f.call) {
+                        if (!!n1 && !!n1.isDirect) {
+                            res = f.call(n1);
+                        } else {
+                            if (n1 instanceof NullReturn) {
+                                n1 = null;
+                            }
+                            if (n1 != null && (n1.arrayResult || Object.prototype.toString.call(n1) !== "[object Array]")) {
+                                res = f.call(element, n1);
+                            } else {
+                                res = f.apply(element, n1);
+                            }
+                        }
+                        if (res instanceof String) {
+                            if (res.precision) {
+                                if (typeof this.precision === "undefined" || res.precision > this.precision) {
+                                    this.precision = res.precision;
+                                }
+                            }
+                            res = res.toString();
+                        } else if (Object.prototype.toString.call(res) == "[object Array]") {
+                            res.arrayResult = true;
+                        }
+                        nstack.push(res);
+                    } else {
+                        if (!element.isBlockChild) {
+                            throw new thymol.ThError(f + " is not a function", element);
+                        }
+                    }
+                } else {
+                    if (!element.isBlockChild) {
+                        throw new thymol.ThError("invalid expression item type: " + type_, element);
+                    }
+                }
+            }
+            if (nstack.length > 1) {
+                if (!element.isBlockChild) {
+                    throw new thymol.ThError("invalid Expression (parity)", element);
+                }
+            }
+            result = nstack[0];
+            return result;
+        },
+        updatePrecision: function(val) {
+            if (typeof val === "number") {
+                var p = thymol.ThUtils.getDecimalDigits(val);
+                if (typeof this.precision === "undefined" || p > this.precision) {
+                    this.precision = p;
+                }
+            }
+        }
+    };
+    function add(a, b) {
+        return a + b;
+    }
+    function assign(a) {
+        return a;
+    }
+    function sub(a, b) {
+        return a - b;
+    }
+    function mul(a, b) {
+        return a * b;
+    }
+    function div(a, b) {
+        return a / b;
+    }
+    function mod(a, b) {
+        return a % b;
+    }
+    function concat(a, b) {
+        return "" + a + b;
+    }
+    function neg(a) {
+        return -a;
+    }
+    function not(a) {
+        var v = thymol.getBooleanValue(a);
+        return !v;
+    }
+    function random(a) {
+        return Math.random() * (a || 1);
+    }
+    function fac(a) {
+        var aa = Math.floor(a);
+        var b = aa;
+        while (aa > 1) {
+            b = b * --aa;
+        }
+        return b;
+    }
+    function append(a, b) {
+        if (a != null) {
+            if (a.arrayResult === true || Object.prototype.toString.call(a) != "[object Array]") {
+                return [ a, b ];
+            }
+        } else {
+            if (b != null) {
+                if (b.arrayResult === true || Object.prototype.toString.call(b) != "[object Array]") {
+                    return [ a, b ];
+                }
+                return b;
+            }
+            return null;
+        }
+        var aa = a.slice();
+        aa.push(b);
+        return aa;
+    }
+    function equal(a, b) {
+        return a == b;
+    }
+    function notEqual(a, b) {
+        return a != b;
+    }
+    function gt(a, b) {
+        return a > b;
+    }
+    function ge(a, b) {
+        return a >= b;
+    }
+    function lt(a, b) {
+        return a < b;
+    }
+    function le(a, b) {
+        return a <= b;
+    }
+    function and(a, b) {
+        return a && b;
+    }
+    function or(a, b) {
+        return a || b;
+    }
+    function dot(a, b) {
+        return a[b];
+    }
+    function binary(a, b) {
+        return a ? b : null;
+    }
+    function elvis(a, b) {
+        return a != null ? a : b;
+    }
+    function getStr(pos, expression, mode, partial, preprocessed) {
+        var localMode = mode;
+        var s = "";
+        var c = expression.charAt(pos);
+        var start = pos + 1;
+        var end = expression.length;
+        var stopChar = c;
+        if (localMode === 4 || c === "#") {
+            stopChar = "}";
+            localMode = 4;
+        }
+        var i = start;
+        var inCurly = false;
+        var curlyPos = null;
+        var urlFragPos = -1;
+        var meta = null;
+        if (localMode !== 4 && c !== "'" && c !== '"') {
+            for (;i <= end; i++) {
+                if (c.toUpperCase() === c.toLowerCase()) {
+                    if (c === "{") {
+                        inCurly = true;
+                        curlyPos = i;
+                        if (meta === null) {
+                            meta = {};
+                            meta.paths = [];
+                        }
+                    } else if (mode === 2 && c === "#") {
+                        urlFragPos = i;
+                    }
+                    if (i === pos || !inCurly && c === "}" || c !== "_" && c !== "?" && c !== ":" && (c < "0" || c > "9")) {
+                        if (!(partial && c == "-") && !((mode === 2 || mode === 6) && (c === "/" || c === "." || c === "~" || c === "?" || c === "=" || c === ":" || c === "-" || c === "_" || c === "[" || c === "]" || c === "#" || inCurly && c === "{" || inCurly && c === "}")) || mode === 6 && c === "=") {
+                            i = i - 1;
+                            break;
+                        }
+                    }
+                    if (inCurly && c === "}") {
+                        inCurly = false;
+                        if (meta === null) {
+                            var message = 'bad path variable definition in expression: "' + expression + '" near column ' + pos;
+                            throw new thymol.ThError(message, element);
+                        }
+                        var curlyVar = expression.substring(curlyPos, i - 1);
+                        var values = [];
+                        meta.paths[curlyVar] = values;
+                    }
+                }
+                s += c;
+                c = expression.charAt(i);
+            }
+            if (urlFragPos >= 0) {
+                var urlFrag = expression.substring(urlFragPos - 1, i);
+                s = s.substring(0, s.length - urlFrag.length);
+                if (meta === null) {
+                    meta = {};
+                    meta.urlFragment = urlFrag;
+                }
+            }
+        } else {
+            var quoted = false;
+            var preprocessing = false;
+            if (c === "'" || c === '"') {
+                quoted = true;
+                stopChar = c;
+            }
+            while (i <= end) {
+                if (c === stopChar && i > start && !preprocessing) {
+                    if (localMode !== 4 || quoted) {
+                        s += c;
+                    } else {
+                        i = i - 1;
+                    }
+                    break;
+                }
+                var nc = expression.charAt(i);
+                if (c === "_" && nc === "_" && !preprocessed) {
+                    preprocessing = !preprocessing;
+                }
+                if (c === "\\") {
+                    if (nc === "'" && s.charAt(s.length - 1) !== "\\") {
+                        c = "&#39;";
+                        if (i + 1 > end) {
+                            break;
+                        }
+                        i = i + 1;
+                        nc = expression.charAt(i);
+                    }
+                }
+                if (!quoted) {
+                    if (c === ".") {
+                        var exp = thymol.thExpressionObjects[s];
+                        if (typeof exp !== "undefined" && exp !== null) {
+                            i -= 1;
+                            break;
+                        }
+                    }
+                    if (c === "(") {
+                        i -= 1;
+                        break;
+                    }
+                }
+                s += c;
+                if (i + 1 > end) {
+                    break;
+                }
+                i = i + 1;
+                c = nc;
+            }
+        }
+        var str = new Object();
+        str.str = s;
+        str.pos = i;
+        if (meta !== null) {
+            str.meta = meta;
+        }
+        return str;
+    }
+    function ThParser() {
+        this.precision;
+        this.success = false;
+        this.errormsg = "";
+        this.expression = "";
+        this.pos = 0;
+        this.tokennumber = 0;
+        this.tokenprio = 0;
+        this.tokenindex = 0;
+        this.tmpprio = 0;
+        this.ops1 = {
+            sin: Math.sin,
+            cos: Math.cos,
+            tan: Math.tan,
+            asin: Math.asin,
+            acos: Math.acos,
+            atan: Math.atan,
+            sqrt: Math.sqrt,
+            log: Math.log,
+            abs: Math.abs,
+            ceil: Math.ceil,
+            floor: Math.floor,
+            round: Math.round,
+            "-": neg,
+            "!": not,
+            not: not,
+            exp: Math.exp,
+            "=": assign
+        };
+        this.ops2 = {
+            "?": binary,
+            ":": elvis,
+            "?:": elvis,
+            "+": add,
+            "-": sub,
+            "*": mul,
+            "/": div,
+            "%": mod,
+            "^": Math.pow,
+            ",": append,
+            "||": concat,
+            "==": equal,
+            eq: equal,
+            "!=": notEqual,
+            ne: notEqual,
+            neq: notEqual,
+            div: div,
+            mod: mod,
+            and: and,
+            or: or,
+            ">": gt,
+            gt: gt,
+            ">=": ge,
+            "=>": ge,
+            ge: ge,
+            "<": lt,
+            lt: lt,
+            "<=": le,
+            "=<": le,
+            le: le,
+            ".": dot,
+            "[": dot
+        };
+        this.functions = {
+            random: random,
+            fac: fac,
+            min: Math.min,
+            max: Math.max,
+            pow: Math.pow
+        };
+        this.consts = {
+            E: Math.E,
+            PI: Math.PI
+        };
+    }
+    ThParser.parse = function(expr, partial, preprocessed) {
+        return new thymol.ThParser().parse(expr, partial, preprocessed);
+    };
+    ThParser.evaluate = function(expr, partial, element) {
+        return thymol.ThParser.parse(expr, partial, false).evaluate(element);
+    };
+    ThParser.Expression = Expression;
+    ThParser.values = {
+        sin: Math.sin,
+        cos: Math.cos,
+        tan: Math.tan,
+        asin: Math.asin,
+        acos: Math.acos,
+        atan: Math.atan,
+        sqrt: Math.sqrt,
+        log: Math.log,
+        abs: Math.abs,
+        ceil: Math.ceil,
+        floor: Math.floor,
+        round: Math.round,
+        random: random,
+        fac: fac,
+        exp: Math.exp,
+        min: Math.min,
+        max: Math.max,
+        pow: Math.pow,
+        E: Math.E,
+        PI: Math.PI
+    };
+    var PRIMARY = 1 << 0;
+    var OPERATOR = 1 << 1;
+    var FUNCTION = 1 << 2;
+    var LPAREN = 1 << 3;
+    var RPAREN = 1 << 4;
+    var COMMA = 1 << 5;
+    var SIGN = 1 << 6;
+    var CALL = 1 << 7;
+    var NULLARY_CALL = 1 << 8;
+    var LBRACK = 1 << 9;
+    var RBRACK = 1 << 10;
+    var LVARBRK = 1 << 11;
+    var RVARBRK = 1 << 11;
+    var OPTION = 1 << 12;
+    var ASSIGN = 1 << 13;
+    ThParser.prototype = {
+        parse: function(expr, partial, preprocessed) {
+            this.errormsg = "";
+            this.success = true;
+            var operstack = [];
+            var tokenstack = [];
+            var modestack = [];
+            this.tmpprio = 0;
+            var expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | OPERATOR | SIGN | OPTION;
+            var noperators = 0;
+            this.expression = expr;
+            this.pos = 0;
+            this.mode = 0;
+            while (this.pos < this.expression.length) {
+                if (this.isWhite()) {} else if (this.isOperator()) {
+                    if (this.isSign() && expected & SIGN) {
+                        if (this.isNegativeSign()) {
+                            this.tokenprio = 6;
+                            this.tokenindex = "-";
+                            noperators++;
+                            this.addfunc(tokenstack, operstack, TOP1);
+                        }
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                    } else if (this.isAssign() && expected & ASSIGN) {
+                        noperators++;
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                    } else if (this.isComment()) {} else {
+                        if (this.tokenindex == "!") {
+                            if ((expected & SIGN) === 0) {
+                                this.error_parsing(this.pos, "unexpected sign");
+                            }
+                            noperators += 1;
+                            this.addfunc(tokenstack, operstack, TOP1);
+                        } else {
+                            if ((expected & OPERATOR) === 0) {
+                                this.error_parsing(this.pos, "unexpected operator");
+                            }
+                            noperators += 2;
+                            this.addfunc(tokenstack, operstack, TOP2);
+                        }
+                        if (this.expression.charAt(this.pos - 1) === "[") {
+                            this.tmpprio += 20;
+                        }
+                        expected = PRIMARY | OPERATOR | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                    }
+                } else if (this.isNumber()) {
+                    if ((expected & PRIMARY) === 0) {
+                        this.error_parsing(this.pos, "unexpected number");
+                    }
+                    var token = new Token(TNUMBER, 0, 0, this.tokennumber);
+                    tokenstack.push(token);
+                    expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA;
+                } else if (this.isLeftParenth()) {
+                    if ((expected & LPAREN) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "("');
+                    }
+                    modestack.push(this.mode);
+                    if (expected & CALL) {
+                        noperators += 2;
+                        this.tokenprio = -2;
+                        this.tokenindex = -1;
+                        this.tmpprio += 2;
+                        var ft = TFUNCALL;
+                        if (this.mode === 4) {
+                            ft = MSGSUBST;
+                            this.mode = 5;
+                        } else if (this.mode === 2) {
+                            ft = ARGLIST;
+                            this.mode = 6;
+                            var url = tokenstack[tokenstack.length - 1];
+                            if (!url.meta_) {
+                                url.meta_ = {};
+                            }
+                            this.meta = url.meta_;
+                        } else {
+                            this.mode = 5;
+                        }
+                        this.addfunc(tokenstack, operstack, ft);
+                        this.tmpprio -= 2;
+                    }
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio += 10;
+                    }
+                    expected = PRIMARY | OPERATOR | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION | NULLARY_CALL;
+                } else if (this.isRightParenth()) {
+                    if (expected & NULLARY_CALL) {
+                        var token = new Token(TNUMBER, 0, 0, []);
+                        tokenstack.push(token);
+                    } else if ((expected & RPAREN) === 0) {
+                        this.error_parsing(this.pos, 'unexpected ")"');
+                    }
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio -= 10;
+                    }
+                    this.mode = modestack.pop();
+                    expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
+                } else if (this.isRightBracket()) {
+                    if ((expected & RBRACK) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "]"');
+                    }
+                    expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
+                } else if (this.isLeftVarBrk(modestack)) {
+                    if ((expected & LVARBRK) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "{"');
+                    }
+                    noperators += 1;
+                    this.addfunc(tokenstack, operstack, TOP1);
+                    expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                } else if (this.isRightVarBrk()) {
+                    if ((expected & RVARBRK) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "}"');
+                    }
+                    this.mode = modestack.pop();
+                    expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
+                } else if (this.isLeftCurly()) {
+                    if (this.mode == 1 || this.mode == 2 || this.mode == 3 || this.mode == 4) {
+                        modestack.push(this.mode);
+                        this.mode = 7;
+                    } else {
+                        this.error_parsing(this.pos, 'unexpected "{"');
+                    }
+                } else if (this.isRightCurly()) {
+                    if (this.mode == 7) {
+                        this.mode = modestack.pop();
+                    } else {
+                        this.error_parsing(this.pos, 'unexpected "}"');
+                    }
+                } else if (this.isComma()) {
+                    if ((expected & COMMA) === 0) {
+                        this.error_parsing(this.pos, 'unexpected ","');
+                    }
+                    if (!!partial) {
+                        break;
+                    }
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio -= 10;
+                    }
+                    this.tmpprio += 2;
+                    this.addfunc(tokenstack, operstack, TOP2);
+                    this.tmpprio -= 2;
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio += 10;
+                    }
+                    noperators += 2;
+                    expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                } else if (this.isConst()) {
+                    if ((expected & PRIMARY) === 0) {
+                        this.error_parsing(this.pos, "unexpected constant");
+                    }
+                    var consttoken = new Token(TNUMBER, 0, 0, this.tokennumber);
+                    tokenstack.push(consttoken);
+                    expected = OPERATOR | RPAREN | RVARBRK | RBRACK | COMMA;
+                } else {
+                    var str = getStr(this.pos, this.expression, this.mode, partial, preprocessed);
+                    if (this.isOpX(str, this.ops2) && (this.mode !== 2 && "/" !== str)) {
+                        if ("and" === str.str || "or" === str.str) {
+                            this.tokenprio = 3;
+                        }
+                        if ((expected & OPERATOR) === 0) {
+                            this.error_parsing(this.pos, "unexpected binary operator");
+                        }
+                        this.addfunc(tokenstack, operstack, TOP2);
+                        noperators += 2;
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | OPERATOR | SIGN | OPTION;
+                    } else if (this.isOpX(str, this.ops1)) {
+                        if ((expected & OPERATOR) === 0) {
+                            this.error_parsing(this.pos, "unexpected unary operator");
+                        }
+                        this.addfunc(tokenstack, operstack, TOP1);
+                        noperators++;
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION;
+                    } else if (this.isLiteralValue(str)) {
+                        if ((expected & PRIMARY) === 0) {
+                            this.error_parsing(this.pos, "unexpected literal value");
+                        }
+                        var token = new Token(TNUMBER, 0, 0, this.tokennumber);
+                        tokenstack.push(token);
+                        expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | RVARBRK | LBRACK | CALL | OPTION;
+                        if (this.mode === 6) {
+                            expected = expected | ASSIGN;
+                        }
+                    } else if (this.isVar(str)) {
+                        if ((expected & PRIMARY) === 0) {
+                            this.error_parsing(this.pos, "unexpected variable");
+                        }
+                        var vartoken = new Token(TVAR, this.tokenindex, 0, 0, this.mode, str.meta);
+                        tokenstack.push(vartoken);
+                        expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | RVARBRK | LBRACK | CALL | OPTION | ASSIGN;
+                    } else {
+                        if (this.errormsg === "") {
+                            this.error_parsing(this.pos, "unknown character");
+                        } else {
+                            this.error_parsing(this.pos, this.errormsg);
+                        }
+                    }
+                }
+            }
+            if (this.tmpprio < 0 || this.tmpprio >= 10) {
+                this.error_parsing(this.pos, 'unmatched "() or []"');
+            }
+            while (operstack.length > 0) {
+                var tmp = operstack.pop();
+                tokenstack.push(tmp);
+            }
+            if (noperators + 1 !== tokenstack.length) {
+                this.error_parsing(this.pos, "parity");
+            }
+            var res = new Expression(tokenstack, object(this.ops1), object(this.ops2), object(this.functions), this.precision, this.pos);
+            return res;
+        },
+        evaluate: function(expr, element) {
+            return this.parse(expr).evaluate(element);
+        },
+        error_parsing: function(column, msg) {
+            this.success = false;
+            this.errormsg = "parse error [column " + column + "]: " + msg;
+            throw new Error(this.errormsg);
+        },
+        addfunc: function(tokenstack, operstack, type_) {
+            var operator = new Token(type_, this.tokenindex, this.tokenprio + this.tmpprio, 0, this.mode, this.meta);
+            while (operstack.length > 0) {
+                if (operator.prio_ <= operstack[operstack.length - 1].prio_) {
+                    tokenstack.push(operstack.pop());
+                } else {
+                    break;
+                }
+            }
+            operstack.push(operator);
+        },
+        isNumber: function() {
+            var r = false;
+            var str = "";
+            var prec = -1;
+            while (this.pos < this.expression.length) {
+                var code = this.expression.charCodeAt(this.pos);
+                if (code >= 48 && code <= 57 || code === 46) {
+                    str += this.expression.charAt(this.pos);
+                    if (prec >= 0 || code === 46) {
+                        prec++;
+                    }
+                    this.pos++;
+                    r = true;
+                } else {
+                    break;
+                }
+            }
+            if (r) {
+                if (prec >= 0 && (typeof this.precision === "undefined" || prec > this.precision)) {
+                    this.precision = prec;
+                }
+                this.tokennumber = parseFloat(str);
+            }
+            return r;
+        },
+        isConst: function() {
+            var str;
+            for (var i in this.consts) {
+                if (true) {
+                    var L = i.length;
+                    str = this.expression.substr(this.pos, L);
+                    if (i === str) {
+                        this.tokennumber = this.consts[i];
+                        this.pos += L;
+                        return true;
+                    }
+                }
+            }
+            return false;
+        },
+        isOperator: function() {
+            var ch = this.expression.charAt(this.pos);
+            if (ch === "+") {
+                this.tokenprio = 0;
+                this.tokenindex = "+";
+            } else if (ch === "-") {
+                this.tokenprio = 0;
+                this.tokenindex = "-";
+            } else if (ch === "|") {
+                if (this.expression.charAt(this.pos + 1) === "|") {
+                    this.pos++;
+                    this.tokenprio = 0;
+                    this.tokenindex = "||";
+                } else {
+                    return false;
+                }
+            } else if (ch === "*") {
+                if (this.expression.charAt(this.pos + 1) === "{") {
+                    return false;
+                }
+                this.tokenprio = 1;
+                this.tokenindex = "*";
+            } else if (ch === "/" && this.mode != 2 && this.pos > 0) {
+                this.tokenprio = 2;
+                this.tokenindex = "/";
+            } else if (ch === "%") {
+                this.tokenprio = 2;
+                this.tokenindex = "%";
+            } else if (ch === "^") {
+                this.tokenprio = 3;
+                this.tokenindex = "^";
+            } else if (ch === "=" || ch === "!") {
+                if (this.expression.charAt(this.pos + 1) === "=") {
+                    if (ch === "=") {
+                        this.tokenindex = "==";
+                    } else if (ch === "!") {
+                        this.tokenindex = "!=";
+                    } else {
+                        return false;
+                    }
+                    this.pos++;
+                    this.tokenprio = 6;
+                } else if (ch === "!") {
+                    this.tokenprio = 7;
+                    this.tokenindex = "!";
+                } else if (ch === "=") {
+                    this.tokenindex = "=";
+                } else {
+                    return false;
+                }
+            } else if (ch === "<") {
+                if (this.expression.charAt(this.pos + 1) === "=") {
+                    this.tokenindex = "<=";
+                    this.pos++;
+                } else {
+                    this.tokenindex = "<";
+                }
+                this.tokenprio = 4;
+            } else if (ch === ">") {
+                if (this.expression.charAt(this.pos + 1) === "=") {
+                    this.tokenindex = ">=";
+                    this.pos++;
+                } else {
+                    this.tokenindex = ">";
+                }
+                this.tokenprio = 4;
+            } else if (ch === "." || ch === "[") {
+                this.tokenprio = 10;
+                this.tokenindex = ".";
+            } else {
+                return false;
+            }
+            this.pos++;
+            return true;
+        },
+        isRightBracket: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 93) {
+                this.pos++;
+                this.tmpprio -= 20;
+                return true;
+            }
+            return false;
+        },
+        isSign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 45 || code === 43) {
+                return true;
+            }
+            return false;
+        },
+        isAssign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 61) {
+                var cha = this.expression.charAt(this.pos - 2);
+                if (cha === "!" || cha === ">" || cha === "<" || cha === "=") {
+                    return false;
+                }
+                cha = this.expression.charAt(this.pos);
+                if (cha === ">" || cha === "<" || cha === "=") {
+                    return false;
+                }
+                return true;
+            }
+            return false;
+        },
+        isPositiveSign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 43) {
+                return true;
+            }
+            return false;
+        },
+        isNegativeSign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 45) {
+                return true;
+            }
+            return false;
+        },
+        isLeftParenth: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 40) {
+                this.pos++;
+                this.tmpprio += 10;
+                return true;
+            }
+            return false;
+        },
+        isRightParenth: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 41) {
+                this.pos++;
+                this.tmpprio -= 10;
+                return true;
+            }
+            return false;
+        },
+        isLeftCurly: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 123) {
+                this.pos++;
+                this.tmpprio += 10;
+                return true;
+            }
+            return false;
+        },
+        isRightCurly: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 125) {
+                this.pos++;
+                this.tmpprio -= 10;
+                return true;
+            }
+            return false;
+        },
+        isComma: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 44) {
+                this.pos++;
+                this.tokenprio = -1;
+                this.tokenindex = ",";
+                return true;
+            }
+            return false;
+        },
+        isWhite: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 32 || code === 9 || code === 10 || code === 13) {
+                this.pos++;
+                return true;
+            }
+            return false;
+        },
+        isLeftVarBrk: function(modestack) {
+            var pp = this.pos, ch = this.expression.charAt(pp);
+            if (ch === "$" || ch === "@" || ch === "*" || ch === "#") {
+                pp++;
+                var ch2 = this.expression.charAt(pp);
+                if (ch2 === "{") {
+                    pp++;
+                    this.tmpprio += 10;
+                    this.tokenprio = -4;
+                    var oldMode = this.mode;
+                    modestack.push(oldMode);
+                    if (ch === "$") {
+                        this.mode = 1;
+                    } else if (ch === "@") {
+                        this.mode = 2;
+                    } else if (ch === "*") {
+                        this.mode = 3;
+                    } else if (ch === "#") {
+                        this.mode = 4;
+                    }
+                    this.tokenindex = "{";
+                    this.pos = pp;
+                    return true;
+                }
+            }
+            return false;
+        },
+        isRightVarBrk: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 125) {
+                this.pos++;
+                this.tmpprio -= 10;
+                return true;
+            }
+            return false;
+        },
+        isOpX: function(str, group) {
+            if (str.str.length > 0) {
+                if (str.str in new Object()) {
+                    return false;
+                }
+                if (str.str in group) {
+                    this.tokenindex = str.str;
+                    this.tokenprio = 5;
+                    this.pos = str.pos;
+                    return true;
+                }
+            }
+            return false;
+        },
+        isLiteralValue: function(str) {
+            if (typeof str.str === "string") {
+                var first = str.str.charAt(0);
+                var last = str.str.charAt(str.str.length - 1);
+                if (first == "'" && last == "'" || first == '"' && last == '"') {
+                    this.tokennumber = str.str.substring(1, str.str.length - 1);
+                    this.pos = str.pos;
+                    return true;
+                }
+            }
+            return false;
+        },
+        isVar: function(str) {
+            if (str.str.length > 0) {
+                this.tokenindex = str.str;
+                this.tokenprio = 4;
+                this.pos = str.pos;
+                return true;
+            }
+            return false;
+        },
+        isComment: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 47 && this.expression.charCodeAt(this.pos) === 42) {
+                this.pos = this.expression.indexOf("*/", this.pos) + 2;
+                if (this.pos === 1) {
+                    this.pos = this.expression.length;
+                }
+                return true;
+            }
+            return false;
+        }
+    };
+    return ThParser;
+}();
+
+(function() {
+    var specAttrModList = [ "abbr", "accept", "accept-charset", "accesskey", "action", "align", "alt", "archive", "audio", "autocomplete", "axis", "background", "bgcolor", "border", "cellpadding", "cellspacing", "challenge", "charset", "cite", "class", "classid", "codebase", "codetype", "cols", "colspan", "compact", "content", "contenteditable", "contextmenu", "data", "datetime", "dir", "draggable", "dropzone", "enctype", "for", "form", "formaction", "formenctype", "formmethod", "formtarget", "frame", "frameborder", "headers", "height", "high", "href", "hreflang", "hspace", "http-equiv", "icon", "id", "keytype", "kind", "label", "lang", "list", "longdesc", "low", "manifest", "marginheight", "marginwidth", "max", "maxlength", "media", "method", "min", "name", "optimum", "pattern", "placeholder", "poster", "preload", "radiogroup", "rel", "rev", "rows", "rowspan", "rules", "sandbox", "scheme", "scope", "scrolling", "size", "sizes", "span", "spellcheck", "src", "srclang", "standby", "start", "step", "style", "summary", "tabindex", "target", "title", "type", "usemap", "value", "valuetype", "vspace", "width", "wrap", "xmlbase", "xmllang", "xmlspace" ];
+    var fixedValBoolAttrList = [ "async", "autofocus", "autoplay", "checked", "controls", "declare", "default", "defer", "disabled", "formnovalidate", "hidden", "ismap", "loop", "multiple", "novalidate", "nowrap", "open", "pubdate", "readonly", "required", "reversed", "scoped", "seamless", "selected" ];
+    var eventAttrList = [ "onabort", "onafterprint", "onbeforeprint", "onbeforeunload", "onblur", "oncanplay", "oncanplaythrough", "onchange", "onclick", "oncontextmenu", "ondblclick", "ondrag", "ondragend", "ondragenter", "ondragleave", "ondragover", "ondragstart", "ondrop", "ondurationchanged", "onemptied", "onended", "onerror", "onfocus", "onformchange", "onforminput", "onhashchange", "oninput", "oninvalid", "onkeydown", "onkeypress", "onkeyup", "onload", "onloadeddata", "onloadedmetadata", "onloadstart", "onmessage", "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onmousewheel", "onoffline", "ononline", "onpause", "onplay", "onplaying", "onpopstate", "onprogress", "onratechange", "onreadystatechange", "onredo", "onreset", "onresize", "onscroll", "onseeked", "onseeking", "onselect", "onshow", "onstalled", "onstorage", "onsubmit", "onsuspend", "ontimeupdate", "onundo", "onunload", "onvolumechange", "onwaiting" ];
+    var literalTokenExpr = /^[a-zA-Z0-9\[\]\.\-_]*$/;
+    var numericExpr = /^[+\-]?[0-9]*?[.]?[0-9]*?$/;
+    var nonURLExpr = /[\$\*#]{1}\{(?:!?[^}]*)\}/;
+    var varExpr = /[\$\*#@]{1}\{(!?[^}]*)\}/;
+    var textInlineCommentExpr = /\[\[(.*)\]\]/;
+    var javascriptInlineCommentExpr = /\/\*\[\[(.*)\]\]\*\//;
+    var javascriptInlineRemainderExpr = /\s*(?:['][^']*['])*(?:["][^"]*["])*(?:[\(][^\(\)]*[\)])*(?:[\{][^\{\}]*[\}])*(?:[\[][^\[\]]*[\]])*((?:[;,\(\)\[\]:\{\}](?=(?:\s*\/\/.*?(?:\n|$)))(?:\s*\/\/.*?(?:\n|$)))|(?:\s*\/\/.*?(?:\n|$))|(?:[;,\(\)\[\]:\{\}](?=(?:\s*(?:\n|$)))(?:\s*(?:\n|$)))|(?:\s*(?:\n|$)))/;
+    var thCase;
+    thymol.getThAttribute = function(part, element) {
+        var result = thymol.ThUtils.unParenthesise(part);
+        result = thymol.doExpression(result, element);
+        if (Object.prototype.toString.call(result) === "[object Array]") {
+            if (result.length === 1) {
+                result = result[0];
+            }
+        }
+        if (result instanceof thymol.ThParam) {
+            result = result.value;
+        }
+        return result;
+    };
+    thymol.doExpression = function(part, element) {
+        var result = thymol.ThUtils.unParenthesise(part), expr, unq, token, mapped;
+        expr = null;
+        unq = thymol.ThUtils.unQuote(result);
+        if (unq != result) {
+            result = thymol.preProcess(unq, element);
+        } else {
+            if (literalTokenExpr.test(result)) {
+                token = thymol.booleanAndNullTokens[result];
+                if (!(typeof token === "undefined")) {
+                    result = token;
+                } else {
+                    if (result.match(numericExpr)) {
+                        result = thymol.ThUtils.getToPrecision(result, thymol.ThUtils.getDecimalDigits(result));
+                    } else {
+                        expr = thymol.getExpression(result, element);
+                        if (expr !== undefined && expr !== null && !(expr != expr)) {
+                            result = expr;
+                        }
+                    }
+                }
+            } else {
+                expr = thymol.getExpression(result, element);
+                if (expr !== null && !(expr != expr)) {
+                    result = expr;
+                } else {
+                    result = null;
+                }
+            }
+        }
+        return result;
+    };
+    thymol.processText = function(element, thUrlAttr, thAttr) {
+        var url = thymol.getThAttribute(thUrlAttr.value, element), updated = false, text, newTextNode, i, iLimit, iUpper;
+        if (url == null) {
+            if (!thymol.allowNullText) {
+                if (thymol.debug) {
+                    thymol.thWindow.alert("thymol.processText cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
+                }
+                return updated;
+            }
+            url = "";
+        } else {
+            if (url instanceof thymol.ThParam || url instanceof thymol.ThObject) {
+                if (url.value) {
+                    url = url.value;
+                }
+            } else if (url instanceof thymol.ThClass && url.abort) {
+                element.removeAttribute(thUrlAttr.name);
+                return true;
+            }
+        }
+        try {
+            while (element.firstChild != null) {
+                element.removeChild(element.firstChild);
+                updated = true;
+                if (element.firstChild == null) {
+                    break;
+                }
+            }
+            if ("text" == thAttr.suffix) {
+                if (Object.prototype.toString.call(url) === "[object Array]") {
+                    text = "[";
+                    for (i = 0, iLimit = url.length, iUpper = url.length - 1; i < iLimit; i++) {
+                        text += url[i].toString();
+                        if (i < iUpper) {
+                            text += ", ";
+                        }
+                    }
+                    text += "]";
+                } else {
+                    text = url.toString();
+                }
+                text = thymol.ThUtils.unescape(text);
+                newTextNode = element.ownerDocument.createTextNode(text);
+                element.appendChild(newTextNode);
+                updated = true;
+            }
+            if ("utext" == thAttr.suffix) {
+                element.innerHTML = url;
+            }
+            element.removeAttribute(thUrlAttr.name);
+        } catch (err) {
+            if (thymol.debug) {
+                thymol.thWindow.alert("text replace error");
+            }
+        }
+        return updated;
+    };
+    thymol.processSpecAttrMod = function(element, thUrlAttr, thAttrObj) {
+        var url = thymol.getThAttribute(thUrlAttr.value, element);
+        if (!url || !(url instanceof thymol.ThClass) || !url.abort) {
+            element.setAttribute(thAttrObj.suffix, url);
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processAttr = function(element, thUrlAttr, thAttrObj) {
+        var argValue = thUrlAttr.value.trim(), argsExpr, expr, identifier, attrName = null, ep, lp, url, tt;
+        if (argValue) {
+            do {
+                argsExpr = thymol.ThParser.parse(argValue, true, false);
+                identifier = argsExpr.tokens.shift();
+                if (identifier.type_ === 3) {
+                    attrName = identifier.index_;
+                    if (!!attrName) {
+                        ep = argValue.indexOf("=");
+                        if (ep >= 0) {
+                            lp = argsExpr.position - 1;
+                            if (argsExpr.position === argValue.length) {
+                                lp = argValue.position;
+                            }
+                            expr = argValue.substring(ep + 1, lp).trim();
+                            if (fixedValBoolAttrList.indexOf(attrName) >= 0) {
+                                thymol.doFixedValBoolAttr(expr, element, attrName);
+                            } else {
+                                url = thymol.getThAttribute(expr, element);
+                                tt = typeof url;
+                                if (thAttrObj.suffix == "attrappend" || thAttrObj.suffix == "attrprepend") {
+                                    if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                                        existing = element.getAttribute(attrName);
+                                        if (existing) {
+                                            if (thAttrObj.suffix == "attrappend") {
+                                                url = existing + url;
+                                            } else if (thAttrObj.suffix == "attrprepend") {
+                                                url = url + existing;
+                                            }
+                                        }
+                                    }
+                                }
+                                if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                                    element.setAttribute(attrName, url);
+                                }
+                            }
+                        }
+                    }
+                    argValue = argValue.substring(argsExpr.position);
+                } else {
+                    break;
+                }
+            } while (argValue.length > 0);
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processCSSAttr = function(element, thUrlAttr, thAttrObj) {
+        var parts = thUrlAttr.value.split(","), i, iLimit, expr, attrName, url, tt, existing;
+        for (i = 0, iLimit = parts.length; i < iLimit; i++) {
+            expr = parts[i];
+            attrName = thAttrObj.suffix == "classappend" ? "class" : "style";
+            if (!!attrName) {
+                if (!!expr) {
+                    url = thymol.getThAttribute(expr, element);
+                    tt = typeof url;
+                    if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                        existing = element.getAttribute(attrName);
+                        if (existing) {
+                            url = existing + " " + url;
+                        }
+                    }
+                    if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                        element.setAttribute(attrName, url);
+                    }
+                }
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processFixedValBoolAttr = function(element, thUrlAttr, thAttrObj) {
+        var val = thymol.doFixedValBoolAttr(thUrlAttr.value, element, thAttrObj.suffix);
+        if (val != null) {
+            element.removeAttribute(thUrlAttr.name);
+        } else {
+            if (thymol.debug) {
+                thymol.thWindow.alert("thymol.processFixedValBoolAttr cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
+            }
+        }
+    };
+    thymol.doFixedValBoolAttr = function(valParam, element, attr) {
+        var val = thymol.getBoolean(valParam, element);
+        if (val) {
+            element.setAttribute(attr, attr);
+        }
+        return val;
+    };
+    thymol.processPairedAttr = function(element, thUrlAttr, thAttrObj) {
+        var url = thymol.getThAttribute(thUrlAttr.value, element);
+        if (url != "") {
+            if (thAttrObj.suffix === "alt-title") {
+                element.setAttribute("alt", url);
+                element.setAttribute("title", url);
+            }
+            if (thAttrObj.suffix === "lang-xmllang") {
+                element.setAttribute("lang", url);
+                element.setAttribute("xml:lang", url);
+            }
+            element.removeAttribute(thUrlAttr.name);
+        } else {
+            if (thymol.debug) {
+                thymol.thWindow.alert("thymol.processPairedAttr cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
+            }
+        }
+    };
+    thymol.processConditional = function(element, attr, thAttrObj) {
+        var removed = false;
+        if (attr.value) {
+            removed = thymol.doIfOrUnless(element, attr.value, thAttrObj.suffix === "if");
+        }
+        element.removeAttribute(attr.name);
+        return removed;
+    };
+    thymol.doIfOrUnless = function(element, value, isIf) {
+        var processed = false, flag;
+        if (value) {
+            flag = thymol.getBoolean(value, element);
+            processed = true;
+            if (!flag) {
+                if (isIf) {
+                    element.parentNode.removeChild(element);
+                    return true;
+                }
+            } else {
+                if (!isIf) {
+                    element.parentNode.removeChild(element);
+                    return true;
+                }
+            }
+        }
+        if (!processed && thymol.debug) {
+            thymol.thWindow.alert("thymol.processConditional cannot process conditional: " + value + "\n" + element.innerHTML);
+        }
+        return false;
+    };
+    thymol.processEach = function(element, thUrlAttr, junk) {
+        var elementsUpdated = false, initial = thUrlAttr.value.trim(), colonPos, varName, varNames, statVarName, expr, root, node, i, iLimit, tho, stat, count, newNode, next;
+        colonPos = initial.indexOf(":");
+        if (colonPos > 0) {
+            varName = initial.substring(0, colonPos);
+            if (varName) {
+                varName = varName.trim();
+                varNames = varName.split(",");
+                varName = varNames[0].trim();
+                if (varNames.length > 1) {
+                    statVarName = varNames[1].trim();
+                } else {
+                    statVarName = varName + "Stat";
+                }
+                expr = initial.substr(colonPos + 1);
+                if (expr) {
+                    expr = expr.trim();
+                    expr = thymol.getExpression(expr, element);
+                    if (expr instanceof thymol.ThSet) {
+                        expr = expr.toArray();
+                    }
+                    root = element.parentNode;
+                    if (expr && expr instanceof Object && expr.length > 0) {
+                        node = element;
+                        iLimit = expr.length;
+                        element.removeAttribute(thUrlAttr.name);
+                        for (i = 0; i < iLimit; i++) {
+                            tho = expr[i];
+                            stat = new Object();
+                            stat.current = tho;
+                            stat.size = expr.length;
+                            stat.index = i;
+                            count = i + 1;
+                            stat.count = count;
+                            if (i == 0) {
+                                stat.first = true;
+                            } else {
+                                stat.first = false;
+                            }
+                            if (i == expr.length - 1) {
+                                stat.last = true;
+                            } else {
+                                stat.last = false;
+                            }
+                            if (i % 2) {
+                                stat.odd = true;
+                                stat.even = false;
+                            } else {
+                                stat.odd = false;
+                                stat.even = true;
+                            }
+                            if (!node.thLocalVars) {
+                                node.thLocalVars = {};
+                            }
+                            node.thLocalVars[varName] = tho;
+                            node.thLocalVars[statVarName] = stat;
+                            if (count < expr.length) {
+                                newNode = element.cloneNode(true);
+                                if (node.nextElementSibling != null) {
+                                    next = root.insertBefore(newNode, node.nextElementSibling);
+                                } else {
+                                    next = root.appendChild(newNode);
+                                }
+                                node = next;
+                                elementsUpdated = true;
+                            }
+                        }
+                    } else {
+                        if (root !== null) {
+                            if (!element.thLocalVars) {
+                                element.thLocalVars = {};
+                            }
+                            if (!element.thLocalVars[varName]) {
+                                element.thLocalVars[varName] = new Object();
+                            }
+                            if (!element.thLocalVars[statVarName]) {
+                                element.thLocalVars[statVarName] = new Object();
+                            }
+                            root.removeChild(element);
+                            elementsUpdated = true;
+                        }
+                    }
+                }
+            }
+        }
+        return elementsUpdated;
+    };
+    thymol.processObject = function(element, thUrlAttr) {
+        var argValue = thUrlAttr.value.trim(), val;
+        if (argValue) {
+            val = thymol.getExpression(argValue, element);
+            if (val) {
+                element.thObjectVar = val;
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processInline = function(element, thUrlAttr, thAttrObj) {
+        var mode = thymol.getThAttribute(thUrlAttr.value, element);
+        if (mode == "text") {
+            thymol.doInlineText(element);
+        } else if (mode == "javascript" || mode == "dart") {
+            thymol.doInlineJavascript(element);
+        } else {
+            if (thymol.debug) {
+                thymol.thWindow.alert('thymol.processInline cannot process scripting mode: "' + mode + '" - it isn\'t supported by version "' + thymol.thVersion + '"\n');
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.doInlineText = function(element) {
+        var changed, value, i, iLimit, expr, term, result;
+        for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
+            do {
+                changed = false;
+                if (element.childNodes[i].nodeType == 1) {
+                    thymol.doInlineText(element.childNodes[i]);
+                } else if (element.childNodes[i].nodeType == 3) {
+                    value = element.childNodes[i].nodeValue;
+                    if (value) {
+                        expr = textInlineCommentExpr.exec(value);
+                        if (expr) {
+                            term = "";
+                            if (expr.length > 1) {
+                                term = "[[" + expr[1] + "]]";
+                            }
+                            if (expr.length > 1) {
+                                result = thymol.getThAttribute(expr[1], element);
+                                result = value.replace(term, result);
+                                element.childNodes[i].nodeValue = result;
+                                changed = true;
+                            }
+                            expr = null;
+                        }
+                    }
+                }
+            } while (changed);
+        }
+    };
+    thymol.doInlineJavascript = function(element) {
+        var changed, value, second, i, iLimit, expr, scraps, remainder, termIndx, term, secondIndx, result;
+        for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
+            do {
+                second = null;
+                changed = false;
+                value = element.childNodes[i].nodeValue;
+                if (value) {
+                    expr = javascriptInlineCommentExpr.exec(value);
+                    if (expr) {
+                        termIndx = expr.index;
+                        term = "";
+                        if (expr.length > 1) {
+                            term = "/*[[" + expr[1] + "]]*/";
+                        }
+                        termIndx = termIndx + term.length;
+                        remainder = value.substring(termIndx);
+                        scraps = javascriptInlineRemainderExpr.exec(remainder);
+                        if (scraps) {
+                            if (scraps.length > 1) {
+                                secondIndx = remainder.indexOf(scraps[1]);
+                                second = remainder.substring(secondIndx);
+                                value = value.substring(0, termIndx);
+                                value = value + second;
+                            }
+                        }
+                        if (expr.length > 1) {
+                            result = thymol.getExpression(expr[1], element);
+                            if (result instanceof thymol.ThObject) {
+                                result = result.toNonThObject();
+                            }
+                            if (!thymol.ThUtils.isLiteral(result)) {
+                                result = thymol.getStringView(result);
+                            }
+                            result = value.replace(term, result);
+                            element.childNodes[i].nodeValue = result;
+                            changed = true;
+                        }
+                        expr = null;
+                        scraps = null;
+                    }
+                }
+            } while (changed);
+        }
+    };
+    thymol.getStringView = function(param) {
+        var view = "", objType;
+        if (typeof param === "string") {
+            view = view + "'" + param + "'";
+        } else if (typeof param === "number" || typeof param === "boolean") {
+            view = view + param;
+        } else if (typeof param === "object") {
+            if (param instanceof Object) {
+                objType = Object.prototype.toString.call(param);
+                if ("[object Array]" == objType) {
+                    view = thymol.getStringViewArray(param);
+                } else if ("[object Object]" == objType) {
+                    view = thymol.getStringViewObject(param);
+                }
+            }
+        }
+        return view;
+    };
+    thymol.getStringViewArray = function(param) {
+        var view = "[", i, iLimit;
+        for (i = 0, iLimit = param.length; i < iLimit; i++) {
+            view = view + thymol.getStringView(param[i]);
+            if (i < param.length - 1) {
+                view = view + ",";
+            }
+        }
+        view = view + "]";
+        return view;
+    };
+    thymol.getStringViewObject = function(param) {
+        var view = "{", key = null;
+        for (key in param) {
+            if (key) {
+                if (view != "{") {
+                    view = view + ",";
+                }
+                view = view + thymol.getStringView(key) + ":";
+                view = view + thymol.getStringView(param[key]);
+            }
+        }
+        view = view + "}";
+        return view;
+    };
+    thymol.processRemove = function(element, thUrlAttr) {
+        var haveRemoved = false;
+        var locals = element.thLocalVars, savedLocals = element.thLocalVars, arg, nodes, first;
+        if (!locals) {
+            locals = {};
+        }
+        if (!locals["tag"]) {
+            locals["tag"] = "tag";
+        }
+        if (!locals["body"]) {
+            locals["body"] = "body";
+        }
+        if (!locals["none"]) {
+            locals["none"] = "none";
+        }
+        if (!locals["all"]) {
+            locals["all"] = "all";
+        }
+        if (!locals["all-but-first"]) {
+            locals["all-but-first"] = "all-but-first";
+        }
+        element.thLocalVars = locals;
+        arg = thymol.getThAttribute(thUrlAttr.value, element);
+        element.thLocalVars = savedLocals;
+        element.removeAttribute(thUrlAttr.name);
+        if ("all" == arg) {
+            if (element.parentNode != null) {
+                element.parentNode.removeChild(element);
+                haveRemoved = true;
+            }
+        } else if ("body" == arg) {
+            element.innerHTML = "";
+            haveRemoved = true;
+        } else if ("tag" == arg) {
+            thymol.ThUtils.removeTag(element);
+            haveRemoved = true;
+        } else if ("all-but-first" == arg) {
+            nodes = element.childNodes;
+            first = true;
+            $(nodes).each(function() {
+                if (this.nodeType == 1) {
+                    if (!first) {
+                        element.removeChild(this);
+                        haveRemoved = true;
+                    }
+                    first = false;
+                }
+            });
+        } else if ("none" == arg || null == arg) {}
+        return haveRemoved;
+    };
+    thymol.processSwitch = function(element, attr) {
+        var val = thymol.ThUtils.unParenthesise(attr.value), updated = false, args, matched = false, thCaseSpecs, caseClause, remove, ccAttr;
+        val = thymol.getThAttribute(val, element);
+        if (typeof val === "string") {
+            args = val.match(nonURLExpr);
+            if (args) {
+                val = args[1];
+            }
+        }
+        val = thymol.ThUtils.unQuote(val);
+        thCaseSpecs = $(thCase.escpName, element);
+        thCaseSpecs.each(function() {
+            caseClause = this;
+            remove = true;
+            $(caseClause.attributes).each(function() {
+                ccAttr = this;
+                if (thCase.name == ccAttr.name || thCase.synonym == ccAttr.name) {
+                    if (!matched) {
+                        matched = thymol.processCase(element, ccAttr, val);
+                        if (matched) {
+                            remove = false;
+                        }
+                    }
+                    caseClause.removeAttribute(ccAttr.name);
+                }
+            });
+            if (remove) {
+                element.removeChild(caseClause);
+                updated = true;
+            }
+        });
+        return updated;
+    };
+    thymol.processCase = function(element, attr, param) {
+        var val = thymol.substitute(attr.value, element);
+        val = thymol.ThUtils.unQuote(val);
+        if (val == "*" || param && param == val) {
+            return true;
+        }
+        return false;
+    };
+    thymol.processWith = function(element, thUrlAttr) {
+        thymol.getWith(element, thUrlAttr.value);
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processAssert = function(element, thUrlAttr) {
+        var argValue = thUrlAttr.value.trim(), result = true, term = "", terms, i, iLimit, expr, val, flag;
+        if (argValue) {
+            terms = argValue.split(",");
+            for (i = 0, iLimit = terms.length; i < iLimit; i++) {
+                term = terms[i];
+                expr = thymol.ThUtils.unParenthesise(term);
+                if (expr != null) {
+                    val = thymol.getExpression(expr, element);
+                    if (val) {
+                        flag = thymol.getBoolean(val, element);
+                        if (!flag) {
+                            result = false;
+                            break;
+                        }
+                    } else {
+                        result = false;
+                        break;
+                    }
+                } else {
+                    result = false;
+                    break;
+                }
+            }
+        }
+        if (!result) {
+            if (argValue != term) {
+                argValue = " list is: " + argValue;
+            } else {
+                argValue = "";
+            }
+            if (term != "") {
+                term = ' false term is: "' + term + '"';
+            }
+            if (thymol.debug) {
+                thymol.thWindow.alert("thymol.processAssert assertion failure -" + argValue + term + "\n");
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processFragment = function(element, thUrlAttr, thAttrObj) {
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.getBoolean = function(param, element) {
+        if (param == null) {
+            return false;
+        }
+        if (typeof param === "boolean") {
+            return param;
+        } else if (typeof param === "number") {
+            return param != 0;
+        }
+        var initial = thymol.ThUtils.unParenthesise(param), negate = false, val, args, flag;
+        if (initial.charAt(0) == "!") {
+            negate = true;
+            initial = initial.substring(1, initial.length);
+            initial = thymol.ThUtils.unParenthesise(initial);
+        }
+        val = thymol.getThAttribute(initial, element);
+        if (val == null) {
+            args = initial.match(varExpr);
+            if (args) {
+                if (args[1].charAt(0) == "!") {
+                    negate = !negate;
+                }
+            }
+        }
+        flag = thymol.getBooleanValue(val);
+        if (negate) {
+            flag = !flag;
+        }
+        return flag;
+    };
+    thymol.appendToAttrList = function(func, prec, attrArray) {
+        var j, jLimit = attrArray.length, tha = null;
+        for (j = 0; j < jLimit; j++) {
+            tha = new thymol.ThAttr(attrArray[j], func, prec, thymol.thThymeleafPrefixList, thymol.prefix);
+        }
+        j = tha;
+    };
+    thymol.setupAttrList = function() {
+        thCase = new thymol.ThAttr("case", null, 275, thymol.thThymeleafPrefixList, thymol.prefix);
+        thymol.addDialect({
+            prefix: thymol.prefix,
+            attributeProcessors: [ {
+                name: "each",
+                processor: thymol.processEach,
+                precedence: 200
+            }, {
+                name: "switch",
+                processor: thymol.processSwitch,
+                precedence: 250
+            }, {
+                name: "if",
+                processor: thymol.processConditional,
+                precedence: 300
+            }, {
+                name: "unless",
+                processor: thymol.processConditional,
+                precedence: 400
+            }, {
+                name: "object",
+                processor: thymol.processObject,
+                precedence: 500
+            }, {
+                name: "with",
+                processor: thymol.processWith,
+                precedence: 600
+            }, {
+                name: "attr",
+                processor: thymol.processAttr,
+                precedence: 700
+            }, {
+                name: "attrprepend",
+                processor: thymol.processAttr,
+                precedence: 800
+            }, {
+                name: "attrappend",
+                processor: thymol.processAttr,
+                precedence: 900
+            }, {
+                name: "alt-title",
+                processor: thymol.processPairedAttr,
+                precedence: 990
+            }, {
+                name: "lang-xmllang",
+                processor: thymol.processPairedAttr,
+                precedence: 990
+            }, {
+                name: "inline",
+                processor: thymol.processInline,
+                precedence: 1e3
+            }, {
+                name: "classappend",
+                processor: thymol.processCSSAttr,
+                precedence: 1100
+            }, {
+                name: "styleappend",
+                processor: thymol.processCSSAttr,
+                precedence: 1100
+            }, {
+                name: "text",
+                processor: thymol.processText,
+                precedence: 1300
+            }, {
+                name: "utext",
+                processor: thymol.processText,
+                precedence: 1400
+            }, {
+                name: "fragment",
+                processor: thymol.processFragment,
+                precedence: 1500
+            }, {
+                name: "assert",
+                processor: thymol.processAssert,
+                precedence: 1550
+            }, {
+                name: "remove",
+                processor: thymol.processRemove,
+                precedence: 1600
+            } ]
+        });
+        thymol.appendToAttrList(thymol.processSpecAttrMod, 1e3, specAttrModList);
+        thymol.appendToAttrList(thymol.processSpecAttrMod, 1e3, eventAttrList);
+        thymol.appendToAttrList(thymol.processFixedValBoolAttr, 1e3, fixedValBoolAttrList);
+    };
+})();
+
+thymol.objects.thHttpSessionObject = function() {
+    var thExpressionObjectName = "#httpSession";
+    function getAttribute(name) {
+        var result = thymol.sessionContext[name];
+        return result;
+    }
+    function getParameter(name) {
+        var result = thymol.sessionContext[name];
+        return result;
+    }
+    function getServletContext() {
+        var result = thymol.applicationContext;
+        return result;
+    }
+    function getSessionContext() {
+        var result = thymol.sessionContext;
+        return result;
+    }
+    function getContextPath() {
+        var result = "";
+        return result;
+    }
+    function getRequestName() {
+        var result = "";
+        return result;
+    }
+    function getParameterValues(name) {
+        var result = thymol.sessionContext[name];
+        return result;
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        getAttribute: getAttribute,
+        getParameter: getParameter,
+        getServletContext: getServletContext,
+        getSessionContext: getSessionContext,
+        getContextPath: getContextPath,
+        getRequestName: getRequestName,
+        getParameterValues: getParameterValues
+    };
+}();
+
+thymol.objects.thHttpServletRequestObject = function() {
+    var thExpressionObjectName = "#httpServletRequest";
+    function getAttribute(name) {
+        var result = thymol.requestContext[name][0];
+        if (result instanceof thymol.ThParam) {
+            result = thymol.ThUtils.unQuote(result.value);
+        }
+        return result;
+    }
+    function getParameter(name) {
+        var result = thymol.requestContext[name];
+        return result;
+    }
+    function getContextPath() {
+        var result = "";
+        return result;
+    }
+    function getRequestName() {
+        var result = "";
+        return result;
+    }
+    function getParameterValues(name) {
+        var result = thymol.requestContext[name];
+        return result;
+    }
+    function getSession(create) {
+        return thymol.objects.thHttpSessionObject;
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        getAttribute: getAttribute,
+        getParameter: getParameter,
+        getContextPath: getContextPath,
+        getRequestName: getRequestName,
+        getParameterValues: getParameterValues,
+        getSession: getSession
+    };
+}();
+
+thymol.objects.thAggregatesObject = function() {
+    var thExpressionObjectName = "#aggregates";
+    function sum(target) {
+        return aggregate(target, false, "sum");
+    }
+    function avg(target) {
+        return aggregate(target, true, "avg");
+    }
+    function aggregate(target, doAvg, label) {
+        if (target !== null) {
+            var result = 0;
+            var count;
+            var tt = typeof target;
+            var ptc = Object.prototype.toString.call(target);
+            if (tt === "Array" || ptc === "[object Array]") {
+                count = target.length;
+                for (var i = 0; i < count; i++) {
+                    if (target[i] !== null) {
+                        result += target[i];
+                    } else {
+                        throw new thymol.ThError("#aggregates." + label + " Cannot aggregate on object containing nulls");
+                    }
+                }
+            } else {
+                count = 0;
+                for (var k in target) {
+                    var value = target[k];
+                    var process = false;
+                    if (value !== null) {
+                        if (target instanceof thymol.ThSet) {
+                            process = target.isContent(k);
+                        } else {
+                            process = target.hasOwnProperty(k) && typeof value !== "function";
+                        }
+                    } else {
+                        throw new thymol.ThError("#aggregates." + label + " Cannot aggregate on object containing nulls");
+                    }
+                    if (process) {
+                        result += value;
+                        count++;
+                    }
+                }
+            }
+            if (doAvg) {
+                if (count == 0) {
+                    throw new thymol.ThError("#aggregates." + label + " Cannot get size of object");
+                }
+                result = result / count;
+            }
+            return result;
+        }
+        throw new thymol.ThError("#aggregates." + label + " Cannot aggregate on null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        sum: sum,
+        avg: avg
+    };
+}();
+
+thymol.objects.thArraysObject = function() {
+    var thExpressionObjectName = "#arrays";
+    function toArray(target) {
+        if (target !== null) {
+            return toTypedArray(null, target);
+        }
+        throw new thymol.ThError("#arrays.toArray Cannot convert null to array");
+    }
+    function toStringArray(target) {
+        if (target !== null) {
+            return toTypedArray("string", target);
+        }
+        throw new thymol.ThError("#arrays.toStringArray Cannot convert null to array");
+    }
+    function toNumberArray(target) {
+        if (target !== null) {
+            return toTypedArray("number", target);
+        }
+        throw new thymol.ThError("#arrays.toNumberArray Cannot convert null to array");
+    }
+    function toBooleanArray(target) {
+        if (target !== null) {
+            return toTypedArray("boolean", target);
+        }
+        throw new thymol.ThError("#arrays.toBooleanArray Cannot convert null to array");
+    }
+    function toTypedArray(componentClass, target) {
+        if (target instanceof Array) {
+            if (componentClass === null || componentClass === "undefined") {
+                return target;
+            }
+            var result = new Array();
+            try {
+                for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                    if (target[i] !== null) {
+                        if (componentClass === "string") {
+                            result.push(new String(target[i]).valueOf());
+                        } else if (componentClass === "number") {
+                            result.push(new Number(target[i]).valueOf());
+                        } else if (componentClass === "boolean") {
+                            result.push(new Boolean(target[i]).valueOf());
+                        } else {
+                            result.push(target[i]);
+                        }
+                    }
+                }
+            } catch (err) {
+                throw new IllegalArgumentException('#arrays.toArray Cannot convert object of class "' + targetComponentClass.getName() + '[]" to an array' + " of " + componentClass.getClass().getSimpleName());
+            }
+            return result;
+        } else if (target instanceof Object) {
+            var result = new Array();
+            try {
+                for (var k in target) {
+                    var value = target[k];
+                    var process = false;
+                    if (value !== null) {
+                        if (target instanceof thymol.ThSet) {
+                            process = target.isContent(k);
+                        } else {
+                            process = target.hasOwnProperty(k) && typeof value !== "function";
+                        }
+                    }
+                    if (process) {
+                        if (componentClass === "string") {
+                            result.push(new String(value).valueOf());
+                        } else if (componentClass === "number") {
+                            result.push(new Number(value).valueOf());
+                        } else if (componentClass === "boolean") {
+                            result.push(new Boolean(value).valueOf());
+                        } else {
+                            result.push(value);
+                        }
+                    }
+                }
+            } catch (err) {
+                throw new IllegalArgumentException('#arrays.toArray Cannot convert object of class "' + targetComponentClass.getName() + '[]" to an array' + " of " + componentClass.getClass().getSimpleName());
+            }
+            return result;
+        } else {
+            throw new thymol.ThError('#arrays.toArray Cannot convert object of type "' + typeof target + '" to an array' + (componentClass == null ? "" : " of " + componentClass));
+        }
+    }
+    function length(target) {
+        if (target !== null) {
+            return target.length;
+        }
+        throw new thymol.ThError("#arrays.length Cannot get array length of null");
+    }
+    function isEmpty(target) {
+        return target === null || target.length <= 0;
+    }
+    function contains(target, element) {
+        if (target !== null) {
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] === null) {
+                    if (element === null) {
+                        return true;
+                    }
+                } else if (element !== null && target[i] === element) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        throw new thymol.ThError("#arrays.contains Cannot execute array contains: target is null");
+    }
+    function containsAll(target, elements) {
+        if (target !== null) {
+            if (elements !== null) {
+                var elementsArray;
+                if (elements instanceof Array) {
+                    elementsArray = [].concat(elements);
+                } else {
+                    if (elements instanceof thymol.ThSet) {
+                        elementsArray = elements.toArray();
+                    } else {
+                        elementsArray = [];
+                        for (var k in elements) {
+                            if (elements.hasOwnProperty(k) && typeof elements[k] !== "function") {
+                                elementsArray.push(elements[k]);
+                            }
+                        }
+                    }
+                }
+                for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                    for (var j = 0, jLimit = elementsArray.length; j < jLimit; j++) {
+                        if (target[i] === elementsArray[j]) {
+                            elementsArray.splice(j, 1);
+                        }
+                    }
+                }
+                return elementsArray.length === 0;
+            }
+            throw new thymol.ThError("#arrays.containsAll Cannot execute array containsAll: elements is null");
+        }
+        throw new thymol.ThError("#arrays.containsAll Cannot execute array containsAll: target is null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        toArray: toArray,
+        toStringArray: toStringArray,
+        toIntegerArray: toNumberArray,
+        toLongArray: toNumberArray,
+        toDoubleArray: toNumberArray,
+        toFloatArray: toNumberArray,
+        toBooleanArray: toBooleanArray,
+        length: length,
+        isEmpty: isEmpty,
+        contains: contains,
+        containsAll: containsAll
+    };
+}();
+
+thymol.objects.thBoolsObject = function() {
+    var thExpressionObjectName = "#bools";
+    function isTrue(target) {
+        var result = true;
+        var tc;
+        if (target == null || (tc = typeof target) === "undefined") {
+            result = false;
+        } else {
+            if (tc === "boolean") {
+                result = target;
+            } else if (tc === "number") {
+                result = target != 0;
+            } else if (tc === "string") {
+                if (target.length === 1) {
+                    result = target.charCodeAt(0) != 0;
+                } else if (thymol.ThUtils.testLiteralFalse(target)) {
+                    result = false;
+                }
+            }
+        }
+        return result;
+    }
+    function arrayIsTrue(target) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(isTrue(target[i]));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#bools.arrayIsTrue Target cannot be null");
+    }
+    function setIsTrue(target) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(isTrue(target[k]));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#bools.setIsTrue Target cannot be null");
+    }
+    function isFalse(target) {
+        return !isTrue(target);
+    }
+    function arrayIsFalse(target) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(!isTrue(target[i]));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#bools.arrayIsFalse Target cannot be null");
+    }
+    function setIsFalse(target) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(!isTrue(target[k]));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#bools.setIsFalse Target cannot be null");
+    }
+    function arrayAnd(target) {
+        if (target !== null) {
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (!isTrue(target[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        throw new thymol.ThError("#bools.arrayAnd Target cannot be null");
+    }
+    function setAnd(target) {
+        if (target !== null) {
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    if (!isTrue(target[k])) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        throw new thymol.ThError("#bools.setAnd Target cannot be null");
+    }
+    function arrayOr(target) {
+        if (target !== null) {
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (isTrue(target[i])) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        throw new thymol.ThError("#bools.arrayOr Target cannot be null");
+    }
+    function setOr(target) {
+        if (target !== null) {
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    if (isTrue(target[k])) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+        throw new thymol.ThError("#bools.setOr Target cannot be null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        isTrue: isTrue,
+        arrayIsTrue: arrayIsTrue,
+        listIsTrue: arrayIsTrue,
+        setIsTrue: setIsTrue,
+        isFalse: isFalse,
+        arrayIsFalse: arrayIsFalse,
+        listIsFalse: arrayIsFalse,
+        setIsFalse: setIsFalse,
+        arrayAnd: arrayAnd,
+        listAnd: arrayAnd,
+        setAnd: setAnd,
+        arrayOr: arrayOr,
+        listOr: arrayOr,
+        setOr: setOr
+    };
+}();
+
+thymol.objects.thDatesObject = function() {
+    var thExpressionObjectName = "#dates";
+    function createProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 6) {
+                return create(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
+            } else if (arguments.length > 5) {
+                return create(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], 0);
+            } else if (arguments.length > 4) {
+                return create(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], 0, 0);
+            }
+            return create(arguments[0], arguments[1], arguments[2], 0, 0, 0, 0);
+        }
+    }
+    function create(year, month, day, hour, minute, second, millisecond) {
+        var result = new Date();
+        result.setMilliseconds(millisecond);
+        result.setSeconds(second);
+        result.setMinutes(minute);
+        result.setHours(hour);
+        result.setDate(day);
+        result.setMonth(month - 1);
+        result.setFullYear(year);
+        return result;
+    }
+    function getDay(dateValue) {
+        var month = dateValue.getMonth() + 1;
+        var year = dateValue.getFullYear();
+        var day = dateValue.getDate();
+        var a = Math.floor((14 - month) / 12);
+        var y = year + 4800 - a;
+        var m = month + 12 * a - 3;
+        var jdn = day + Math.floor((153 * m + 2) / 5) + 365 * y + Math.floor(y / 4);
+        if (jdn < 2331254) {
+            jdn = jdn - 32083;
+        } else {
+            jdn = jdn - Math.floor(y / 100) + Math.floor(y / 400) - 32045;
+        }
+        var mjdn = (jdn + 1) % 7;
+        return mjdn;
+    }
+    function createNow() {
+        return new Date();
+    }
+    function createToday() {
+        var today = new Date();
+        today.setHours(0, 0, 0, 0);
+        return today;
+    }
+    function format(dateParam, patternParam, locale) {
+        var pattern = "";
+        var date;
+        if (arguments === null) {
+            date = new Date();
+        } else {
+            if (arguments.length > 1) {
+                pattern = patternParam;
+            }
+            date = dateParam;
+        }
+        return formatDate(date, pattern, locale);
+    }
+    function formatDate(target, patternParam, locale) {
+        var pattern = "";
+        if (arguments.length > 1) {
+            pattern = patternParam;
+        }
+        var result = dateFormat(target, pattern, false);
+        return result;
+    }
+    function arrayFormat(target, patternParam) {
+        var pattern = "";
+        if (arguments.length > 1) {
+            pattern = patternParam;
+        }
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(dateFormat(target[i], pattern, false));
+        }
+        return result;
+    }
+    function setFormat(target, patternParam) {
+        var pattern = "";
+        if (arguments.length > 1) {
+            pattern = patternParam;
+        }
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(dateFormat(target[k], pattern, false));
+            }
+        }
+        return result;
+    }
+    function day(target) {
+        return target.getDate();
+    }
+    function arrayDay(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getDate());
+        }
+        return result;
+    }
+    function setDay(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getDate());
+            }
+        }
+        return result;
+    }
+    function month(target) {
+        return target.getMonth() + 1;
+    }
+    function arrayMonth(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getMonth() + 1);
+        }
+        return result;
+    }
+    function setMonth(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getMonth() + 1);
+            }
+        }
+        return result;
+    }
+    function monthName(target) {
+        return dateFormat.i18n.monthNames[target.getMonth() + 12];
+    }
+    function arrayMonthName(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(dateFormat.i18n.monthNames[target[i].getMonth() + 12]);
+        }
+        return result;
+    }
+    function setMonthName(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(dateFormat.i18n.monthNames[target[k].getMonth() + 12]);
+            }
+        }
+        return result;
+    }
+    function monthNameShort(target) {
+        return dateFormat.i18n.monthNames[target.getMonth()];
+    }
+    function arrayMonthNameShort(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(dateFormat.i18n.monthNames[target[i].getMonth()]);
+        }
+        return result;
+    }
+    function setMonthNameShort(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(dateFormat.i18n.monthNames[target[k].getMonth()]);
+            }
+        }
+        return result;
+    }
+    function year(target) {
+        return target.getFullYear();
+    }
+    function arrayYear(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getFullYear());
+        }
+        return result;
+    }
+    function setYear(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getFullYear());
+            }
+        }
+        return result;
+    }
+    function dayOfWeek(target) {
+        return getDay(target) + 1;
+    }
+    function arrayDayOfWeek(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(getDay(target[i]) + 1);
+        }
+        return result;
+    }
+    function setDayOfWeek(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(getDay(target[k]) + 1);
+            }
+        }
+        return result;
+    }
+    function dayOfWeekName(target) {
+        return dateFormat.i18n.dayNames[getDay(target) + 7];
+    }
+    function arrayDayOfWeekName(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(dateFormat.i18n.dayNames[getDay(target[i]) + 7]);
+        }
+        return result;
+    }
+    function setDayOfWeekName(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(dateFormat.i18n.dayNames[getDay(target[k]) + 7]);
+            }
+        }
+        return result;
+    }
+    function dayOfWeekNameShort(target) {
+        return dateFormat.i18n.dayNames[getDay(target)];
+    }
+    function arrayDayOfWeekNameShort(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(dateFormat.i18n.dayNames[getDay(target[i])]);
+        }
+        return result;
+    }
+    function setDayOfWeekNameShort(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(dateFormat.i18n.dayNames[getDay(target[k])]);
+            }
+        }
+        return result;
+    }
+    function hour(target) {
+        return target.getHours();
+    }
+    function arrayHour(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getHours());
+        }
+        return result;
+    }
+    function setHour(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getHours());
+            }
+        }
+        return result;
+    }
+    function minute(target) {
+        return target.getMinutes();
+    }
+    function arrayMinute(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getMinutes());
+        }
+        return result;
+    }
+    function setMinute(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getMinutes());
+            }
+        }
+        return result;
+    }
+    function second(target) {
+        return target.getSeconds();
+    }
+    function arraySecond(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getSeconds());
+        }
+        return result;
+    }
+    function setSecond(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getSeconds());
+            }
+        }
+        return result;
+    }
+    function millisecond(target) {
+        return target.getMilliseconds();
+    }
+    function arrayMillisecond(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getMilliseconds());
+        }
+        return result;
+    }
+    function setMillisecond(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getMilliseconds());
+            }
+        }
+        return result;
+    }
+    var timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, timezoneClip = /[^-+\dA-Z]/g;
+    function processTZ(target) {
+        var toStr = String(target);
+        var result = toStr;
+        result = (result.match(timezone) || [ "" ]).pop();
+        if ("" !== result) {
+            result = result.replace(timezoneClip, "");
+            var tail = toStr.match(/[\(]((?:[GL]M|BS)T[^\)]*?)[\)]/);
+            if (tail) {
+                if (target.getFullYear() > 1916 || target.getFullYear() === 1916 && target.getMonth() > 4 || target.getFullYear() === 1916 && target.getMonth() === 4 && target.getDate() > 20) {
+                    result = result.replace(/GMT\+\d{1,4}/, "BST");
+                } else {
+                    result = result.replace(/GMT\+\d{1,4}/, "GMT");
+                }
+            }
+        }
+        return result;
+    }
+    var dateFormat = function() {
+        var token = /d{1,4}|M{1,4}|yy(?:yy)?|([HhmsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, pad = function(valp, lenp) {
+            var val = String(valp), len = lenp || 2;
+            while (val.length < len) val = "0" + val;
+            return val;
+        };
+        return function(datep, maskp, utcp) {
+            var dF = dateFormat, mask = maskp, date = datep, utc = utcp;
+            if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
+                mask = date;
+                date = undefined;
+            }
+            date = date ? new Date(date) : new Date();
+            if (isNaN(date)) throw SyntaxError("invalid date");
+            mask = String(dF.masks[mask] || mask || dF.masks["default"]);
+            if (mask.slice(0, 4) == "UTC:") {
+                mask = mask.slice(4);
+                utc = true;
+            }
+            var _ = utc ? "getUTC" : "get", d = date[_ + "Date"](), D = getDay(date), M = date[_ + "Month"](), y = date[_ + "FullYear"](), H = date[_ + "Hours"](), m = date[_ + "Minutes"](), s = date[_ + "Seconds"](), L = date[_ + "Milliseconds"](), o = utc ? 0 : date.getTimezoneOffset(), flags = {
+                d: d,
+                dd: pad(d),
+                ddd: dF.i18n.dayNames[D],
+                dddd: dF.i18n.dayNames[D + 7],
+                M: M + 1,
+                MM: pad(M + 1),
+                MMM: dF.i18n.monthNames[M],
+                MMMM: dF.i18n.monthNames[M + 12],
+                yy: String(y).slice(2),
+                yyyy: y,
+                h: H % 12 || 12,
+                hh: pad(H % 12 || 12),
+                H: H,
+                HH: pad(H),
+                m: m,
+                mm: pad(m),
+                s: s,
+                ss: pad(s),
+                l: pad(L, 3),
+                L: pad(L > 99 ? Math.round(L / 10) : L),
+                t: H < 12 ? "a" : "p",
+                tt: H < 12 ? "am" : "pm",
+                T: H < 12 ? "A" : "P",
+                TT: H < 12 ? "AM" : "PM",
+                Z: utc ? "UTC" : processTZ(date),
+                o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
+                S: [ "th", "st", "nd", "rd" ][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
+            };
+            return mask.replace(token, function($0) {
+                return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
+            });
+        };
+    }();
+    dateFormat.masks = {
+        "default": "dd MMMM yyyy HH:mm:ss Z",
+        shortDate: "M/d/yy",
+        mediumDate: "MMM d, yyyy",
+        longDate: "d MMMM yyyy",
+        fullDate: "dddd, MMMM d, yyyy",
+        shortTime: "h:mm TT",
+        mediumTime: "h:mm:ss TT",
+        longTime: "h:mm:ss TT Z",
+        isoDate: "yyyy-MM-dd",
+        isoTime: "HH:mm:ss",
+        isoDateTime: "yyyy-MM-dd'T'HH:mm:ss",
+        isoUtcDateTime: "UTC:yyyy-MM-dd'T'HH:mm:ss'Z'"
+    };
+    dateFormat.i18n = {
+        dayNames: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
+        monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]
+    };
+    Date.prototype.format = function(mask, utc) {
+        return dateFormat(this, mask, utc);
+    };
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        create: createProxy,
+        createNow: createNow,
+        createNowForTimeZone: createNow,
+        createToday: createToday,
+        createTodayForTimeZone: createToday,
+        format: format,
+        dateFormat: dateFormat,
+        arrayFormat: arrayFormat,
+        listFormat: arrayFormat,
+        setFormat: setFormat,
+        day: day,
+        arrayDay: arrayDay,
+        listDay: arrayDay,
+        setDay: setDay,
+        month: month,
+        arrayMonth: arrayMonth,
+        listMonth: arrayMonth,
+        setMonth: setMonth,
+        monthName: monthName,
+        arrayMonthName: arrayMonthName,
+        listMonthName: arrayMonthName,
+        setMonthName: setMonthName,
+        monthNameShort: monthNameShort,
+        arrayMonthNameShort: arrayMonthNameShort,
+        listMonthNameShort: arrayMonthNameShort,
+        setMonthNameShort: setMonthNameShort,
+        year: year,
+        arrayYear: arrayYear,
+        listYear: arrayYear,
+        setYear: setYear,
+        dayOfWeek: dayOfWeek,
+        arrayDayOfWeek: arrayDayOfWeek,
+        listDayOfWeek: arrayDayOfWeek,
+        setDayOfWeek: setDayOfWeek,
+        dayOfWeekName: dayOfWeekName,
+        arrayDayOfWeekName: arrayDayOfWeekName,
+        listDayOfWeekName: arrayDayOfWeekName,
+        setDayOfWeekName: setDayOfWeekName,
+        dayOfWeekNameShort: dayOfWeekNameShort,
+        arrayDayOfWeekNameShort: arrayDayOfWeekNameShort,
+        listDayOfWeekNameShort: arrayDayOfWeekNameShort,
+        setDayOfWeekNameShort: setDayOfWeekNameShort,
+        hour: hour,
+        arrayHour: arrayHour,
+        listHour: arrayHour,
+        setHour: setHour,
+        minute: minute,
+        arrayMinute: arrayMinute,
+        listMinute: arrayMinute,
+        setMinute: setMinute,
+        second: second,
+        arraySecond: arraySecond,
+        listSecond: arraySecond,
+        setSecond: setSecond,
+        millisecond: millisecond,
+        arrayMillisecond: arrayMillisecond,
+        listMillisecond: arrayMillisecond,
+        setMillisecond: setMillisecond
+    };
+}();
+
+thymol.objects.thCalendarsObject = function() {
+    var thExpressionObjectName = "#calendars";
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        create: thymol.objects.thDatesObject.create,
+        createNow: thymol.objects.thDatesObject.createNow,
+        createNowForTimeZone: thymol.objects.thDatesObject.createNow,
+        createToday: thymol.objects.thDatesObject.createToday,
+        createTodayForTimeZone: thymol.objects.thDatesObject.createToday,
+        format: thymol.objects.thDatesObject.format,
+        dateFormat: thymol.objects.thDatesObject.dateFormat,
+        arrayFormat: thymol.objects.thDatesObject.arrayFormat,
+        listFormat: thymol.objects.thDatesObject.arrayFormat,
+        setFormat: thymol.objects.thDatesObject.setFormat,
+        day: thymol.objects.thDatesObject.day,
+        arrayDay: thymol.objects.thDatesObject.arrayDay,
+        listDay: thymol.objects.thDatesObject.arrayDay,
+        setDay: thymol.objects.thDatesObject.setDay,
+        month: thymol.objects.thDatesObject.month,
+        arrayMonth: thymol.objects.thDatesObject.arrayMonth,
+        listMonth: thymol.objects.thDatesObject.arrayMonth,
+        setMonth: thymol.objects.thDatesObject.setMonth,
+        monthName: thymol.objects.thDatesObject.monthName,
+        arrayMonthName: thymol.objects.thDatesObject.arrayMonthName,
+        listMonthName: thymol.objects.thDatesObject.arrayMonthName,
+        setMonthName: thymol.objects.thDatesObject.setMonthName,
+        monthNameShort: thymol.objects.thDatesObject.monthNameShort,
+        arrayMonthNameShort: thymol.objects.thDatesObject.arrayMonthNameShort,
+        listMonthNameShort: thymol.objects.thDatesObject.arrayMonthNameShort,
+        setMonthNameShort: thymol.objects.thDatesObject.setMonthNameShort,
+        year: thymol.objects.thDatesObject.year,
+        arrayYear: thymol.objects.thDatesObject.arrayYear,
+        listYear: thymol.objects.thDatesObject.arrayYear,
+        setYear: thymol.objects.thDatesObject.setYear,
+        dayOfWeek: thymol.objects.thDatesObject.dayOfWeek,
+        arrayDayOfWeek: thymol.objects.thDatesObject.arrayDayOfWeek,
+        listDayOfWeek: thymol.objects.thDatesObject.arrayDayOfWeek,
+        setDayOfWeek: thymol.objects.thDatesObject.setDayOfWeek,
+        dayOfWeekName: thymol.objects.thDatesObject.dayOfWeekName,
+        arrayDayOfWeekName: thymol.objects.thDatesObject.arrayDayOfWeekName,
+        listDayOfWeekName: thymol.objects.thDatesObject.arrayDayOfWeekName,
+        setDayOfWeekName: thymol.objects.thDatesObject.setDayOfWeekName,
+        dayOfWeekNameShort: thymol.objects.thDatesObject.dayOfWeekNameShort,
+        arrayDayOfWeekNameShort: thymol.objects.thDatesObject.arrayDayOfWeekNameShort,
+        listDayOfWeekNameShort: thymol.objects.thDatesObject.arrayDayOfWeekNameShort,
+        setDayOfWeekNameShort: thymol.objects.thDatesObject.setDayOfWeekNameShort,
+        hour: thymol.objects.thDatesObject.hour,
+        arrayHour: thymol.objects.thDatesObject.arrayHour,
+        listHour: thymol.objects.thDatesObject.arrayHour,
+        setHour: thymol.objects.thDatesObject.setHour,
+        minute: thymol.objects.thDatesObject.minute,
+        arrayMinute: thymol.objects.thDatesObject.arrayMinute,
+        listMinute: thymol.objects.thDatesObject.arrayMinute,
+        setMinute: thymol.objects.thDatesObject.setMinute,
+        second: thymol.objects.thDatesObject.second,
+        arraySecond: thymol.objects.thDatesObject.arraySecond,
+        listSecond: thymol.objects.thDatesObject.arraySecond,
+        setSecond: thymol.objects.thDatesObject.setSecond,
+        millisecond: thymol.objects.thDatesObject.millisecond,
+        arrayMillisecond: thymol.objects.thDatesObject.arrayMillisecond,
+        listMillisecond: thymol.objects.thDatesObject.arrayMillisecond,
+        setMillisecond: thymol.objects.thDatesObject.setMillisecond
+    };
+}();
+
+thymol.objects.thIdsObject = function() {
+    var thExpressionObjectName = "#ids";
+    function seq(id) {
+        if (id !== null) {
+            var str = id.toString();
+            var idCount = getLocal(str);
+            var result = str + idCount;
+            idCount++;
+            setLocal(str, idCount);
+            return result;
+        }
+        throw new thymol.ThError("#ids.seq ID Cannot be null");
+    }
+    function next(id) {
+        if (id !== null) {
+            var str = id.toString();
+            var idCount = getLocal(str);
+            return str + idCount;
+        }
+        throw new thymol.ThError("#ids.next ID Cannot be null");
+    }
+    function prev(id) {
+        if (id !== null) {
+            var str = id.toString();
+            var idCount = getLocal(str);
+            return str + (idCount - 1);
+        }
+        throw new thymol.ThError("#ids.prev ID Cannot be null");
+    }
+    function setLocal(str, idCount) {
+        if (!thymol.objects.thIdsObject.thLocalVars) {
+            thymol.objects.thIdsObject.thLocalVars = [];
+        }
+        if (!thymol.objects.thIdsObject.thLocalVars["thIdCounts"]) {
+            thymol.objects.thIdsObject.thLocalVars["thIdCounts"] = [];
+        }
+        thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str] = idCount;
+    }
+    function getLocal(str) {
+        if (!thymol.objects.thIdsObject.thLocalVars) {
+            thymol.objects.thIdsObject.thLocalVars = [];
+        }
+        if (!thymol.objects.thIdsObject.thLocalVars["thIdCounts"]) {
+            thymol.objects.thIdsObject.thLocalVars["thIdCounts"] = [];
+        }
+        if (!thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str]) {
+            thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str] = 1;
+        }
+        return thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str];
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        seq: seq,
+        next: next,
+        prev: prev
+    };
+}();
+
+thymol.objects.thListsObject = function() {
+    var thExpressionObjectName = "#lists";
+    function sort(list, comparator) {
+        if (list !== null) {
+            if (arguments.length > 1) {
+                if (comparator !== null) {
+                    if (typeof comparator === "function") {
+                        return list.sort(comparator);
+                    }
+                    throw new thymol.ThError("#lists.sort Cannot execute list sort: comparator is not a function");
+                }
+                throw new thymol.ThError("#lists.sort Cannot execute list sort: comparator is null");
+            }
+            return list.sort();
+        }
+        throw new thymol.ThError("#lists.sort Cannot execute list sort: list is null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        toList: thymol.objects.thArraysObject.toArray,
+        size: thymol.objects.thArraysObject.length,
+        isEmpty: thymol.objects.thArraysObject.isEmpty,
+        contains: thymol.objects.thArraysObject.contains,
+        containsAll: thymol.objects.thArraysObject.containsAll,
+        sort: sort
+    };
+}();
+
+thymol.objects.thMapsObject = function() {
+    var thExpressionObjectName = "#maps";
+    function size(target) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                return target.size();
+            }
+            throw new thymol.ThError('#maps.size Cannot get size of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.size Cannot get size of null");
+    }
+    function isEmpty(target) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                return target.isEmpty();
+            }
+            throw new thymol.ThError('#maps.size Cannot get isEmpty of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.size Cannot get isEmpty of null");
+    }
+    function containsKey(target, key) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                return target.containsKey(key);
+            }
+            throw new thymol.ThError('#maps.size Cannot get containsKey of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.containsKey Cannot execute map containsKey: target is null");
+    }
+    function containsValue(target, value) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                return target.containsValue(value);
+            }
+            throw new thymol.ThError('#maps.size Cannot get containsValue of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.containsKey Cannot execute map containsValue: target is null");
+    }
+    function containsAllKeys(target, keys) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                var ptc = Object.prototype.toString.call(keys);
+                if (keys instanceof thymol.ThSet || keys instanceof Array || ptc === "[object Array]") {
+                    return target.containsAll(keys);
+                }
+                throw new thymol.ThError('#maps.size Cannot get containsAllKeys with non-collection type "' + ptc + '"');
+            }
+            throw new thymol.ThError('#maps.size Cannot get containsAllKeys of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.containsKey Cannot execute map containsAllKeys: target is null");
+    }
+    function containsAllValues(target, values) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                var ptc = Object.prototype.toString.call(values);
+                if (values instanceof thymol.ThSet || values instanceof Array || ptc === "[object Array]") {
+                    var vArray = values;
+                    if (values instanceof thymol.ThSet) {
+                        vArray = values.toArray();
+                    }
+                    for (var i = 0, iLimit = vArray.length; i < iLimit; i++) {
+                        var found = false;
+                        for (var k in target) {
+                            if (target.hasOwnProperty(k)) {
+                                var value = target[k];
+                                if (value === vArray[i]) {
+                                    found = true;
+                                    break;
+                                }
+                            }
+                        }
+                        if (!found) {
+                            return false;
+                        }
+                    }
+                    return true;
+                }
+                throw new thymol.ThError('#maps.size Cannot get containsAllValues with non-collection type "' + ptc + '"');
+            }
+            throw new thymol.ThError('#maps.size Cannot get containsAllValues of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.containsKey Cannot execute map containsAllValues: target is null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        size: size,
+        isEmpty: isEmpty,
+        containsKey: containsKey,
+        containsValue: containsValue,
+        containsAllKeys: containsAllKeys,
+        containsAllValues: containsAllValues
+    };
+}();
+
+thymol.objects.thMessagesObject = function() {
+    var thExpressionObjectName = "#messages";
+    function msg() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return msgWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.msg Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.msg Target cannot be null");
+    }
+    function msgWithParams(target, params) {
+        if (target !== null) {
+            return thymol.getMessage(target, params, true);
+        }
+        throw new thymol.ThError("#messages.msgWithParams Target cannot be null");
+    }
+    function msgOrNull() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return msgOrNullWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.msgOrNull Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.msgOrNull Target cannot be null");
+    }
+    function msgOrNullWithParams(target, params) {
+        if (target !== null) {
+            return thymol.getMessage(target, params, false);
+        }
+        throw new thymol.ThError("#messages.msgOrNullWithParams Target cannot be null");
+    }
+    function arrayMsg() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return arrayMsgWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.arrayMsg Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.arrayMsg Target cannot be null");
+    }
+    function arrayMsgWithParams(target, params) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(msgWithParams(target[i], params));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#messages.arrayMsgWithParams Target cannot be null");
+    }
+    function setMsg() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return setMsgWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.setMsg Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.setMsg Target cannot be null");
+    }
+    function setMsgWithParams(target, params) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(msgWithParams(target[k], params));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#messages.setMsgWithParams Target cannot be null");
+    }
+    function arrayMsgOrNull() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return arrayMsgOrNullWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.arrayMsgOrNull Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.arrayMsgOrNull Target cannot be null");
+    }
+    function arrayMsgOrNullWithParams(target, params) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(msgOrNullWithParams(target[i], params));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#messages.arrayMsgOrNullWithParams Target cannot be null");
+    }
+    function setMsgOrNull() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return setMsgOrNullWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.setMsgOrNull Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.setMsgOrNull Target cannot be null");
+    }
+    function setMsgOrNullWithParams(target, params) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(msgOrNullWithParams(target[k], params));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#messages.setMsgOrNullWithParams Target cannot be null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        msg: msg,
+        msgWithParams: msgWithParams,
+        msgOrNull: msgOrNull,
+        msgOrNullWithParams: msgOrNullWithParams,
+        arrayMsg: arrayMsg,
+        listMsg: arrayMsg,
+        setMsg: setMsg,
+        arrayMsgWithParams: arrayMsgWithParams,
+        listMsgWithParams: arrayMsgWithParams,
+        setMsgWithParams: setMsgWithParams,
+        arrayMsgOrNull: arrayMsgOrNull,
+        listMsgOrNull: arrayMsgOrNull,
+        setMsgOrNull: setMsgOrNull,
+        arrayMsgOrNullWithParams: arrayMsgOrNullWithParams,
+        listMsgOrNullWithParams: arrayMsgOrNullWithParams,
+        setMsgOrNullWithParams: setMsgOrNullWithParams
+    };
+}();
+
+thymol.objects.thNumbersObject = function() {
+    var thExpressionObjectName = "#numbers";
+    var DEFAULT_THOU_PT = ",";
+    var DEFAULT_DECI_PT = ".";
+    var DEFAULT_NONE_PT = "?";
+    function formatDecimalProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 4) {
+                return formatDecimal5(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
+            } else if (arguments.length > 3) {
+                return formatDecimal4(arguments[0], arguments[1], arguments[2], arguments[3]);
+            }
+            return formatDecimal3(arguments[0], arguments[1], arguments[2]);
+        }
+    }
+    function formatIntegerProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 4) {
+                return formatDecimal5(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
+            } else if (arguments.length > 3) {
+                return formatDecimal5(arguments[0], arguments[1], "NONE", arguments[2], arguments[3]);
+            } else if (arguments.length > 2) {
+                if (typeof arguments[2] === "string") {
+                    return formatDecimal5(arguments[0], arguments[1], arguments[2], 0, "POINT");
+                }
+                return formatDecimal5(arguments[0], arguments[1], "NONE", arguments[2], "POINT");
+            } else {
+                return formatDecimal5(arguments[0], arguments[1], "NONE", 0, "POINT");
+            }
+        }
+    }
+    function arrayFormatIntegerProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 2) {
+                return arrayFormatDecimal(arguments[0], arguments[1], arguments[2], 0, "POINT");
+            }
+            return arrayFormatDecimal(arguments[0], arguments[1], "NONE", 0, "POINT");
+        }
+    }
+    function setFormatIntegerProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 2) {
+                return setFormatDecimal(arguments[0], arguments[1], arguments[2], 0, "POINT");
+            }
+            return setFormatDecimal(arguments[0], arguments[1], "NONE", 0, "POINT");
+        }
+    }
+    function arrayFormatDecimalProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 4) {
+                return arrayFormatDecimal(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
+            } else if (arguments.length > 3) {
+                return arrayFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], arguments[3]);
+            }
+            return arrayFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], "POINT");
+        }
+    }
+    function setFormatDecimalProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 4) {
+                return setFormatDecimal(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
+            } else if (arguments.length > 3) {
+                return setFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], arguments[3]);
+            }
+            return setFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], "POINT");
+        }
+    }
+    function sequenceProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 2) {
+                return sequence(arguments[0], arguments[1], arguments[2]);
+            }
+            return sequence(arguments[0], arguments[1], 1);
+        }
+    }
+    function getIntegerDigits(val) {
+        var s = val.toString();
+        var digits = s.length;
+        var dp = s.indexOf(".");
+        if (dp > 0) {
+            digits = dp;
+        }
+        return digits;
+    }
+    function formatDecimal3(target, minIntegerDigits, decimalDigits) {
+        var result = target.toString();
+        var value = new Number(target);
+        value = value.toFixed(decimalDigits);
+        if (minIntegerDigits > 0) {
+            result = value;
+            value = new Number(value);
+            var a = Math.abs(value);
+            if (a < Math.pow(10, minIntegerDigits)) {
+                if (target < 0) {
+                    result = result.substring(1);
+                }
+                var p = getIntegerDigits(a);
+                var x = minIntegerDigits - p;
+                if (x > 0) {
+                    for (var i = 0; i < x; i++) {
+                        result = "0" + result;
+                    }
+                }
+                if (target < 0) {
+                    result = "-" + result;
+                }
+            }
+        } else {
+            result = value.toString();
+        }
+        result = new String(result);
+        result.precision = decimalDigits;
+        return result;
+    }
+    function formatDecimal4(target, minIntegerDigits, decimalDigits, decimalPointType) {
+        var result = formatDecimal3(target, minIntegerDigits, decimalDigits);
+        var decimalPoint;
+        if ("DEFAULT" === decimalPointType) {
+            decimalPoint = DEFAULT_DECI_PT;
+        } else if ("NONE" === decimalPointType) {
+            decimalPoint = DEFAULT_NONE_PT;
+        } else {
+            decimalPoint = getPointType(decimalPointType);
+        }
+        if ("." !== decimalPoint) {
+            result = result.replace(".", decimalPoint, "g");
+        }
+        return result;
+    }
+    function formatDecimal5(target, minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType) {
+        var result = target.toString();
+        var decimalPoint;
+        if ("DEFAULT" === decimalPointType) {
+            decimalPoint = DEFAULT_DECI_PT;
+        } else if ("NONE" === decimalPointType) {
+            decimalPoint = DEFAULT_NONE_PT;
+        } else {
+            decimalPoint = getPointType(decimalPointType);
+        }
+        if ("" !== decimalPoint) {
+            result = formatDecimal4(target, minIntegerDigits, decimalDigits, decimalPointType);
+        } else {
+            result = formatDecimal3(target, minIntegerDigits, decimalDigits);
+        }
+        var thousandsPoint;
+        if ("DEFAULT" === thousandsPointType) {
+            thousandsPoint = DEFAULT_THOU_PT;
+        } else {
+            thousandsPoint = getPointType(thousandsPointType);
+        }
+        if ("" !== thousandsPoint) {
+            result = addThousandsPointType(result.toString(), decimalPoint, thousandsPoint);
+        }
+        return result;
+    }
+    function getPointType(type) {
+        var result = ".";
+        if ("COMMA" === type) {
+            result = ",";
+        } else if ("WHITESPACE" === type) {
+            result = " ";
+        } else if ("NONE" === type) {
+            result = "";
+        }
+        return result;
+    }
+    function arrayFormatDecimal(target, minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(formatDecimal5(target[i], minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType));
+        }
+        return result;
+    }
+    function setFormatDecimal(target, minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.hasOwnProperty(k) && typeof target[k] !== "function") {
+                result.add(formatDecimal5(target[k], minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType));
+            }
+        }
+        return result;
+    }
+    function addThousandsPointType(nStr, dpt, tpt) {
+        var x = nStr.split(dpt);
+        var x1 = x[0];
+        var x2 = x.length > 1 ? dpt + x[1] : "";
+        var rgx = /(\d+)(\d{3})/;
+        while (rgx.test(x1)) {
+            x1 = x1.replace(rgx, "$1" + tpt + "$2");
+        }
+        return x1 + x2;
+    }
+    function sequence(start, stop, step) {
+        var result = [];
+        if (step > 0) {
+            var value = start;
+            if (start <= stop) {
+                do {
+                    result.push(value);
+                    value += step;
+                } while (value <= stop);
+            } else {
+                do {
+                    result.push(value);
+                    value -= step;
+                } while (value >= stop);
+            }
+        }
+        return result;
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        formatDecimal: formatDecimalProxy,
+        formatInteger: formatIntegerProxy,
+        arrayFormatInteger: arrayFormatIntegerProxy,
+        arrayFormatDecimal: arrayFormatDecimalProxy,
+        listFormatInteger: arrayFormatIntegerProxy,
+        listFormatDecimal: arrayFormatDecimalProxy,
+        setFormatInteger: setFormatIntegerProxy,
+        setFormatDecimal: setFormatDecimalProxy,
+        sequence: sequenceProxy
+    };
+}();
+
+thymol.objects.thObjectsObject = function() {
+    var thExpressionObjectName = "#objects";
+    function nullSafe(target, defaultValue) {
+        return target != null ? target : defaultValue;
+    }
+    function arrayNullSafe(target, defaultValue) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(nullSafe(target[i], defaultValue));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#objects.arrayNullSafe Target cannot be null");
+    }
+    function setNullSafe(target, defaultValue) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(nullSafe(target[k], defaultValue));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#objects.setNullSafe Target cannot be null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        nullSafe: nullSafe,
+        arrayNullSafe: arrayNullSafe,
+        listNullSafe: arrayNullSafe,
+        setNullSafe: setNullSafe
+    };
+}();
+
+thymol.objects.thSetsObject = function() {
+    var thExpressionObjectName = "#sets";
+    function toSet(target) {
+        if (target !== null) {
+            var tt = typeof target;
+            var ptc = Object.prototype.toString.call(target);
+            var result;
+            if (tt === "thymol.ThSet") {
+                result = target;
+            }
+            if (tt === "Array" || ptc === "[object Array]") {
+                result = thymol.ThSet.prototype.fromArray(target);
+            } else if (tt === "object") {
+                result = new thymol.ThSet();
+                for (var k in target) {
+                    var value = target[k];
+                    var process = false;
+                    if (value !== null) {
+                        if (target instanceof thymol.ThSet) {
+                            process = target.isContent(k);
+                        } else {
+                            process = target.hasOwnProperty(k) && typeof value !== "function";
+                        }
+                    }
+                    if (process) {
+                        result.add(value);
+                    }
+                }
+            } else {
+                throw new thymol.ThError('#sets.toSet Cannot convert object of type "' + tt + '" to a set');
+            }
+            return result;
+        }
+        throw new thymol.ThError("#sets.toSet Cannot convert null to set");
+    }
+    function size(target) {
+        if (target !== null) {
+            if (target instanceof thymol.ThSet) {
+                return target.size();
+            }
+            throw new thymol.ThError('#sets.size Cannot get size of non-set type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#sets.size Cannot get size of null");
+    }
+    function isEmpty(target) {
+        if (target !== null) {
+            if (target instanceof thymol.ThSet) {
+                return target.isEmpty();
+            }
+            throw new thymol.ThError('#sets.size Cannot get isEmpty of non-set type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#sets.size Cannot get isEmpty of null");
+    }
+    function contains(target, element) {
+        if (target !== null) {
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    if (target[k] === null) {
+                        if (element === null) {
+                            return true;
+                        }
+                    } else if (element !== null && target[k] === element) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+        throw new thymol.ThError("#sets.contains Cannot execute sets contains: target is null");
+    }
+    function containsAll(target, elements) {
+        if (target !== null) {
+            if (elements !== null) {
+                var elementsArray;
+                if (elements instanceof Array) {
+                    elementsArray = [].concat(elements);
+                } else {
+                    if (elements instanceof thymol.ThSet) {
+                        elementsArray = elements.toArray();
+                    } else {
+                        elementsArray = [];
+                        for (var k in elements) {
+                            if (elements.hasOwnProperty(k) && typeof elements[k] !== "function") {
+                                elementsArray.push(elements[k]);
+                            }
+                        }
+                    }
+                }
+                for (var k in target) {
+                    if (target.isContent(k)) {
+                        for (var j = 0, jLimit = elementsArray.length; j < jLimit; j++) {
+                            if (target[k] === elementsArray[j]) {
+                                elementsArray.splice(j, 1);
+                            }
+                        }
+                    }
+                }
+                return elementsArray.length === 0;
+            }
+            throw new thymol.ThError("#sets.containsAll Cannot execute sets containsAll: elements is null");
+        }
+        throw new thymol.ThError("#sets.containsAll Cannot execute sets containsAll: target is null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        toSet: toSet,
+        size: size,
+        isEmpty: isEmpty,
+        contains: contains,
+        containsAll: containsAll
+    };
+}();
+
+thymol.objects.thStringsObject = function() {
+    var thExpressionObjectName = "#strings";
+    function toString(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString();
+        }
+        return result;
+    }
+    function arrayToString(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(target[i].toString());
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setToString(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(toString(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    function abbreviate(target, maxSize, source) {
+        if (maxSize >= 3) {
+            var result = null;
+            if (target !== null && typeof target !== "undefined") {
+                result = target.toString();
+                if (result.length > maxSize) {
+                    result = result.substring(0, maxSize - 3) + "...";
+                }
+            }
+            return result;
+        }
+        throwAbbreviateException("abbreviate", maxSize);
+    }
+    function arrayAbbreviate(target, maxSize) {
+        if (maxSize >= 3) {
+            var result = null;
+            if (target !== null && typeof target !== "undefined") {
+                result = [];
+                for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                    result.push(abbreviate(target[i], maxSize));
+                }
+            }
+            return result;
+        }
+        throwAbbreviateException("arrayAbbreviate", maxSize);
+    }
+    function setAbbreviate(target, maxSize) {
+        if (maxSize >= 3) {
+            var result = null;
+            if (target !== null && typeof target !== "undefined") {
+                result = new thymol.ThSet();
+                for (var k in target) {
+                    if (target.isContent(k)) {
+                        result.add(abbreviate(target[k], maxSize));
+                    }
+                }
+            }
+            return result;
+        }
+        throwAbbreviateException("setAbbreviate", maxSize);
+    }
+    function throwAbbreviateException(source, maxSize) {
+        throw new thymol.ThError("#strings." + source + ' Maximum size must be greater than or equal to 3 but was: "' + maxSize + '"');
+    }
+    function equals(o1, o2) {
+        if (o1 === null) {
+            return o2 === null;
+        } else if (o2 !== null) {
+            return o1.toString() === o2.toString();
+        }
+        return false;
+    }
+    function equalsIgnoreCase(o1, o2) {
+        if (o1 === null) {
+            return o2 === null;
+        } else if (o2 !== null) {
+            return o1.toString().toLowerCase() === o2.toString().toLowerCase();
+        }
+        return false;
+    }
+    function contains(target, fragment) {
+        if (target !== null) {
+            if (fragment !== null) {
+                return target.toString().indexOf(fragment) >= 0;
+            }
+            throw new thymol.ThError("#strings.contains Fragment cannot be null");
+        }
+        throw new thymol.ThError("#strings.contains Cannot apply contains on null");
+    }
+    function arrayContains(target, fragment) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(contains(target[i], fragment));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayContains Cannot apply arrayContains on null");
+    }
+    function setContains(target, fragment) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(contains(target[k], fragment));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setContains Cannot apply setContains on null");
+    }
+    function containsIgnoreCase(target, fragment) {
+        if (target !== null) {
+            if (fragment !== null) {
+                return target.toString().toLowerCase().indexOf(fragment.toLowerCase()) >= 0;
+            }
+            throw new thymol.ThError("#strings.containsIgnoreCase Fragment cannot be null");
+        }
+        throw new thymol.ThError("#strings.containsIgnoreCase Cannot apply containsIgnoreCase on null");
+    }
+    function arrayContainsIgnoreCase(target, fragment) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(containsIgnoreCase(target[i], fragment));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayContainsIgnoreCase Cannot apply arrayContainsIgnoreCase on null");
+    }
+    function setContainsIgnoreCase(target, fragment) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(containsIgnoreCase(target[k], fragment));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setContainsIgnoreCase Cannot apply setContainsIgnoreCase on null");
+    }
+    function startsWith(target, prefix) {
+        if (target !== null) {
+            if (prefix !== null) {
+                return target.toString().indexOf(prefix) === 0;
+            }
+            throw new thymol.ThError("#strings.startsWith Prefix cannot be null");
+        }
+        throw new thymol.ThError("#strings.startsWith Cannot apply startsWith on null");
+    }
+    function arrayStartsWith(target, prefix) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(startsWith(target[i], prefix));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayStartsWith Target cannot be null");
+    }
+    function setStartsWith(target, prefix) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(startsWith(target[k], prefix));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setStartsWith Target cannot be null");
+    }
+    function endsWith(target, suffix) {
+        if (target !== null) {
+            if (suffix !== null) {
+                var str = target.toString();
+                return str.indexOf(suffix) === str.length - suffix.length;
+            }
+            throw new thymol.ThError("#strings.startsWith Suffix cannot be null");
+        }
+        throw new thymol.ThError("#strings.endsWith Cannot apply endsWith on null");
+    }
+    function arrayEndsWith(target, suffix) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(endsWith(target[i], suffix));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayEndsWith Target cannot be null");
+    }
+    function setEndsWith(target, suffix) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(endsWith(target[k], suffix));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setEndsWith Target cannot be null");
+    }
+    function substring(target, start, end) {
+        if (target !== null) {
+            return target.toString().substring(start, end);
+        }
+        throw new thymol.ThError("#strings.substring Target cannot be null");
+    }
+    function arraySubstring(target, start, end) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(substring(target[i], start, end));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arraySubstring Target cannot be null");
+    }
+    function setSubstring(target, start, end) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(substring(target[k], start, end));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setSubstring Target cannot be null");
+    }
+    function substringAfter(target, substr) {
+        if (target !== null) {
+            if (substr !== null) {
+                var str = target.toString();
+                var indx = str.indexOf(substr);
+                if (indx < 0) {
+                    return null;
+                }
+                return str.substring(indx + substr.length);
+            }
+            throw new thymol.ThError("#strings.substringAfter Parameter substring cannot be null");
+        }
+        throw new thymol.ThError("#strings.substringAfter Cannot apply substringAfter on null");
+    }
+    function arraySubstringAfter(target, substr) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(substringAfter(target[i], substr));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arraySubstringAfter Cannot apply arraySubstringAfter on null");
+    }
+    function setSubstringAfter(target, substr) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(substringAfter(target[k], substr));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setSubstringAfter Cannot apply setSubstringAfter on null");
+    }
+    function substringBefore(target, substr) {
+        if (target !== null) {
+            if (substr !== null) {
+                var str = target.toString();
+                var indx = str.indexOf(substr);
+                if (indx < 0) {
+                    return null;
+                }
+                return str.substring(0, indx);
+            }
+            throw new thymol.ThError("#strings.substringBefore Parameter substring cannot be null");
+        }
+        throw new thymol.ThError("#strings.substringBefore Cannot apply substringBefore on null");
+    }
+    function arraySubstringBefore(target, substr) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(substringBefore(target[i], substr));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arraySubstringBefore Cannot apply arraySubstringBefore on null");
+    }
+    function setSubstringBefore(target, substr) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(substringBefore(target[k], substr));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setSubstringBefore Cannot apply setSubstringBefore on null");
+    }
+    function prepend(target, prefix) {
+        if (target !== null) {
+            if (prefix !== null) {
+                return prefix.toString() + target.toString();
+            }
+            throw new thymol.ThError("#strings.prepend Prefix cannot be null");
+        }
+        throw new thymol.ThError("#strings.prepend Cannot apply prepend on null");
+    }
+    function arrayPrepend(target, prefix) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(prepend(target[i], prefix));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayPrepend Cannot apply arrayPrepend on null");
+    }
+    function setPrepend(target, prefix) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(prepend(target[k], prefix));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setPrepend Cannot apply setPrepend on null");
+    }
+    function repeat(target, times) {
+        var result = "";
+        for (var i = 0; i < times; i++) {
+            result += target.toString();
+        }
+        return result;
+    }
+    function append(target, suffix) {
+        if (target !== null) {
+            if (suffix !== null) {
+                return target.toString() + suffix.toString();
+            }
+            throw new thymol.ThError("#strings.append Suffix cannot be null");
+        }
+        throw new thymol.ThError("#strings.append Cannot apply append on null");
+    }
+    function concat() {
+        var result = "";
+        for (var i = 0, iLimit = arguments.length; i < iLimit; i++) {
+            if (arguments[i] !== null) {
+                result += arguments[i];
+            }
+        }
+        return result;
+    }
+    function concatReplaceNulls() {
+        var result = "";
+        for (var i = 1, iLimit = arguments.length; i < iLimit; i++) {
+            if (arguments[i] === null) {
+                result += arguments[0];
+            } else {
+                result += arguments[i];
+            }
+        }
+        return result;
+    }
+    function arrayAppend(target, suffix) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(append(target[i], suffix));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayAppend Target cannot be null");
+    }
+    function setAppend(target, suffix) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(append(target[k], suffix));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setAppend Target cannot be null");
+    }
+    function indexOf(target, fragment) {
+        if (target !== null) {
+            if (fragment !== null) {
+                var str = target.toString();
+                var indx = str.indexOf(fragment);
+                return indx;
+            }
+            throw new thymol.ThError("#strings.indexOf Fragment cannot be null");
+        }
+        throw new thymol.ThError("#strings.indexOf Cannot apply indexOf on null");
+    }
+    function arrayIndexOf(target, fragment) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(indexOf(target[i], fragment));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayIndexOf Cannot apply arrayIndexOf on null");
+    }
+    function setIndexOf(target, fragment) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(indexOf(target[k], fragment));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setIndexOf Cannot apply setIndexOf on null");
+    }
+    function isEmpty(target) {
+        if (target !== null) {
+            var str = target.toString();
+            if (str !== null) {
+                str = str.replace(/(?:[\\]t)/g, "      ").replace(/(?:[\\]n)/g, "\n").replace(/(?:[\\]v)/g, "\v").replace(/(?:[\\]f)/g, "\f").replace(/(?:[\\]r)/g, "\r");
+                str = str.trim();
+                if (str.length !== 0) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+    function arrayIsEmpty(target) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(isEmpty(target[i]));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayIsEmpty Target cannot be null");
+    }
+    function setIsEmpty(target) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(isEmpty(target[k]));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setIsEmpty Target cannot be null");
+    }
+    function arrayJoin(stringArray, separator) {
+        if (stringArray !== null) {
+            if (separator !== null) {
+                var sepStr = separator.toString();
+                var result = "";
+                for (var i = 0, iLimit = stringArray.length; i < iLimit; i++) {
+                    if ("" !== result) {
+                        result += sepStr;
+                    }
+                    result += stringArray[i];
+                }
+                return result;
+            }
+            throw new thymol.ThError("#strings.arrayJoin Separator cannot be null");
+        }
+        throw new thymol.ThError("#strings.arrayJoin Cannot apply join on null");
+    }
+    function setJoin(stringSet, separator) {
+        if (stringSet !== null) {
+            if (separator !== null) {
+                var sepStr = separator.toString();
+                var result = "";
+                for (var k in stringSet) {
+                    if (stringSet.isContent(k)) {
+                        if ("" !== result) {
+                            result += sepStr;
+                        }
+                        result += stringSet[k];
+                    }
+                }
+                return result;
+            }
+            throw new thymol.ThError("#strings.setJoin Separator cannot be null");
+        }
+        throw new thymol.ThError("#strings.setJoin Cannot apply join on null");
+    }
+    function doRegExpify(target, flags) {
+        var result = target.toString();
+        result = result.replace(/[\\]/g, "\\").replace(/[\^]/g, "^").replace(/[\[]/g, "[").replace(/[\]]/g, "]").replace(/[\(]/g, "(").replace(/[\)]/g, ")");
+        result = "[" + result + "]";
+        return new RegExp(result, flags);
+    }
+    function doSplit(target, separator) {
+        var re = doRegExpify(separator);
+        var splits = target.split(re);
+        var result = [];
+        for (var i = 0, iLimit = splits.length; i < iLimit; i++) {
+            if (splits[i]) {
+                result.push(splits[i]);
+            }
+        }
+        return result;
+    }
+    function arraySplit(target, separator) {
+        if (target !== null) {
+            if (separator !== null) {
+                return doSplit(target, separator);
+            }
+            throw new thymol.ThError("#strings.arraySplit Separator cannot be null");
+        }
+        throw new thymol.ThError("#strings.arraySplit Cannot apply split on null");
+    }
+    function setSplit(target, separator) {
+        if (target !== null) {
+            if (separator !== null) {
+                var result = new thymol.ThSet();
+                var splits = doSplit(target, separator);
+                for (var i = 0, iLimit = splits.length; i < iLimit; i++) {
+                    result.add(splits[i]);
+                }
+                return result;
+            }
+            throw new thymol.ThError("#strings.setSplit Separator cannot be null");
+        }
+        throw new thymol.ThError("#strings.setSplit Cannot apply split on null");
+    }
+    function length(target) {
+        if (target !== null) {
+            return target.toString().length;
+        }
+        throw new thymol.ThError("#strings.length Cannot apply length on null");
+    }
+    function arrayLength(target) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(length(target[i]));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayLength Target cannot be null");
+    }
+    function setLength(target) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(length(target[k]));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setLength Target cannot be null");
+    }
+    function getReplacer(target) {
+        var bfr = target.replace(/[$]/g, "[$]").replace(/[*]/g, "[*]").replace(/[\']/g, "[']").replace(/[+]/g, "[+]").replace(/[\(]/g, "[(]").replace(/[\)]/g, "[)]");
+        return new RegExp(bfr, "g");
+    }
+    function replace(target, before, after) {
+        if (target !== null) {
+            if (before !== null) {
+                var bfr = unescapeXml(before);
+                if (after !== null) {
+                    var re = getReplacer(bfr);
+                    var aft = unescapeXml(after);
+                    return target.replace(re, aft);
+                }
+                throw new thymol.ThError("#strings.replace After cannot be null");
+            }
+            throw new thymol.ThError("#strings.replace Before cannot be null");
+        }
+        throw new thymol.ThError("#strings.replace Cannot apply replace on null");
+    }
+    function arrayReplace(target, before, after) {
+        if (target !== null) {
+            if (before !== null) {
+                var bfr = unescapeXml(before);
+                if (after !== null) {
+                    var re = getReplacer(bfr);
+                    var aft = unescapeXml(after);
+                    var result = [];
+                    for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                        result.push(target[i].toString().replace(re, aft));
+                    }
+                    return result;
+                }
+                throw new thymol.ThError("#strings.arrayReplace After cannot be null");
+            }
+            throw new thymol.ThError("#strings.arrayReplace Before cannot be null");
+        }
+        throw new thymol.ThError("#strings.arrayReplace Cannot apply replace on null");
+    }
+    function setReplace(target, before, after) {
+        if (target !== null) {
+            if (before !== null) {
+                var bfr = unescapeXml(before);
+                if (after !== null) {
+                    var re = getReplacer(bfr);
+                    var aft = unescapeXml(after);
+                    var result = new thymol.ThSet();
+                    for (var k in target) {
+                        if (target.isContent(k)) {
+                            result.add(target[k].toString().replace(re, aft));
+                        }
+                    }
+                    return result;
+                }
+                throw new thymol.ThError("#strings.setReplace Array of 'after' values cannot be null");
+            }
+            throw new thymol.ThError("#strings.setReplace Array of 'before' values cannot be null");
+        }
+        throw new thymol.ThError("#strings.setReplace Cannot apply replace on null");
+    }
+    function multipleReplace(target, before, after) {
+        if (target !== null) {
+            if (before !== null) {
+                if (Object.prototype.toString.call(before) == "[object Array]") {
+                    if (after !== null) {
+                        if (Object.prototype.toString.call(after) == "[object Array]") {
+                            if (before.length === after.length) {
+                                var result = target;
+                                var bfr, aft;
+                                for (var i = 0, iLimit = before.length; i < iLimit; i++) {
+                                    bfr = unescapeXml(before[i]);
+                                    var re = getReplacer(bfr);
+                                    aft = unescapeXml(after[i]);
+                                    result = result.replace(re, aft);
+                                }
+                                return result;
+                            }
+                            throw new thymol.ThError("#strings.multipleReplace Arrays of 'before' and 'after' values must have the same length");
+                        }
+                        throw new thymol.ThError("#strings.multipleReplace After must be an array type");
+                    }
+                    throw new thymol.ThError("#strings.multipleReplace After cannot be null");
+                }
+                throw new thymol.ThError("#strings.multipleReplace Before must be an array type");
+            }
+            throw new thymol.ThError("#strings.multipleReplace Before cannot be null");
+        }
+        throw new thymol.ThError("#strings.multipleReplace Target cannot be null");
+    }
+    function arrayMultipleReplace(target, before, after) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(multipleReplace(target[i].toString(), before, after));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayMultipleReplace Target cannot be null");
+    }
+    function setMultipleReplace(target, before, after) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(multipleReplace(target[k].toString(), before, after));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setMultipleReplace Target cannot be null");
+    }
+    function toUpperCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString().toUpperCase();
+        }
+        return result;
+    }
+    function arrayToUpperCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(target[i].toString().toUpperCase());
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setToUpperCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(target[k].toString().toUpperCase());
+                }
+            }
+        }
+        return result;
+    }
+    function toLowerCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString().toLowerCase();
+        }
+        return result;
+    }
+    function arrayToLowerCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(target[i].toString().toLowerCase());
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setToLowerCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(target[k].toString().toLowerCase());
+                }
+            }
+        }
+        return result;
+    }
+    function trim(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString().trim();
+        }
+        return result;
+    }
+    function arrayTrim(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(target[i].toString().trim());
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setTrim(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(target[k].toString().trim());
+                }
+            }
+        }
+        return result;
+    }
+    function capitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString();
+            if (result.length > 0) {
+                result = result.charAt(0).toUpperCase() + result.substr(1);
+            }
+        }
+        return result;
+    }
+    function arrayCapitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(capitalize(target[i]));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setCapitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(capitalize(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    function unCapitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString();
+            if (result.length > 0) {
+                result = result.charAt(0).toLowerCase() + result.substr(1);
+            }
+        }
+        return result;
+    }
+    function arrayUnCapitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(unCapitalize(target[i]));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setUnCapitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(unCapitalize(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    function capitalizeWords(target, delimiters) {
+        var splitter;
+        if (typeof delimiters === "undefined") {
+            splitter = new RegExp("[^  \r\n\f\v]\\w*", "g");
+        } else {
+            var spec = "[^ " + delimiters + "]\\w*";
+            splitter = new RegExp(spec, "g");
+        }
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            var str = target.toString();
+            if (str.length > 0) {
+                result = "";
+                var matched;
+                var indx = 0;
+                while ((matched = splitter.exec(str)) !== null) {
+                    result += str.substring(indx, matched.index);
+                    result += matched[0].charAt(0).toUpperCase() + matched[0].substr(1);
+                    indx = splitter.lastIndex;
+                }
+                result += str.substring(indx);
+            }
+        }
+        return result;
+    }
+    function arrayCapitalizeWords(target, delimiters) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(capitalizeWords(target[i], delimiters));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setCapitalizeWords(target, delimiters) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(capitalizeWords(target[k], delimiters));
+                }
+            }
+        }
+        return result;
+    }
+    function escapeXml(target, escapeQuotesParam) {
+        var result = target;
+        if (target !== null && typeof target !== "undefined") {
+            var escapeQuotes = escapeQuotesParam !== null && typeof escapeQuotesParam !== "undefined" && escapeQuotesParam;
+            if (escapeQuotes) {
+                result = escapeXmlTrue(target);
+            } else {
+                result = "";
+                for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                    var c = target.charAt(i);
+                    if (c === "&") {
+                        if (!isEntityStart(target, i)) {
+                            c = "&amp;";
+                        }
+                    } else if (c === "<") {
+                        c = "&amp;lt;";
+                    } else if (c === ">") {
+                        c = "&amp;gt;";
+                    } else if (c === '"') {
+                        c = "&amp;quot;";
+                    } else if (c === "'") {
+                        c = "&amp;#39;";
+                    }
+                    result += c;
+                }
+            }
+        }
+        return result;
+    }
+    function escapeXmlTrue(target) {
+        var result = "";
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            var c = target.charAt(i);
+            if (c === "&") {
+                if (!isEntityStart(target, i)) {
+                    c = "&amp;";
+                }
+            } else if (c === "<") {
+                c = "&lt;";
+            } else if (c === ">") {
+                c = "&gt;";
+            } else if (c === '"') {
+                c = "&quot;";
+            } else if (c === "'") {
+                c = "&#39;";
+            }
+            result += c;
+        }
+        return result;
+    }
+    function unescapeXml(target) {
+        var result = "";
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            var c = target.charAt(i);
+            if (c === "&") {
+                c = isEntity(target, i);
+                if (c !== "&") {
+                    i += c.length;
+                    if (c === "&lt;") {
+                        c = "<";
+                    } else if (c === "&gt;") {
+                        c = ">";
+                    } else if (c === "&amp;") {
+                        c = "&";
+                    } else if (c === "&quot;") {
+                        c = '"';
+                    } else if (c === "&#39;") {
+                        c = "'";
+                    }
+                } else {
+                    c = "&amp;";
+                }
+            }
+            result += c;
+        }
+        return result;
+    }
+    function isEntity(buffer, position) {
+        var entity = "&";
+        var i = position + 1;
+        while (i < buffer.length) {
+            var c = buffer[i];
+            if (!(c >= "A" && c <= "Z" || c >= "a" && c <= "z" || c >= "0" && c <= "9" || c == ";" || c == "#")) {
+                return "&";
+            }
+            entity += c;
+            if (c == ";") {
+                return entity;
+            }
+            i++;
+        }
+        return "&";
+    }
+    function isEntityStart(buffer, position) {
+        var i = position + 1;
+        while (i < buffer.length) {
+            var c = buffer[i];
+            if (!(c >= "A" && c <= "Z" || c >= "a" && c <= "z" || c >= "0" && c <= "9" || c == ";" || c == "#")) {
+                return false;
+            }
+            if (c == ";") {
+                return true;
+            }
+            i++;
+        }
+        return false;
+    }
+    function arrayEscapeXml(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(escapeXml(target[i], false));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setEscapeXml(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(escapeXml(target[k], false));
+                }
+            }
+        }
+        return result;
+    }
+    function escapeJavaScript(target) {
+        var result = target;
+        if (target !== null && typeof target !== "undefined") {
+            result = escapeJavaAny(target, true);
+        }
+        return result;
+    }
+    function escapeJavaAny(target, javaScript) {
+        var result = "";
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            var c = target.charAt(i);
+            var cc = target.charCodeAt(i);
+            if (cc >= 32 && cc <= 127) {
+                switch (c) {
+                  case "\\":
+                    c = "\\";
+                    break;
+
+                  case '"':
+                    c = '\\"';
+                    break;
+
+                  case "'":
+                    if (javaScript) {
+                        c = "\\'";
+                    }
+                    break;
+
+                  case "/":
+                    if (javaScript) {
+                        if (i > 0 && target.charAt(i - 1) == "<") {
+                            c = "\\/";
+                        }
+                    }
+                    break;
+
+                  case ">":
+                    if (javaScript && i > 1) {
+                        if (target.charAt(i - 1) == "]" && target.charAt(i - 2) == "]") {
+                            c = "\\>";
+                        }
+                    }
+                    break;
+
+                  default:
+                    break;
+                }
+            } else {
+                switch (c) {
+                  case "       ":
+                    c = "\\t";
+                    break;
+
+                  case "\n":
+                    c = "\\n";
+                    break;
+
+                  case "\b":
+                    c = "\\b";
+                    break;
+
+                  case "\f":
+                    c = "\\f";
+                    break;
+
+                  case "\r":
+                    c = "\\r";
+                    break;
+
+                  default:
+                    if (javaScript) {
+                        c = hexEscape(cc);
+                    } else {
+                        c = unicodeEscape(cc);
+                    }
+                    break;
+                }
+            }
+            result += c;
+        }
+        return result;
+    }
+    function unicodeEscape(c) {
+        var x = c + 65536;
+        x = x.toString(16);
+        x = x.slice(1);
+        var output = "\\u" + x.toUpperCase();
+        return output;
+    }
+    function hexEscape(c) {
+        var x = c + 256;
+        x = x.toString(16);
+        x = x.slice(1);
+        var output = "\\x" + x.toUpperCase();
+        return output;
+    }
+    function arrayEscapeJavaScript(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(escapeJavaScript(target[i]));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setEscapeJavaScript(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(escapeJavaScript(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    function unescapeJavaScript(target) {
+        var result = target;
+        if (target !== null && typeof target !== "undefined") {
+            result = unescapeJavaAny(target);
+        }
+        return result;
+    }
+    function unescapeJavaAny(target) {
+        var result = "";
+        var unicodeSpec = "";
+        var unicodeLen = -1;
+        var hexSpec = "";
+        var hexLen = -1;
+        var lastWasEscape = false;
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            var c = target.charAt(i);
+            if (unicodeLen >= 0) {
+                unicodeSpec += c;
+                if (c >= "0" && c <= "9" || c >= "A" && c <= "F" || c >= "a" && c <= "f") {
+                    unicodeLen++;
+                    if (unicodeLen > 3) {
+                        var cc = parseInt(unicodeSpec, 16);
+                        c = String.fromCharCode(cc);
+                        unicodeSpec = "";
+                        unicodeLen = -1;
+                        result += c;
+                        lastWasEscape = false;
+                    }
+                } else {
+                    return target;
+                }
+            } else if (hexLen >= 0) {
+                hexSpec += c;
+                if (c >= "0" && c <= "9" || c >= "A" && c <= "F" || c >= "a" && c <= "f") {
+                    hexLen++;
+                    if (hexLen > 1) {
+                        var cc = parseInt(hexSpec, 16);
+                        c = String.fromCharCode(cc);
+                        hexSpec = "";
+                        hexLen = -1;
+                        result += c;
+                        lastWasEscape = false;
+                    }
+                } else {
+                    return target;
+                }
+            } else if (lastWasEscape) {
+                if (c === "u") {
+                    unicodeLen = 0;
+                } else if (c === "x") {
+                    hexLen = 0;
+                } else {
+                    switch (c) {
+                      case "t":
+                        c = "  ";
+                        break;
+
+                      case "n":
+                        c = "\n";
+                        break;
+
+                      case "b":
+                        c = "\b";
+                        break;
+
+                      case "f":
+                        c = "\f";
+                        break;
+
+                      case "r":
+                        c = "\r";
+                        break;
+
+                      default:
+                        break;
+                    }
+                    result += c;
+                    lastWasEscape = false;
+                }
+            } else if (c == "\\") {
+                lastWasEscape = true;
+            } else {
+                result += c;
+                lastWasEscape = false;
+            }
+        }
+        if (unicodeLen >= 0) {
+            result += "\\u" + unicodeSpec;
+        } else if (hexLen >= 0) {
+            result += "\\x" + hexSpec;
+        } else if (lastWasEscape) {
+            result += "\\";
+        }
+        return result;
+    }
+    function arrayUnescapeJavaScript(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(unescapeJavaScript(target[i]));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setUnescapeJavaScript(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(unescapeJavaScript(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    function escapeJava(target) {
+        var result = target;
+        if (target !== null && typeof target !== "undefined") {
+            result = escapeJavaAny(target, false);
+        }
+        return result;
+    }
+    function arrayEscapeJava(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(escapeJava(target[i]));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setEscapeJava(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(escapeJava(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    var ALPHA_NUMERIC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    function randomAlphanumeric(count) {
+        var result = "";
+        for (var i = 0; i < count; i++) {
+            result += ALPHA_NUMERIC.charAt(Math.floor(Math.random() * ALPHA_NUMERIC.length));
+        }
+        return result;
+    }
+    function defaultString(target, defaultValue) {
+        if (defaultValue !== null && typeof defaultValue !== "undefined") {
+            if (target == null) {
+                return defaultValue.toString();
+            }
+            var targetString = target.toString();
+            if (isEmpty(targetString)) {
+                return defaultValue.toString();
+            }
+            return targetString;
+        }
+        throw new thymol.ThError("#strings.defaultString defaultValue cannot be null");
+    }
+    function doArrayDefaultString(target, defaultValue) {
+        if (target == null || typeof target === "undefined") {
+            return target;
+        }
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(defaultString(target[i], defaultValue));
+        }
+        return result;
+    }
+    function arrayDefaultString(target, defaultValue) {
+        if (defaultValue !== null && typeof defaultValue !== "undefined") {
+            return doArrayDefaultString(target, defaultValue);
+        }
+        throw new thymol.ThError("#strings.arrayDefaultString defaultValue cannot be null");
+    }
+    function listDefaultString(target, defaultValue) {
+        if (defaultValue !== null && typeof defaultValue !== "undefined") {
+            return doArrayDefaultString(target, defaultValue);
+        }
+        throw new thymol.ThError("#strings.listDefaultString defaultValue cannot be null");
+    }
+    function setDefaultString(target, defaultValue) {
+        if (defaultValue !== null && typeof defaultValue !== "undefined") {
+            if (target == null || typeof target === "undefined") {
+                return target;
+            }
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(defaultString(target[k], defaultValue));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setDefaultString defaultValue cannot be null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        toString: toString,
+        arrayToString: arrayToString,
+        listToString: arrayToString,
+        setToString: setToString,
+        abbreviate: abbreviate,
+        arrayAbbreviate: arrayAbbreviate,
+        listAbbreviate: arrayAbbreviate,
+        setAbbreviate: setAbbreviate,
+        equals: equals,
+        equalsIgnoreCase: equalsIgnoreCase,
+        contains: contains,
+        arrayContains: arrayContains,
+        listContains: arrayContains,
+        setContains: setContains,
+        containsIgnoreCase: containsIgnoreCase,
+        arrayContainsIgnoreCase: arrayContainsIgnoreCase,
+        listContainsIgnoreCase: arrayContainsIgnoreCase,
+        setContainsIgnoreCase: setContainsIgnoreCase,
+        startsWith: startsWith,
+        arrayStartsWith: arrayStartsWith,
+        listStartsWith: arrayStartsWith,
+        setStartsWith: setStartsWith,
+        endsWith: endsWith,
+        arrayEndsWith: arrayEndsWith,
+        listEndsWith: arrayEndsWith,
+        setEndsWith: setEndsWith,
+        substring: substring,
+        arraySubstring: arraySubstring,
+        listSubstring: arraySubstring,
+        setSubstring: setSubstring,
+        substringAfter: substringAfter,
+        arraySubstringAfter: arraySubstringAfter,
+        listSubstringAfter: arraySubstringAfter,
+        setSubstringAfter: setSubstringAfter,
+        substringBefore: substringBefore,
+        arraySubstringBefore: arraySubstringBefore,
+        listSubstringBefore: arraySubstringBefore,
+        setSubstringBefore: setSubstringBefore,
+        prepend: prepend,
+        arrayPrepend: arrayPrepend,
+        listPrepend: arrayPrepend,
+        setPrepend: setPrepend,
+        repeat: repeat,
+        append: append,
+        concat: concat,
+        concatReplaceNulls: concatReplaceNulls,
+        arrayAppend: arrayAppend,
+        listAppend: arrayAppend,
+        setAppend: setAppend,
+        indexOf: indexOf,
+        arrayIndexOf: arrayIndexOf,
+        listIndexOf: arrayIndexOf,
+        setIndexOf: setIndexOf,
+        isEmpty: isEmpty,
+        arrayIsEmpty: arrayIsEmpty,
+        listIsEmpty: arrayIsEmpty,
+        setIsEmpty: setIsEmpty,
+        arrayJoin: arrayJoin,
+        listJoin: arrayJoin,
+        setJoin: setJoin,
+        arraySplit: arraySplit,
+        listSplit: arraySplit,
+        setSplit: setSplit,
+        length: length,
+        arrayLength: arrayLength,
+        listLength: arrayLength,
+        setLength: setLength,
+        replace: replace,
+        arrayReplace: arrayReplace,
+        listReplace: arrayReplace,
+        setReplace: setReplace,
+        multipleReplace: multipleReplace,
+        arrayMultipleReplace: arrayMultipleReplace,
+        listMultipleReplace: arrayMultipleReplace,
+        setMultipleReplace: setMultipleReplace,
+        toUpperCase: toUpperCase,
+        arrayToUpperCase: arrayToUpperCase,
+        listToUpperCase: arrayToUpperCase,
+        setToUpperCase: setToUpperCase,
+        toLowerCase: toLowerCase,
+        arrayToLowerCase: arrayToLowerCase,
+        listToLowerCase: arrayToLowerCase,
+        setToLowerCase: setToLowerCase,
+        trim: trim,
+        arrayTrim: arrayTrim,
+        listTrim: arrayTrim,
+        setTrim: setTrim,
+        capitalize: capitalize,
+        arrayCapitalize: arrayCapitalize,
+        listCapitalize: arrayCapitalize,
+        setCapitalize: setCapitalize,
+        unCapitalize: unCapitalize,
+        arrayUnCapitalize: arrayUnCapitalize,
+        listUnCapitalize: arrayUnCapitalize,
+        setUnCapitalize: setUnCapitalize,
+        capitalizeWords: capitalizeWords,
+        arrayCapitalizeWords: arrayCapitalizeWords,
+        listCapitalizeWords: arrayCapitalizeWords,
+        setCapitalizeWords: setCapitalizeWords,
+        escapeXml: escapeXml,
+        arrayEscapeXml: arrayEscapeXml,
+        listEscapeXml: arrayEscapeXml,
+        setEscapeXml: setEscapeXml,
+        escapeJavaScript: escapeJavaScript,
+        arrayEscapeJavaScript: arrayEscapeJavaScript,
+        listEscapeJavaScript: arrayEscapeJavaScript,
+        setEscapeJavaScript: setEscapeJavaScript,
+        unescapeJavaScript: unescapeJavaScript,
+        arrayUnescapeJavaScript: arrayUnescapeJavaScript,
+        listUnescapeJavaScript: arrayUnescapeJavaScript,
+        setUnescapeJavaScript: setUnescapeJavaScript,
+        escapeJava: escapeJava,
+        arrayEscapeJava: arrayEscapeJava,
+        listEscapeJava: arrayEscapeJava,
+        setEscapeJava: setEscapeJava,
+        unescapeJava: unescapeJavaScript,
+        arrayUnescapeJava: arrayUnescapeJavaScript,
+        listUnescapeJava: arrayUnescapeJavaScript,
+        setUnescapeJava: setUnescapeJavaScript,
+        randomAlphanumeric: randomAlphanumeric,
+        defaultString: defaultString,
+        arrayDefaultString: arrayDefaultString,
+        listDefaultString: listDefaultString,
+        setDefaultString: setDefaultString
+    };
+}();
+
+thymol.thObjectsConfigureModules = function() {
+    thymol.addDialect({
+        objects: [ thymol.objects.thAggregatesObject, thymol.objects.thArraysObject, thymol.objects.thBoolsObject, thymol.objects.thDatesObject, thymol.objects.thCalendarsObject, thymol.objects.thIdsObject, thymol.objects.thListsObject, thymol.objects.thMapsObject, thymol.objects.thMessagesObject, thymol.objects.thNumbersObject, thymol.objects.thObjectsObject, thymol.objects.thSetsObject, thymol.objects.thStringsObject ]
+    });
+};
+
+(function() {
+    var DOMParser_proto = thymol.thDomParser.prototype, real_parseFromString = DOMParser_proto.parseFromString;
+    try {
+        if (new thymol.thDomParser().parseFromString("", "text/html")) {
+            return;
+        }
+    } catch (ignore) {}
+    DOMParser_proto.parseFromString = function(markup, type) {
+        var res, doc;
+        if (/^\s*text\/html\s*(?:;|$)/i.test(type)) {
+            doc = thymol.thDocument.implementation.createHTMLDocument("");
+            if (markup.toLowerCase().indexOf("<!doctype") > -1) {
+                doc.documentElement.innerHTML = markup;
+            } else {
+                doc.body.innerHTML = markup;
+            }
+            res = doc;
+        } else {
+            res = real_parseFromString.apply(this, arguments);
+        }
+        return res;
+    };
+})();
+
+if (!Array.indexOf) {
+    Array.prototype.indexOf = function(obj, start) {
+        for (var i = start || 0; i < this.length; i++) {
+            if (this[i] === obj) {
+                return i;
+            }
+        }
+        return -1;
+    };
+}
+
+$(function() {
+    thymol.jqSetup($);
+    thymol.execute(document);
+});
+
+$(window).unload(function() {
+    if (thymol.sessionContext && thymol.sessionContext.persist) {
+        thymol.sessionContext.persist();
+    }
+});
\ No newline at end of file
diff --git a/dist/js/thymol-lite.js b/dist/js/thymol-lite.js
new file mode 100644 (file)
index 0000000..71dcf1d
--- /dev/null
@@ -0,0 +1,5212 @@
+/*-------------------- Thymol - the flavour of Thymeleaf --------------------*
+
+   Thymol version 2.0.0 Copyright (C) 2012-2015 James J. Benson
+   jjbenson .AT. users.sf.net (http://www.thymoljs.org/)
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" basis,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ *---------------------------------------------------------------------------*/
+
+thymol = function() {
+    thymol.thVersion = "2.0.0";
+    thymol.thReleaseDate = "2015-03-31";
+    thymol.thURL = "http://www.thymoljs.org";
+    thymol.thAltURL = "http://www.thymeleaf.org";
+    thymol.thUsingNullPrefix = false;
+    thymol.thThymeleafPrefixList = [];
+    thymol.thThymeleafElementsList = [];
+    thymol.objects = {};
+    var textFuncSynonym = "~~~~", varRefExpr = /([$#]{.*?})/, literalTokenExpr = /^[a-zA-Z0-9\[\]\.\-_]*$/, startParserLevelCommentExpr = /^\s*\/\*\s*$/, endParserLevelCommentExpr = /^\s*\*\/\s*$/, startParserLevelCommentExpr2 = /^\/\*[^\/].*/, endParserLevelCommentExpr2 = /.*[^\/]\*\/$/, prototypeOnlyCommentEscpExpr = /\/\*\/(.*)\/\*\//, varExpr3 = /[\$\*#@]{1}\{(.*)\}$/, nonURLExpr = /[\$\*#]{1}\{(?:!?[^}]*)\}/, numericExpr = /^[+\-]?[0-9]*?[.]?[0-9]*?$/, varParExpr = /([^(]*)\s*[(]([^)]*?)[)]/, domSelectExpr = /([\/]{1,2})?([A-Za-z0-9_\-]*(?:[\(][\)])?)?([^\[]\S[A-Za-z0-9_\-]*(?:[\(][\)])?[\/]*(?:[\.\/#]?[^\[]\S[A-Za-z0-9_\-]*(?:[\(][\)])?[\/]*)*)?([\[][^\]]*?[\]])?/, litSubstExpr = /\.*?([\|][^\|]*?[\|])\.*?/;
+    function Thymol() {}
+    function isClientSide() {
+        if (typeof thymol.isServerSide !== "undefined" && !!thymol.isServerSide()) {
+            thymol.isClientSide = function() {
+                return false;
+            };
+            return false;
+        }
+        thymol.isClientSide = function() {
+            return true;
+        };
+        return true;
+    }
+    function execute(doc) {
+        if (typeof thymol.protocol === "undefined") {
+            thymol.protocol = "";
+        }
+        if (typeof thymol.root === "undefined") {
+            thymol.root = "";
+        }
+        if (typeof thymol.path === "undefined") {
+            thymol.path = "";
+        }
+        thymol.thDocument = doc;
+        var theWindow = thymol.thWindow;
+        if (typeof thymol.thWindow === "undefined") {
+            if (typeof doc.defaultView !== "undefined") {
+                theWindow = doc.defaultView;
+            } else if (typeof doc.parentWindow !== "undefined") {
+                theWindow = doc.parentWindow;
+            }
+        }
+        thymol.thWindow = theWindow;
+        var theTop = thymol.thTop;
+        if (typeof thymol.thTop === "undefined") {
+            if (typeof top !== "undefined") {
+                theTop = top;
+            }
+        }
+        thymol.thTop = theTop;
+        thymol.init();
+        var base = new ThNode(thymol.thDocument, false, null, null, null, thymol.thDocument.nodeName, "::", false, thymol.thDocument);
+        Thymol.prototype.process(base);
+        postExecute();
+        return thymol.thDocument;
+    }
+    function jqSetup(jq) {
+        jq.fn.extend({
+            getComments: function() {
+                return this.filter(function() {
+                    return this.nodeType === 8;
+                });
+            },
+            getThDecorated: function(thInst) {
+                var i, iAttrName, iLength, j, jLength, instances = [], result = null, expanded = false;
+                if (thInst.escpName !== null) {
+                    instances = this.filter(thInst.escpName);
+                }
+                if (thInst.escpSynonym !== null) {
+                    instances = instances.add(this.filter(thInst.escpSynonym));
+                }
+                for (i = 0, iLength = instances.length; i < iLength; i++) {
+                    if (instances[i]) {
+                        for (j = 0, jLength = instances[i].attributes.length; j < jLength; j++) {
+                            if (instances[i].attributes[j]) {
+                                iAttrName = instances[i].attributes[j].name;
+                                if (iAttrName && (thInst.name == iAttrName || thInst.synonym == iAttrName)) {
+                                    expanded = thymol.ThUtils.processElement(thInst.process, instances[i], instances[i].attributes[j], thInst);
+                                    if (expanded) {
+                                        if (result === null) {
+                                            result = [];
+                                        }
+                                        result.push(instances[i]);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                return result;
+            }
+        });
+    }
+    function ready(func) {
+        if (typeof thymolDeferredFunctions === "undefined" || thymolDeferredFunctions === null) {
+            thymolDeferredFunctions = [];
+        }
+        thymolDeferredFunctions.push(func);
+    }
+    function setupEnv() {
+        thymol.prefix = Thymol.prototype.getThParam("thPrefix", false, false, thymol.thDefaultPrefix);
+        thymol.dataPrefix = Thymol.prototype.getThParam("thDataPrefix", false, false, thymol.thDefaultDataPrefix);
+        thymol.messagePath = Thymol.prototype.getThParam("thMessagePath", false, true, thymol.thDefaultMessagePath);
+        thymol.resourcePath = Thymol.prototype.getThParam("thResourcePath", false, true, thymol.thDefaultResourcePath);
+        thymol.messagesBaseName = Thymol.prototype.getThParam("thMessagesBaseName", false, false, thymol.thDefaultMessagesBaseName);
+        thymol.relativeRootPath = Thymol.prototype.getThParam("thRelativeRootPath", false, true, thymol.thDefaultRelativeRootPath);
+        thymol.extendedMapping = Thymol.prototype.getThParam("thExtendedMapping", true, false, thymol.thDefaultExtendedMapping);
+        thymol.localMessages = Thymol.prototype.getThParam("thLocalMessages", true, false, thymol.thDefaultLocalMessages);
+        thymol.disableMessages = Thymol.prototype.getThParam("thDisableMessages", true, false, thymol.thDefaultDisableMessages);
+        thymol.templateSuffix = Thymol.prototype.getThParam("thTemplateSuffix", false, false, thymol.thDefaultTemplateSuffix);
+        thymol.scriptPath = "";
+        if (typeof thymol.thScriptPath !== "undefined") {
+            thymol.scriptPath = Thymol.prototype.getThParam("thScriptPath", false, true, thymol.thScriptPath);
+        }
+        thymol.absolutePath = "";
+        if (typeof thymol.thAbsolutePath !== "undefined") {
+            thymol.absolutePath = Thymol.prototype.getThParam("thAbsolutePath", false, true, thymol.thAbsolutePath);
+        }
+        thymol.useAbsolutePath = false;
+        if (typeof thymol.thUseAbsolutePath !== "undefined") {
+            thymol.useAbsolutePath = Thymol.prototype.getThParam("thUseAbsolutePath", true, false, thymol.thUseAbsolutePath);
+        }
+        thymol.useFullURLPath = true;
+        if (typeof thymol.thUseFullURLPath !== "undefined") {
+            thymol.useFullURLPath = Thymol.prototype.getThParam("thUseFullURLPath", true, false, thymol.thUseFullURLPath);
+        }
+        thymol.indexFile = Thymol.prototype.getThParam("thIndexFile", false, false, null);
+        thymol.debug = Thymol.prototype.getThParam("thDebug", true, false, false);
+        thymol.allowNullText = Thymol.prototype.getThParam("thAllowNullText", true, false, true);
+        thymol.location = thymol.thLocation;
+        if ("" !== thymol.relativeRootPath) {
+            thymol.root = thymol.location + thymol.relativeRootPath;
+            thymol.messagePath = thymol.root + thymol.messagePath;
+        } else {
+            if (typeof thymol.thMessagePath !== "undefined") {
+                thymol.messagePath = Thymol.prototype.getThParam("thMessagePath", false, true, thymol.thMessagePath);
+            }
+            if (typeof thymol.thRoot !== "undefined") {
+                thymol.root = Thymol.prototype.getThParam("thRoot", false, true, thymol.thRoot);
+            }
+        }
+        thymol.root = Thymol.prototype.getThParam("thRoot", false, true, thymol.root);
+        if (typeof thymol.thPath !== "undefined") {
+            thymol.path = Thymol.prototype.getThParam("thPath", false, true, thymol.thPath);
+        }
+        thymol.path = Thymol.prototype.getThParam("thPath", false, true, thymol.path);
+        thymol.protocol = thymol.thDocument.location.protocol;
+        if ("" == thymol.protocol) {
+            thymol.protocol = thymol.thDefaultProtocol;
+        } else {
+            thymol.protocol += "//";
+            if ("" == thymol.thDocument.location.host) {
+                thymol.protocol += "/";
+            }
+        }
+        thymol.protocol = Thymol.prototype.getThParam("thProtocol", false, false, thymol.protocol);
+        thymol.resourcePath = Thymol.prototype.getThParam("thResourcePath", false, true, thymol.resourcePath);
+    }
+    function updatePrefix(pref) {
+        thymol.prefix = pref;
+        thymol.thThymeleafPrefixList = [];
+        thymol.thThymeleafElementsList = [];
+    }
+    function init() {
+        this.messages = null;
+        this.mappings = null;
+        this.debug = null;
+        getLocations(this);
+        this.locale = new thymol.ThObject();
+        getLanguage();
+        var accessor = undefined, i, iLimit, j, jLimit;
+        if (typeof thVars !== "undefined") {
+            accessor = new thymol.ThVarsAccessor(thVars, "thVars");
+        }
+        this.applicationContext = thymol.makeContext("application", accessor);
+        this.sessionContext = thymol.makeContext("session", undefined);
+        this.sessionContext.persist = function() {
+            var save = this.serialise();
+            thymol.thTop.name = save;
+        };
+        this.requestContext = thymol.makeContext("request", undefined);
+        this.booleanAndNullTokens = new Array();
+        this.booleanAndNullTokens["null"] = this.applicationContext.createVariable("null", null);
+        this.booleanAndNullTokens["true"] = this.applicationContext.createVariable("true", true);
+        this.booleanAndNullTokens["false"] = this.applicationContext.createVariable("false", false);
+        this.allowNullText = null;
+        setupEnv();
+        this.thCache = {};
+        this.thExpressionObjects;
+        this.thDeferredFunctions;
+        this.thPreExecutionFunctions;
+        this.thPostExecutionFunctions;
+        if (typeof this.thExpressionObjects === "undefined" || this.thExpressionObjects === null) {
+            this.thExpressionObjects = {};
+        }
+        this.thExpressionObjects["#object"] = {};
+        this.thExpressionObjects["#locale"] = {};
+        this.thExpressionObjects["#ctx"] = [];
+        this.thExpressionObjects["#ctx"]["variables"] = {};
+        thymol.configureModule(thymol.objects.thHttpServletRequestObject);
+        thymol.configureModule(thymol.objects.thHttpSessionObject);
+        if (typeof thymol.thObjectsConfigureModules !== "undefined") {
+            thymol.thObjectsConfigureModules();
+        }
+        var scripts = thymol.thDocument.getElementsByTagName("script");
+        for (var i = 0, iLimit = scripts.length; i < iLimit; i++) {
+            var parameters = scripts[i].getAttribute("data-thymol-load");
+            if (!!parameters) {
+                var splits = parameters.split(",");
+                for (var j = 0, jLimit = splits.length; j < jLimit; j++) {
+                    thymol.ThUtils.loadScript(splits[j]);
+                }
+            }
+        }
+        setupEnv();
+        if (typeof thymol.thPreExecutionFunctions === "undefined" || thymol.thPreExecutionFunctions === null) {
+            thymol.thPreExecutionFunctions = [];
+        }
+        if (typeof thymol.thPostExecutionFunctions === "undefined" || thymol.thPostExecutionFunctions === null) {
+            thymol.thPostExecutionFunctions = [];
+        }
+        $.ajaxSetup({
+            async: false,
+            isLocal: true,
+            dataType: "text"
+        });
+        if (!(typeof thVars === "undefined")) {
+            for (i = 0, iLimit = thVars.length; i < iLimit; i++) {
+                this.applicationContext.createVariable(thVars[i][0], thVars[i][1]);
+            }
+        }
+        executeDeferred();
+        (function() {
+            var htmlTagAttrs = $("html")[0].attributes, tp = null, tu, nsspec;
+            $([ thymol.thURL, thymol.thAltURL ]).each(function() {
+                tu = this;
+                $(htmlTagAttrs).each(function() {
+                    if (this.value == tu) {
+                        nsspec = this.localName.split(":");
+                        if (nsspec.length > 0) {
+                            tp = nsspec[nsspec.length - 1];
+                            return false;
+                        }
+                    }
+                });
+                if (tp) {
+                    thymol.updatePrefix(tp);
+                    return false;
+                }
+            });
+        })();
+        var defaultScriptUrl = "";
+        if (!!thymol.thRequest) {
+            thymol.thWindow.location.search = thymol.thRequest;
+        }
+        (function(app, req) {
+            var e, f, a = /\+/g, r = /([^&=]+)=?([^&]*)/g, d = function(s) {
+                return decodeURIComponent(s.replace(a, " "));
+            }, q = thymol.thWindow.location.search.substring(1), surl, scriptUrl = defaultScriptUrl;
+            $("script").each(function() {
+                surl = this.src;
+                if (surl.indexOf(thymol.thScriptName) >= 0) {
+                    scriptUrl = d(surl);
+                    return false;
+                }
+            });
+            while (e = r.exec(scriptUrl)) {
+                f = e[1].split("?");
+                switch (f[1]) {
+                  case "thPrefix":
+                    thymol.prefix = e[2];
+                    break;
+
+                  case "thDataPrefix":
+                    thymol.dataPrefix = e[2];
+                    break;
+
+                  case "thMessagePath":
+                    thymol.messagePath = e[2];
+                    break;
+
+                  case "thResourcePath":
+                    thymol.resourcePath = e[2];
+                    break;
+
+                  case "thMessagesBaseName":
+                    thymol.messagesBaseName = e[2];
+                    break;
+
+                  case "thRelativeRootPath":
+                    thymol.relativeRootPath = e[2];
+                    break;
+
+                  case "thExtendedMapping":
+                    thymol.extendedMapping = e[2];
+                    break;
+
+                  case "thTemplateSuffix":
+                    thymol.templateSuffix = e[2];
+                    break;
+
+                  case "thLocalMessages":
+                    thymol.localMessages = e[2];
+                    break;
+
+                  case "thDisableMessages":
+                    thymol.disableMessages = e[2];
+                    break;
+
+                  case "thIndexFile":
+                    thymol.indexFile = e[2];
+                    break;
+
+                  case "thProtocol":
+                    thymol.protocol = e[2];
+                    break;
+
+                  case "thDebug":
+                    thymol.debug = e[2];
+                    break;
+
+                  case "thRoot":
+                    thymol.root = e[2];
+                    break;
+
+                  case "thPath":
+                    thymol.path = e[2];
+                    break;
+
+                  case "thAllowNullText":
+                    thymol.allowNullText = e[2];
+                    break;
+
+                  case "thLocale":
+                    thymol.locale.value = e[2];
+                    break;
+
+                  case "thDefaultPrecision":
+                    thymol.thDefaultPrecision = e[2];
+                    break;
+
+                  case "thDefaultPrecedence":
+                    thymol.thDefaultPrecedence = e[2];
+                    break;
+
+                  default:
+                    app.createVariable(e[1], e[2]);
+                }
+            }
+            while (e = r.exec(q)) {
+                req.createVariable(d(e[1]), e[2], true);
+            }
+        })(this.applicationContext, this.requestContext);
+        thymol.thInclude = new thymol.ThAttr("include", null, 100, null, thymol.prefix);
+        thymol.thReplace = new thymol.ThAttr("replace", null, 100, null, thymol.prefix);
+        thymol.thSubstituteby = new thymol.ThAttr("substituteby", null, 100, null, thymol.prefix);
+        thymol.thFragment = new thymol.ThAttr("fragment", null, 2e4, null, thymol.prefix);
+        thymol.thRemove = null;
+        thymol.thBlock = new thymol.ThElement("block", function(element) {
+            var i, limit = element.childNodes.length;
+            for (i = 0; i < limit; i++) {
+                if (element.childNodes[i].nodeType === 1) {
+                    element.childNodes[i].isBlockChild = true;
+                }
+            }
+        }, thymol.prefix);
+        this.applicationContext.resolveJSONReferences();
+        thymol.setupAttrList();
+        preExecute(this.applicationContext);
+        this.thExpressionObjects["#vars"] = this.applicationContext;
+        this.thExpressionObjects["#root"] = this.applicationContext;
+        this.sessionContext.init();
+        this.sessionContext.resolveJSONReferences();
+        this.requestContext.resolveJSONReferences();
+        this.thExpressionObjects["#ctx"]["variables"] = this.applicationContext;
+        this.thExpressionObjects["#ctx"]["requestParameters"] = this.requestContext;
+        this.thExpressionObjects["#ctx"]["servletContext"] = this.applicationContext;
+        this.thExpressionObjects["#ctx"]["httpServletRequest"] = this.thExpressionObjects["#httpServletRequest"];
+        this.thExpressionObjects["#ctx"]["httpSession"] = this.thExpressionObjects["#httpSession"];
+        this.protocol = Thymol.prototype.override("thProtocol", this.protocol);
+        this.debug = Thymol.prototype.override("thDebug", this.debug);
+        this.root = Thymol.prototype.override("thRoot", this.root);
+        if ("" !== this.relativeRootPath) {
+            var rootURI = thymol.thDocument.location.href;
+            var quePos = rootURI.indexOf("?");
+            if (quePos >= 0) {
+                rootURI = rootURI.substring(0, quePos);
+            }
+            var sepPos = rootURI.lastIndexOf("/");
+            if (sepPos >= 0) {
+                rootURI = rootURI.substring(0, sepPos + 1);
+            }
+            var newThRoot = rootURI + this.thLocation + this.relativeRootPath;
+            this.thRoot = Thymol.prototype.getThParam("thRoot", false, true, newThRoot);
+        }
+        this.path = Thymol.prototype.override("thPath", this.path);
+        this.allowNullText = Thymol.prototype.override("thAllowNullText", this.allowNullText);
+        this.locale.value = Thymol.prototype.override("thLocale", this.locale.value);
+        if (!(typeof thMappings === "undefined")) {
+            this.mappings = [];
+            for (j = 0, jLimit = thMappings.length; j < jLimit; j++) {
+                this.mappings.push([ thMappings[j][0], thMappings[j][1] ]);
+            }
+            this.mappings.sort(function(a, b) {
+                return a[0].length > b[0].length ? -1 : 1;
+            });
+        }
+        this.messages = {};
+        setLocaleValue();
+        if (!(typeof thMessages === "undefined")) {
+            this.messages[""] = [];
+            for (j = 0, jLimit = thMessages.length; j < jLimit; j++) {
+                this.messages[""][thMessages[j][0]] = thMessages[j][1];
+            }
+            for (var k in thMessages) {
+                if (thMessages.hasOwnProperty(k)) {
+                    if (!k.match(numericExpr)) {
+                        this.messages[k] = [];
+                        for (j = 0, jLimit = thMessages[k].length; j < jLimit; j++) {
+                            this.messages[k][thMessages[k][j][0]] = thMessages[k][j][1];
+                        }
+                    }
+                }
+            }
+        }
+        if (!(typeof thDisable === "undefined")) {
+            for (j = 0, jLimit = thDisable.length; j < jLimit; j++) {
+                Thymol.prototype.doDisable(thDisable[j]);
+            }
+        }
+        thymol.thRemove = Thymol.prototype.getThAttrByName("remove");
+    }
+    function getLocations(thiz) {
+        thiz.templateName = "";
+        thiz.templatePath = "";
+        if (!!thymol.thDocument.location.href) {
+            var templateName = templatePath = thymol.thDocument.location.href;
+            thiz.templateName = templateName.substring(0, templateName.indexOf(".") == -1 ? templateName.length : templateName.lastIndexOf("."));
+            thiz.templatePath = templatePath.substring(0, templatePath.indexOf("/") == -1 ? 0 : templatePath.lastIndexOf("/") + 1);
+        }
+    }
+    function getCtx() {
+        return thymol.thExpressionObjects["#ctx"];
+    }
+    function configureModule(module) {
+        if (typeof thymol.thExpressionObjects === "undefined" || thymol.thExpressionObjects === null) {
+            thymol.thExpressionObjects = {};
+        }
+        thymol.thExpressionObjects[module.thExpressionObjectName] = module;
+    }
+    function configureAttributeProcessor(prefix, suffix, func, prec, dataAttr) {
+        var p = prefix + ":";
+        if (p !== null) {
+            if (thymol.thThymeleafPrefixList.indexOf(p) < 0) {
+                thymol.thThymeleafPrefixList.push(p);
+            }
+        } else {
+            thymol.thUsingNullPrefix = true;
+        }
+        p = new thymol.ThAttr(suffix, func, prec, thymol.thThymeleafPrefixList, prefix, dataAttr);
+    }
+    function configureElementProcessor(prefix, suffix, func) {
+        var p = new thymol.ThElement(suffix, func, prefix);
+    }
+    function configurePreExecution(func) {
+        if (typeof thymol.thPreExecutionFunctions === "undefined" || thymol.thPreExecutionFunctions === null) {
+            thymol.thPreExecutionFunctions = [];
+        }
+        thymol.thPreExecutionFunctions.push(func);
+    }
+    function configurePostExecution(func) {
+        if (typeof thymol.thPostExecutionFunctions === "undefined" || thymol.thPostExecutionFunctions === null) {
+            thymol.thPostExecutionFunctions = [];
+        }
+        thymol.thPostExecutionFunctions.push(func);
+    }
+    function executeDeferred() {
+        if (typeof thymolDeferredFunctions !== "undefined" && thymolDeferredFunctions !== null) {
+            while (thymolDeferredFunctions.length > 0) {
+                var func = thymolDeferredFunctions.pop();
+                func();
+            }
+        }
+    }
+    function preExecute(context) {
+        while (thymol.thPreExecutionFunctions.length > 0) {
+            var func = thymol.thPreExecutionFunctions.pop();
+            func();
+            context.resolveJSONReferences();
+        }
+    }
+    function postExecute() {
+        while (thymol.thPostExecutionFunctions.length > 0) {
+            var func = thymol.thPostExecutionFunctions.pop();
+            func();
+        }
+    }
+    function preProcess(expr, element) {
+        var result = expr, fp, lp;
+        do {
+            fp = result.indexOf("__");
+            if (fp >= 0) {
+                lp = -1;
+                if (result.length > 4) {
+                    lp = result.lastIndexOf("__");
+                }
+                if (lp <= 0) {
+                    throw new thymol.ThError("Mismatched pre-processing indicators", element);
+                }
+                var head = result.substring(0, fp);
+                var centre = result.substring(fp + 2, lp);
+                centre = this.getParsedExpr(centre, element);
+                var tail = result.substring(lp + 2);
+                result = head + centre + tail;
+                fp = result.indexOf("__");
+            }
+        } while (fp >= 0);
+        result = result.replace(/\\_\\_/g, "__");
+        return result;
+    }
+    function substituteParam(argValue, mode, element) {
+        var result = argValue, varName = argValue, subs = null, msg, expo;
+        if (result) {
+            if (mode === 4) {
+                msg = thymol.getMessage(varName);
+                if (msg) {
+                    subs = msg;
+                }
+            } else if (mode === 6) {
+                subs = argValue;
+            } else {
+                var token = thymol.booleanAndNullTokens[result];
+                if (!(typeof token === "undefined")) {
+                    if (token === null) {
+                        subs = null;
+                    } else {
+                        subs = token.value;
+                    }
+                } else {
+                    if (varName.charAt(0) === "#") {
+                        if ("#object" === varName) {
+                            if (element.thObjectVar) {
+                                subs = element.thObjectVar;
+                            }
+                        } else {
+                            expo = thymol.thExpressionObjects[varName];
+                            if (typeof expo !== "undefined" && expo !== null) {
+                                subs = expo;
+                            }
+                        }
+                    }
+                    if ((typeof subs === "undefined" || subs == null) && element.thObjectVar) {
+                        subs = element.thObjectVar[varName];
+                    }
+                    if ((typeof subs === "undefined" || subs == null) && element.thLocalVars) {
+                        subs = element.thLocalVars[varName];
+                    }
+                    if (typeof subs === "undefined" || subs == null) {
+                        subs = thymol.ThUtils.getParameter(varName);
+                    }
+                    if (typeof subs === "undefined" || subs == null) {
+                        if ("param" === varName) {
+                            subs = thymol.requestContext;
+                        }
+                        if ("session" === varName) {
+                            subs = thymol.sessionContext;
+                        }
+                        if ("application" === varName) {
+                            subs = thymol.applicationContext;
+                        }
+                    }
+                    if (mode === 2 && (typeof subs === "undefined" || subs == null)) {
+                        subs = argValue;
+                    }
+                }
+            }
+            result = subs;
+            if (subs instanceof thymol.ThParam) {
+                result = subs.value;
+            }
+        }
+        return result;
+    }
+    function getStandardURL(initial) {
+        var result = initial.trim(), mapped, head;
+        mapped = thymol.getMapped(result, thymol.extendedMapping);
+        if (mapped) {
+            result = mapped;
+        }
+        if ("/" === result && !!thymol.indexFile) {
+            result += thymol.indexFile;
+        }
+        if (!/.*:\/\/.*/.test(result)) {
+            if (/^~?\/.*$/.test(result)) {
+                if (/^~.*$/.test(result)) {
+                    result = result.substring(1);
+                }
+                if (!/^\/\/.*$/.test(result)) {
+                    if (thymol.useFullURLPath) {
+                        head = thymol.root + thymol.resourcePath;
+                        if (head != "") {
+                            if (head.charAt(head.length - 1) !== "/") {
+                                head = head + "/";
+                            }
+                            if (result.charAt(0) === "/") {
+                                result = head + result.substring(1);
+                            } else {
+                                result = head + result;
+                            }
+                        }
+                    } else {
+                        result = thymol.resourcePath + result;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    function getExpression(argValue, element) {
+        var result = argValue, subst = false, initial, shortCut, args, negate, token, lsp;
+        if (typeof argValue === "string") {
+            initial = argValue.trim();
+            result = initial;
+            if (result) {
+                shortCut = thymol.ThUtils.getParameter(result);
+                if (!shortCut) {
+                    args = result.match(varExpr3);
+                    if (args) {
+                        if (args[1] && args[1].length > 0) {
+                            shortCut = thymol.ThUtils.getParameter(args[1]);
+                        }
+                    }
+                }
+                if (shortCut) {
+                    if (shortCut instanceof thymol.ThParam) {
+                        result = shortCut.value;
+                    } else {
+                        result = shortCut;
+                    }
+                    if (typeof result === "string" && result.match(numericExpr)) {
+                        result = parseInt(result);
+                    }
+                } else {
+                    initial = thymol.ThUtils.unParenthesise(result);
+                    negate = false;
+                    if (initial.charAt(0) == "!") {
+                        negate = true;
+                        initial = initial.substring(1, initial.length);
+                        initial = thymol.ThUtils.unParenthesise(initial);
+                    }
+                    if (literalTokenExpr.test(initial)) {
+                        token = thymol.booleanAndNullTokens[initial];
+                        if (!(typeof token === "undefined")) {
+                            result = token.value;
+                            subst = true;
+                        }
+                    }
+                    lsp = null;
+                    if (!subst) {
+                        lsp = initial.match(litSubstExpr);
+                        if (lsp && lsp.length > 0) {
+                            if (thymol.ThUtils.charOcurrences(lsp[1], "'") < 2) {
+                                initial = Thymol.prototype.doLiteralSubstExpr(initial, lsp[1]);
+                            }
+                        }
+                        result = "";
+                        if (initial != "") {
+                            initial = thymol.ThUtils.unParenthesise(initial);
+                            initial = thymol.preProcess(initial, element);
+                            result = thymol.getParsedExpr(initial, element, true);
+                        }
+                    }
+                    if (result == initial && typeof result == typeof initial) {
+                        result = null;
+                    } else if (typeof result === "string") {
+                        if (!lsp) {
+                            result = result.replace(/[\\][\\]/g, "\\");
+                        }
+                        result = result.replace(/&#39;/g, "'").replace(/&apos;/gi, "'");
+                    }
+                    if (negate) {
+                        if (typeof result === "boolean") {
+                            result = !result;
+                        } else if (typeof result === "number") {
+                            result = result == 0;
+                        } else if (typeof result === "string") {
+                            result = !thymol.ThUtils.testLiteralFalse(result);
+                        }
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    function getMapped(uri, extended) {
+        var mapped = null, i, iLimit, key;
+        if (uri && typeof uri === "string") {
+            if (thymol.mappings) {
+                for (i = 0, iLimit = thymol.mappings.length; i < iLimit; i++) {
+                    key = thymol.mappings[i][0];
+                    if (uri == key) {
+                        mapped = thymol.mappings[i][1];
+                        break;
+                    } else if (extended) {
+                        if (uri.indexOf(key) == 0) {
+                            mapped = uri.substring(key.length);
+                            mapped = thymol.mappings[i][1] + mapped;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        return mapped;
+    }
+    function substitute(initial, element, lenient) {
+        var argValue = initial, result, args, token, re, subs, saved;
+        if (typeof argValue === "string") {
+            argValue = argValue.trim();
+        }
+        result = argValue;
+        args = "";
+        while (args != null) {
+            args = argValue.match(/.*([$\*#@]{(!?[^}]*)}).*/);
+            if (args != null && args.length > 0) {
+                if (args.length == 3) {
+                    token = args[1];
+                    token = token.replace(/[$]/g, "[$]").replace(/[*]/g, "[*]").replace(/[\']/g, "[']").replace(/[+]/g, "[+]").replace(/[\(]/g, "[(]").replace(/[\)]/g, "[)]");
+                    re = new RegExp(token);
+                    subs = this.getExpression(args[2], element);
+                    if (subs != args[2]) {
+                        result = result.replace(re, subs, "g");
+                        if (result == "null") {
+                            result = null;
+                        }
+                    } else {
+                        subs = "";
+                        if (thymol.debug && !lenient) {
+                            thymol.thWindow.alert('thymol variable substitution failed: "' + initial + '"');
+                        }
+                    }
+                    saved = argValue;
+                    argValue = argValue.replace(re, subs, "g");
+                    if (saved == argValue) {
+                        argValue = "";
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    function getWith(element, content) {
+        var argValue = content.trim(), argCount = 0;
+        if (argValue) {
+            do {
+                var argsExpr = thymol.ThParser.parse(argValue, true, false);
+                var identifier = argsExpr.tokens.shift();
+                if (identifier.type_ === 3) {
+                    var result = argsExpr.evaluate(element);
+                    var varName = identifier.index_;
+                    if (!!varName) {
+                        argCount++;
+                        if (!element.thLocalVars) {
+                            element.thLocalVars = {};
+                        }
+                        element.thLocalVars[varName] = result;
+                    }
+                    argValue = argValue.substring(argsExpr.position);
+                } else {
+                    break;
+                }
+            } while (argValue.length > 0);
+        }
+        return argCount;
+    }
+    function getParsedExpr(initial, element, preprocessed) {
+        var expr, result = initial;
+        expr = thymol.ThParser.parse(result, false, preprocessed);
+        expr = expr.simplify();
+        result = expr.evaluate(element);
+        if (typeof result === "number") {
+            result = thymol.ThUtils.getToPrecision(result, expr.precision);
+        }
+        return result;
+    }
+    function getBooleanValue(param) {
+        var flag = false, val, args;
+        if (param != null) {
+            if (typeof param === "boolean") {
+                flag = param;
+            } else if (typeof param === "number") {
+                flag = param != 0;
+            } else {
+                val = param;
+                if (Object.prototype.toString.call(val) === "[object Array]") {
+                    if (val.length === 1) {
+                        val = val[0];
+                    } else {
+                        val = true;
+                    }
+                }
+                if (typeof val === "boolean") {
+                    flag = val;
+                } else if (typeof val === "number") {
+                    flag = val != 0;
+                } else if (typeof val === "string") {
+                    args = val.match(nonURLExpr);
+                    if (args) {
+                        val = args[1];
+                        flag = this.testParam(val);
+                    } else {
+                        flag = !thymol.ThUtils.testLiteralFalse(val);
+                    }
+                } else if (val instanceof thymol.ThParam) {
+                    flag = val.getBooleanValue();
+                } else {
+                    flag = typeof val !== "undefined" && val !== null;
+                }
+            }
+        }
+        return flag;
+    }
+    function isFragmentChild(element) {
+        var result = false, parent = element.parentElement;
+        while (parent) {
+            if (parent.getAttribute(thymol.thFragment.name) || parent.getAttribute(thymol.thFragment.synonym)) {
+                result = true;
+                break;
+            }
+            parent = parent.parentElement;
+        }
+        return result;
+    }
+    function setLocale(locValue) {
+        thymol.locale.value = locValue;
+        setLocaleValue();
+    }
+    function getLocale() {
+        return thymol.locale.value;
+    }
+    function getLanguage() {
+        if (!thymol.locale.value) {
+            if (typeof navigator !== "undefined" && !!navigator) {
+                var userLang = navigator.language || navigator.userLanguage || navigator.browserLanguage || navigator.systemLanguage;
+                if (!!userLang) {
+                    thymol.locale.value = userLang.replace(/\-/g, "_");
+                }
+            }
+        }
+    }
+    function setLocaleValue() {
+        if (!thymol.locale.value) {
+            thymol.locale.value = thymol.thDefaultLocale;
+        }
+        var sepPos;
+        var locale = thymol.locale.value.replace(/\-/g, "_");
+        var level = thymol.locale.value;
+        var levels = [];
+        var part, parts = [];
+        do {
+            levels.push(level);
+            sepPos = locale.lastIndexOf("_");
+            if (sepPos >= 0) {
+                part = locale.substring(sepPos + 1);
+                parts.push(part);
+                locale = locale.substring(0, sepPos);
+                level = level.substring(0, sepPos);
+            }
+        } while (sepPos >= 0);
+        thymol.locale.language = level;
+        if (!!parts) {
+            parts.reverse();
+            for (var i = 0, iLimit = parts.length; i < iLimit; i++) {
+                if (i === 0) {
+                    thymol.locale.country = parts[i];
+                } else if (i === 1) {
+                    thymol.locale.variant = parts[i];
+                }
+            }
+        }
+        thymol.locale.levels = levels;
+        thymol.thExpressionObjects["#ctx"]["locale"] = thymol.locale;
+        thymol.thExpressionObjects["#locale"] = thymol.locale;
+    }
+    function getMessage(varName, parameters, returnStringAlways) {
+        if (thymol.disableMessages) {
+            return undefined;
+        }
+        var msgKey = null;
+        var locale;
+        if (!!thymol.locale.levels) {
+            var prefix = "$";
+            var ident, section, jLower = thymol.localMessages ? 0 : 1;
+            for (var j = jLower; j < 2; j++) {
+                for (var i = 0, iLimit = thymol.locale.levels.length; i < iLimit + 1; i++) {
+                    ident = prefix;
+                    if (i < iLimit) {
+                        locale = thymol.locale.levels[i];
+                    } else {
+                        locale = "";
+                    }
+                    ident = ident + locale;
+                    section = thymol.messages[ident];
+                    if (!section) {
+                        if (j < 1) {
+                            section = getLocalMessages(locale);
+                        } else {
+                            section = getDefaultMessages(locale);
+                        }
+                    }
+                    if (!!section) {
+                        thymol.messages[ident] = section;
+                        msgKey = section[varName];
+                        if (!!msgKey) {
+                            break;
+                        }
+                    }
+                }
+                if (!!msgKey) {
+                    break;
+                }
+                prefix += "$";
+            }
+        }
+        if (!msgKey) {
+            for (var i = 0, iLimit = thymol.locale.levels.length; i <= iLimit; i++) {
+                if (i < iLimit) {
+                    locale = thymol.locale.levels[i];
+                } else {
+                    locale = "";
+                }
+                if (!!thymol.messages[locale]) {
+                    msgKey = thymol.messages[locale][varName];
+                    if (!!msgKey) {
+                        break;
+                    }
+                }
+            }
+        }
+        if (!!msgKey) {
+            if (typeof parameters === "undefined") {
+                return msgKey;
+            } else {
+                return thymol.ThUtils.renderMessage(msgKey, parameters);
+            }
+        } else if (returnStringAlways !== undefined && returnStringAlways) {
+            return "??" + varName + "_" + thymol.locale.value + "??";
+        }
+        return null;
+    }
+    function getProperties(propFile) {
+        var props = null;
+        var messages = [];
+        $.get(propFile, function(textContent, status) {
+            var err = null;
+            try {
+                if ("success" == status) {
+                    props = textContent;
+                } else if (thymol.debug) {
+                    thymol.thWindow.alert("read failed: " + propFile);
+                }
+            } catch (err) {
+                if (thymol.debug) {
+                    thymol.thWindow.alert("properties file read failed: " + propFile + " error: " + err);
+                }
+            }
+        }, "text");
+        if (props !== null) {
+            var splits = props.split("\n");
+            if (splits.length > 0) {
+                for (var i = 0, iLimit = splits.length; i < iLimit; i++) {
+                    var line = splits[i].trim();
+                    if (line.charAt(0) !== "#") {
+                        var p = line.split("=");
+                        if (p.length > 1) {
+                            messages[p[0].trim()] = thymol.ThUtils.unicodeUnescape(p[1].trim());
+                        }
+                    }
+                }
+            }
+        }
+        return messages;
+    }
+    function getLocalMessages(locale) {
+        var messages = [];
+        if (!!thymol.thDocument.location.href) {
+            var propsFile = thymol.templateName;
+            if (!!locale && locale !== "") {
+                propsFile += "_" + locale;
+            }
+            propsFile += ".properties";
+            messages = getProperties(propsFile);
+        }
+        return messages;
+    }
+    function getDefaultMessages(locale) {
+        var messages = null;
+        var propsPath = "";
+        if (thymol.useAbsolutePath) {
+            propsPath += thymol.protocol + thymol.root + thymol.path;
+        }
+        propsPath += thymol.messagePath;
+        if (propsPath !== "") {
+            propsPath += "/";
+        }
+        var propsFile = propsPath + thymol.messagesBaseName;
+        if (!!locale && locale !== "") {
+            propsFile += "_" + locale;
+        }
+        propsFile += ".properties";
+        messages = getProperties(propsFile);
+        return messages;
+    }
+    Thymol.prototype = {
+        process: function(rootNode) {
+            var n = rootNode;
+            try {
+                while (n.thDoc) {
+                    this.getChildren(n);
+                    if (n.firstChild && n.firstChild.thDoc && !n.visited) {
+                        n.visited = true;
+                        n = n.firstChild;
+                    } else {
+                        if (n.element != n.thDoc) {
+                            this.doReplace(n.isNode, n.element, n.thDoc);
+                            if (!n.isNode) {
+                                n.thDoc = n.element;
+                            }
+                        }
+                        if (n.nextSibling && n.nextSibling.thDoc) {
+                            n = n.nextSibling;
+                        } else {
+                            if (n == rootNode) {
+                                break;
+                            }
+                            n = n.parentDoc;
+                        }
+                    }
+                }
+                this.processChildren(rootNode);
+            } catch (err) {
+                if (thymol.debug) {
+                    if (err instanceof thymol.ThError) {
+                        if (!err.suppress) {
+                            thymol.thWindow.alert(err);
+                        }
+                    } else {
+                        thymol.thWindow.alert(err);
+                    }
+                }
+            }
+        },
+        getChildren: function(rootNode) {
+            var count = 0, last = null, changed = false, child, froot, fstar, fchildren, i, iLimit, j, jLimit, element, matches, theAttr;
+            if (!rootNode.visited) {
+                this.processComments(rootNode);
+                var rnd = this.getContentRoot(rootNode);
+                froot = $(rnd);
+                fstar = $(froot).add(froot.find("*"));
+                fchildren = fstar.filter(thymol.thInclude.escpName).add(fstar.filter(thymol.thInclude.escpSynonym)).add(fstar.filter(thymol.thReplace.escpName)).add(fstar.filter(thymol.thReplace.escpSynonym)).add(fstar.filter(thymol.thSubstituteby.escpName)).add(fstar.filter(thymol.thSubstituteby.escpSynonym));
+                for (i = 0, iLimit = fchildren.length; i < iLimit; i++) {
+                    element = fchildren[i], matches = [];
+                    for (j = 0, jLimit = element.attributes.length; j < jLimit; j++) {
+                        theAttr = element.attributes[j];
+                        if (thymol.thInclude.name == theAttr.name || thymol.thInclude.synonym == theAttr.name || thymol.thReplace.name == theAttr.name || thymol.thReplace.synonym == theAttr.name || thymol.thSubstituteby.name == theAttr.name || thymol.thSubstituteby.synonym == theAttr.name) {
+                            matches.push(theAttr);
+                        }
+                    }
+                    for (j = 0, jLimit = matches.length; j < jLimit; j++) {
+                        child = this.processImport(element, rootNode, matches[j]);
+                        if (child != null) {
+                            changed = true;
+                            if (count == 0) {
+                                rootNode.firstChild = child;
+                            } else {
+                                last.nextSibling = child;
+                            }
+                            last = child;
+                            count++;
+                        }
+                    }
+                }
+            }
+            return changed;
+        },
+        processChildren: function(rootNode) {
+            var i, iLimit, j, jLimit, k, kLimit;
+            var elements = rootNode.thDoc.getElementsByTagName("*");
+            for (k = 0, kLimit = elements.length; k < kLimit; k++) {
+                var element = elements[k];
+                for (j = 0, jLimit = thymol.thThymeleafElementsList.length; j < jLimit; j++) {
+                    if (element.localName == thymol.thThymeleafElementsList[j].name || element.localName == thymol.thThymeleafElementsList[j].synonym) {
+                        var updated = thymol.thThymeleafElementsList[j].process(element);
+                        if (updated) {
+                            elements = rootNode.thDoc.getElementsByTagName("*");
+                            k--;
+                            kLimit = elements.length;
+                        }
+                        break;
+                    }
+                }
+                var allAttributes = element.attributes;
+                if (allAttributes && allAttributes.length > 0) {
+                    var attributes = [], aii = 0;
+                    if (!thymol.thUsingNullPrefix) {
+                        for (i = 0, iLimit = allAttributes.length; i < iLimit; i++) {
+                            var ai = allAttributes[i];
+                            if (ai) {
+                                for (j = 0, jLimit = thymol.thThymeleafPrefixList.length; j < jLimit; j++) {
+                                    var attrName = ai.name.toString();
+                                    if (attrName.length > thymol.thThymeleafPrefixList[j].length) {
+                                        attrName = attrName.substring(0, thymol.thThymeleafPrefixList[j].length);
+                                        if (attrName === thymol.thThymeleafPrefixList[j]) {
+                                            ai.order = i;
+                                            attributes[aii++] = ai;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    } else {
+                        attributes = allAttributes;
+                    }
+                    if (attributes.length > 0) {
+                        attributes.sort(function(a, b) {
+                            return b.order - a.order;
+                        });
+                        var matchedAttributes = [];
+                        for (i = 0, iLimit = attributes.length; i < iLimit; i++) {
+                            var splits = attributes[i].name.toString().split(":");
+                            if (splits && splits.length > 0) {
+                                var prefix = "", name;
+                                if (splits.length > 1) {
+                                    prefix = splits[0];
+                                    name = splits[1];
+                                } else {
+                                    name = splits[0];
+                                    var hpos = name.lastIndexOf("-");
+                                    if (hpos >= 0) {
+                                        prefix = name.substring(0, hpos + 1);
+                                    }
+                                }
+                                var attrList = thymol.thThymeleafPrefixList[prefix];
+                                if (splits.length > 1) {
+                                    prefix += ":";
+                                }
+                                if (attrList) {
+                                    for (j = 0, jLimit = attrList.length; j < jLimit; j++) {
+                                        var matched = false;
+                                        if (name === attrList[j].suffix || name === attrList[j].synonym) {
+                                            matched = true;
+                                        } else if (attrList[j].regex !== null) {
+                                            var fqn = prefix + name;
+                                            matched = attrList[j].regex.test(fqn);
+                                        }
+                                        if (matched) {
+                                            var matchedAttribute = {};
+                                            matchedAttribute.attr = attrList[j];
+                                            matchedAttribute.elementAttr = attributes[i];
+                                            matchedAttributes.push(matchedAttribute);
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (matchedAttributes.length > 0) {
+                            matchedAttributes.sort(function(a, b) {
+                                return a.attr.precedence - b.attr.precedence;
+                            });
+                            var updated = false;
+                            for (i = 0, iLimit = matchedAttributes.length; i < iLimit; i++) {
+                                var exp = thymol.ThUtils.processElement(matchedAttributes[i].attr.process, element, matchedAttributes[i].elementAttr, matchedAttributes[i].attr, 1);
+                                updated = exp || updated;
+                            }
+                            if (updated) {
+                                elements = rootNode.thDoc.getElementsByTagName("*");
+                                k--;
+                                kLimit = elements.length;
+                            }
+                        }
+                    }
+                }
+            }
+            elements = rootNode.thDoc.getElementsByTagName("*");
+            var kc = 0;
+            for (k = 0, kLimit = elements.length; k < kLimit; k++) {
+                var element = elements[kc];
+                var elName = element.nodeName.toLowerCase();
+                if (elName == thymol.thBlock.name || elName == thymol.thBlock.synonym) {
+                    thymol.ThUtils.removeTag(element);
+                    elements = rootNode.thDoc.getElementsByTagName("*");
+                } else {
+                    kc++;
+                }
+            }
+        },
+        override: function(paramName, paramValue) {
+            var param = paramValue, thv;
+            thv = thymol.thWindow[paramName];
+            if (typeof thv === "undefined") {
+                thv = thymol.applicationContext.javascriptify(paramName);
+            }
+            if (thv) {
+                if (thv instanceof thymol.ThParam) {
+                    param = thv.value;
+                } else {
+                    param = thv;
+                }
+            }
+            thv = thymol.applicationContext[paramName];
+            if (thv) {
+                if (thv instanceof thymol.ThParam) {
+                    param = thv.value;
+                } else {
+                    param = thv;
+                }
+            }
+            thv = thymol.requestContext[paramName];
+            if (thv) {
+                if (thv instanceof thymol.ThParam) {
+                    param = thv.value;
+                } else {
+                    param = thv;
+                }
+            }
+            return param;
+        },
+        doDisable: function(attrName) {
+            var tha = this.getThAttrByName(attrName);
+            if (tha !== null) {
+                tha.disable();
+            } else {
+                if (thymol.debug) {
+                    thymol.thWindow.alert('cannot disable unknown attribute "' + attrName + '"');
+                }
+            }
+        },
+        getThAttrByName: function(name) {
+            var attrList = thymol.thThymeleafPrefixList[thymol.prefix];
+            attrList.push(thymol.thInclude);
+            attrList.push(thymol.thReplace);
+            attrList.push(thymol.thSubstituteby);
+            attrList.push(thymol.thFragment);
+            var i, iLimit = attrList.length;
+            for (i = 0; i < iLimit; i++) {
+                if (name === attrList[i].suffix) {
+                    return attrList[i];
+                }
+            }
+            return null;
+        },
+        getContents: function(rootNode) {
+            var rnd = this.getContentRoot(rootNode);
+            var froot = $(rnd);
+            var fstar = froot.find("*");
+            return fstar;
+        },
+        getContentRoot: function(rn) {
+            var rnd = rn.thDoc;
+            if (rnd.nodeName !== "#document") {
+                rnd = rnd.childNodes;
+            }
+            return rnd;
+        },
+        processComments: function(rootNode) {
+            var comments = null, fstar, changed, i, iLimit, startComment, parent, startValue, pointer, nextPointer;
+            do {
+                fstar = this.getContents(rootNode);
+                comments = fstar.contents().getComments();
+                changed = false;
+                for (i = 0, iLimit = comments.length; i < iLimit; i++) {
+                    startComment = comments[i];
+                    parent = startComment.parentNode;
+                    startValue = startComment.nodeValue.trim();
+                    if (startParserLevelCommentExpr.test(startValue)) {
+                        pointer = startComment;
+                        while (pointer != null) {
+                            if (endParserLevelCommentExpr.test(pointer.nodeValue)) {
+                                changed = parent.removeChild(pointer) != null;
+                                break;
+                            }
+                            nextPointer = pointer.nextSibling;
+                            changed = parent.removeChild(pointer) != null;
+                            pointer = nextPointer;
+                        }
+                    } else if (startParserLevelCommentExpr2.test(startValue) && endParserLevelCommentExpr2.test(startValue)) {
+                        parent.removeChild(startComment);
+                        changed = true;
+                    }
+                }
+            } while (changed);
+            this.processPrototypeOnlyComments(rootNode);
+        },
+        processPrototypeOnlyComments: function(rootNode) {
+            var comments = null, fstar, changed, indexOfLast, i, iLimit, j, jLimit, k, kLimit, startComment, parent, deletions, res, fullText, innerNodes, done, next, commentText, res2, blockElement, blockDoc, blockDocBody, blockBase, newNode, newDoc;
+            do {
+                fstar = this.getContents(rootNode);
+                comments = fstar.contents().getComments();
+                changed = false;
+                indexOfLast = comments.length - 1;
+                for (i = 0, iLimit = comments.length; i < iLimit; i++) {
+                    startComment = comments[i];
+                    parent = startComment.parentNode;
+                    if (parent != null) {
+                        startValue = startComment.nodeValue.trim();
+                        deletions = [];
+                        deletions.push(startComment);
+                        startValue = startValue.replace(/\n/g, "");
+                        res = startValue.match(prototypeOnlyCommentEscpExpr);
+                        if (res) {
+                            fullText = startValue;
+                            if (parent.localName == "table" || parent.localName == "tbody") {
+                                if (startValue.indexOf(thymol.thBlock.name) >= 0 || startValue.indexOf(thymol.thBlock.synonym) >= 0) {
+                                    if (startValue.indexOf(thymol.thBlock.endName) < 0 || startValue.indexOf(thymol.thBlock.endSynonym) < 0) {
+                                        fullText = fullText.replace(res[0], res[1]);
+                                        innerNodes = [];
+                                        done = false;
+                                        next = startComment;
+                                        do {
+                                            next = next.nextSibling;
+                                            if (next != null) {
+                                                deletions.push(next);
+                                                if (i < indexOfLast) {
+                                                    if (next == comments[i + 1]) {
+                                                        commentText = next.nodeValue;
+                                                        if (commentText.indexOf(thymol.thBlock.endName) >= 0 || commentText.indexOf(thymol.thBlock.endSynonym) >= 0) {
+                                                            res2 = commentText.match(prototypeOnlyCommentEscpExpr);
+                                                            if (res2) {
+                                                                commentText = commentText.replace(res2[0], res2[1]);
+                                                                fullText = fullText + commentText;
+                                                            }
+                                                            done = true;
+                                                        }
+                                                    } else {
+                                                        innerNodes.push(next);
+                                                    }
+                                                }
+                                            } else {
+                                                done = true;
+                                            }
+                                        } while (!done);
+                                        blockElement = null;
+                                        blockDoc = new thymol.thDomParser().parseFromString(fullText, "text/html");
+                                        blockDocBody = $(blockDoc).find("body")[0];
+                                        for (j = 0, jLimit = blockDocBody.childNodes.length; j < jLimit; j++) {
+                                            if (blockDocBody.childNodes[j].localName == thymol.thBlock.name || blockDocBody.childNodes[j].localName == thymol.thBlock.synonym) {
+                                                blockElement = blockDocBody.childNodes[j];
+                                                for (k = 0, kLimit = innerNodes.length; k < kLimit; k++) {
+                                                    newNode = blockDoc.importNode(innerNodes[k], true);
+                                                    blockElement.appendChild(newNode);
+                                                }
+                                            }
+                                        }
+                                        if (blockElement != null) {
+                                            blockBase = new ThNode(blockDoc, false, null, null, null, blockDoc.nodeName, "::", false, blockDoc);
+                                            this.processChildren(blockBase);
+                                            changed = this.insertUncommented(blockBase.thDoc, deletions, parent);
+                                        } else {
+                                            parent.removeChild(startComment);
+                                            changed = true;
+                                        }
+                                    } else {
+                                        parent.removeChild(startComment);
+                                        changed = true;
+                                    }
+                                }
+                            } else {
+                                startValue = startValue.substring(3, startValue.length - 3);
+                                newDoc = new thymol.thDomParser().parseFromString(startValue, "text/html");
+                                changed = this.insertUncommented(newDoc, deletions, parent);
+                            }
+                        }
+                    }
+                }
+            } while (changed);
+        },
+        insertUncommented: function(doc, deletions, parent) {
+            var docBody = $(doc).find("body")[0], i, iLimit, newNode;
+            for (i = 0, iLimit = docBody.childNodes.length; i < iLimit; i++) {
+                if (parent.ownerDocument === doc) {
+                    newNode = docBody.childNodes[i].cloneNode(true);
+                } else {
+                    newNode = parent.ownerDocument.importNode(docBody.childNodes[i], true);
+                    newNode.parentNode = parent;
+                }
+                parent.insertBefore(newNode, deletions[0]);
+            }
+            for (i = 0, iLimit = deletions.length; i < iLimit; i++) {
+                parent.removeChild(deletions[i]);
+            }
+            return true;
+        },
+        getList: function(element, content) {
+            var argValue = content.trim(), argsCount = 0, argsList = [], assigs, i, iLimit, val;
+            if (argValue) {
+                assigs = argValue.split(",");
+                for (i = 0, iLimit = assigs.length; i < iLimit; i++) {
+                    val = thymol.getExpression(assigs[i], element);
+                    argsList[i] = val;
+                }
+                if (!element.thLocalVars) {
+                    element.thLocalVars = {};
+                }
+                element.thLocalVars["..."] = argsList;
+                argsCount = argsList.length;
+            }
+            return argsCount;
+        },
+        testParam: function(param) {
+            var initial = param, result = false, theParam = null, negate = false;
+            if (typeof initial === "boolean") {
+                result = initial;
+            } else {
+                theParam = null;
+                negate = false;
+                if (typeof initial === "object" && initial instanceof thymol.ThParam) {
+                    theParam = initial;
+                } else {
+                    initial = initial.valueOf();
+                    if (initial.charAt(0) == "!") {
+                        negate = true;
+                        initial = initial.substring(1);
+                    }
+                }
+                theParam = thymol.applicationContext[initial];
+                if (theParam != null) {
+                    result = theParam.getBooleanValue();
+                }
+                if (negate) {
+                    result = !result;
+                }
+            }
+            return result ? true : false;
+        },
+        processImport: function(element, rootNode, attr) {
+            var importNode = null, filePart, fragmentPart, names, parts, fragmentArgsList, isNode, fragment, fileName, content, importError;
+            filePart = null;
+            if (attr.value.indexOf("::") < 0) {
+                filePart = attr.value;
+                fragmentPart = "::";
+            } else {
+                names = attr.value.split("::");
+                filePart = names[0].trim();
+                fragmentPart = names[1].trim();
+            }
+            if ("this" === filePart) {
+                filePart = "";
+            } else {
+                filePart = this.getFilePath(filePart, element);
+            }
+            if (filePart != null) {
+                parts = filePart.match(varParExpr);
+                fragmentArgsList = null;
+                if (parts) {
+                    if (parts.length > 1) {
+                        filePart = parts[1].trim();
+                    }
+                    if (parts.length > 2) {
+                        fragmentArgsList = parts[2].trim();
+                    }
+                }
+                if (filePart != "" || !isFragmentChild(element)) {
+                    isNode = thymol.thReplace.name == attr.localName || thymol.thReplace.synonym == attr.localName || thymol.thSubstituteby.name == attr.localName || thymol.thSubstituteby.synonym == attr.localName;
+                    if (thymol.thCache[filePart] != null && thymol.thCache[filePart][fragmentPart] != null) {
+                        isNode = isNode || fragmentPart == "::";
+                        importNode = new ThNode(thymol.thCache[filePart][fragmentPart], false, rootNode, null, null, filePart, fragmentPart, isNode, element);
+                    } else {
+                        fragment = null;
+                        importError = null;
+                        if (filePart != "") {
+                            fileName = filePart + thymol.templateSuffix;
+                            $.get(fileName, function(textContent, status) {
+                                try {
+                                    if ("success" == status) {
+                                        content = new thymol.thDomParser().parseFromString(textContent, "text/html");
+                                        fragment = Thymol.prototype.getImportNode(element, filePart, fragmentPart, fragmentArgsList, content);
+                                    } else if (thymol.debug) {
+                                        thymol.thWindow.alert("thymol.processImport file read failed: " + filePart + " fragment: " + fragmentPart);
+                                    }
+                                } catch (err) {
+                                    importError = err;
+                                }
+                            }, "text");
+                        } else {
+                            fragment = this.getImportNode(element, filePart, fragmentPart, fragmentArgsList, thymol.thDocument);
+                        }
+                        if (fragment == null) {
+                            if (importError !== null) {
+                                throw importError;
+                            }
+                            if (thymol.debug) {
+                                thymol.thWindow.alert("thymol.processImport fragment import failed: " + filePart + " fragment: " + fragmentPart);
+                            }
+                        } else {
+                            importNode = new ThNode(fragment, false, rootNode, null, null, filePart, fragmentPart, isNode, element);
+                        }
+                    }
+                }
+            }
+            element.removeAttribute(attr.name);
+            return importNode;
+        },
+        getImportNode: function(element, filePart, fragmentArg, fragmentArgsList, content) {
+            var result = null, fragmentName = fragmentArg.trim(), fragmentPart = fragmentName, parts, argsCount, matched, fragment, htmlContent, fragArray, i, iLimit, j, jLimit, k, clean, bare, vlParts, vlArgs, argsList, varName, newElement;
+            fragmentName = fragmentName.replace(/text\(\)/g, textFuncSynonym);
+            parts = fragmentName.match(varParExpr);
+            if (parts == null && fragmentArgsList != null) {
+                parts = [];
+                parts[1] = fragmentName;
+                parts[2] = fragmentArgsList;
+            }
+            argsCount = 0;
+            if (parts) {
+                if (parts.length > 1) {
+                    fragmentName = parts[1].trim();
+                    if (parts.length > 2) {
+                        if (parts[2].indexOf("=") > 0) {
+                            argsCount = thymol.getWith(element, parts[2]);
+                        } else {
+                            argsCount = this.getList(element, parts[2]);
+                        }
+                    }
+                }
+            }
+            if (thymol.thCache[filePart] == null) {
+                thymol.thCache[filePart] = new Object();
+            }
+            matched = false;
+            fragment = null;
+            if (fragmentName == "::") {
+                htmlContent = $("html", content)[0];
+                result = htmlContent;
+                matched = true;
+            } else {
+                fragArray = $(thymol.thFragment.escpName, content);
+                for (i = 0, iLimit = fragArray.length; i < iLimit; i++) {
+                    fragment = fragArray[i];
+                    for (j = 0, jLimit = fragment.attributes.length; j < jLimit; j++) {
+                        clean = fragment.attributes[j];
+                        clean = clean.value.replace(/\s/g, "");
+                        bare = null;
+                        vlParts = clean.match(varParExpr);
+                        if (vlParts) {
+                            if (vlParts.length > 1) {
+                                bare = vlParts[1].trim();
+                            }
+                        }
+                        if (fragmentName == bare && argsCount > 0) {
+                            if (vlParts.length > 2) {
+                                vlArgs = vlParts[2].trim().split(",");
+                                if (vlArgs) {
+                                    if (vlArgs.length == argsCount) {
+                                        argsList = element.thLocalVars["..."];
+                                        if (argsList != null) {
+                                            for (k = 0; k < argsCount; k++) {
+                                                varName = vlArgs[k].trim();
+                                                element.thLocalVars[varName] = argsList[k];
+                                            }
+                                            element.thLocalVars["..."] = null;
+                                        }
+                                        matched = true;
+                                        break;
+                                    } else if (vlArgs.length > argsCount) {
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        if (fragmentName == clean || fragmentPart == clean || fragmentName == bare) {
+                            matched = true;
+                            break;
+                        }
+                    }
+                    if (matched) {
+                        result = fragment;
+                        break;
+                    }
+                }
+            }
+            if (!matched) {
+                fragment = this.getDOMSelection(fragmentName, content);
+                if (fragment) {
+                    matched = true;
+                    result = fragment;
+                } else {
+                    if (!element.isBlockChild) {
+                        throw new thymol.ThError('getImportNode cannot match fragment: "' + fragmentName + '"', element);
+                    }
+                }
+            }
+            thymol.thCache[filePart][fragmentPart] = result;
+            if (matched) {
+                newElement = result.cloneNode(true);
+                if (newElement.nodeType == 1) {
+                    newElement.removeAttribute(thymol.thFragment.name);
+                    newElement.removeAttribute(thymol.thFragment.synonym);
+                }
+                result = newElement;
+                result.thLocalVars = element.thLocalVars;
+            }
+            return result;
+        },
+        getDOMSelection: function(initial, content) {
+            var spec = initial, result = null, scope = "", query = new Array(), parts = "", innr = thymol.ThUtils.unBracket(spec), i, iLimit, j, jLimit, k, kLimit, m, mLimit, token, indx, saved, indxed, start, selection, descend, subQuery, exprFrags, classSpecs, qTerms, subSelect, partial, html, newNode;
+            if (spec != innr && innr.charAt(innr.length - 1) == "]") {
+                spec = innr;
+            }
+            while (spec != "") {
+                parts = spec.match(domSelectExpr);
+                if (parts != null && parts.length > 1) {
+                    for (i = 1, iLimit = parts.length; i < iLimit; i++) {
+                        if (parts[i] != null) {
+                            token = parts[i];
+                            indx = null;
+                            innr = thymol.ThUtils.unBracket(token);
+                            if (token != innr) {
+                                if (innr.match(numericExpr)) {
+                                    indx = innr;
+                                }
+                            }
+                            saved = spec;
+                            spec = spec.replace(token, "");
+                            if (saved == spec) {
+                                spec = "";
+                            }
+                            if (indx) {
+                                token = query[query.length - 1];
+                                indxed = new String(token);
+                                indxed.indx = indx;
+                                query[query.length - 1] = indxed;
+                            } else {
+                                query.push(token.trim());
+                            }
+                            break;
+                        }
+                    }
+                } else {
+                    break;
+                }
+            }
+            start = 0;
+            if (query.length > 0 && query[0] != "" && query[0].charAt(0) == "/") {
+                scope = query[0];
+                start = 1;
+            }
+            selection = [];
+            selection.push(content);
+            descend = false;
+            for (i = start, iLimit = query.length; i < iLimit; i++) {
+                subQuery = query[i];
+                innr = thymol.ThUtils.unBracket(subQuery);
+                if (subQuery != innr) {
+                    innr = innr.replace(/[']/g, '"');
+                    subQuery = "";
+                    exprFrags = innr.split(/\s{1}\s*((?:and)|(?:or))\s{1}\s*/);
+                    for (j = 0, jLimit = exprFrags.length; j < jLimit; j++) {
+                        if (exprFrags[j] != "and" && exprFrags[j] != "or") {
+                            classSpecs = exprFrags[j].match(/[@]?\s*(?:class)\s*(\W?[=])\s*[\"]((?:\w*[\-_]*)*)[\"]/);
+                            if (classSpecs && classSpecs.length > 0) {
+                                if (classSpecs[1] == "=") {
+                                    subQuery = subQuery + "[class~='" + classSpecs[2] + "']";
+                                }
+                                if (classSpecs[1] == "^=") {
+                                    subQuery = subQuery + "[class^='" + classSpecs[2] + "'],[class*=' " + classSpecs[2] + "']";
+                                }
+                            } else {
+                                subQuery = subQuery + "[" + exprFrags[j] + "]";
+                            }
+                        } else if (exprFrags[j] == "or") {
+                            subQuery = subQuery + ",";
+                        }
+                    }
+                }
+                qTerms = subQuery.split("/");
+                for (j = 0, jLimit = qTerms.length; j < jLimit; j++) {
+                    if (qTerms[j] != "") {
+                        qTerms[j] = qTerms[j].replace(/[@]/g, "");
+                        if (subQuery.indx != null) {
+                            qTerms[j] = qTerms[j] + ":eq(" + subQuery.indx + ")";
+                        }
+                        subSelect = [];
+                        for (k = 0, kLimit = selection.length; k < kLimit; k++) {
+                            partial = null;
+                            if (qTerms[j] == textFuncSynonym) {
+                                partial = $(selection[k]).contents().filter(function() {
+                                    return this.nodeType === 3;
+                                });
+                            } else if (descend) {
+                                partial = $(selection[k]).children(qTerms[j]);
+                            } else if (j == 0) {
+                                if (scope == "/") {
+                                    html = $("html", selection[k]);
+                                    if (html.length > 0) {
+                                        selection[k] = html;
+                                    }
+                                    partial = $(selection[k]).children("body").children(qTerms[j]);
+                                    scope = "";
+                                } else {
+                                    if (i == 0 || scope == "//") {
+                                        partial = $(selection[k]).find(qTerms[j]);
+                                        scope = "";
+                                    } else {
+                                        partial = $(selection[k]).filter(qTerms[j]);
+                                    }
+                                }
+                            } else {
+                                partial = $(selection[k]).children(qTerms[j]);
+                            }
+                            if (partial != null) {
+                                for (m = 0, mLimit = partial.length; m < mLimit; m++) {
+                                    subSelect.push(partial[m]);
+                                }
+                            }
+                        }
+                        selection = subSelect;
+                    }
+                }
+                descend = qTerms[qTerms.length - 1] == "";
+            }
+            result = selection;
+            if (result != null && !(result.length === undefined)) {
+                if (result.length > 1) {
+                    newNode = thymol.thDocument.createDocumentFragment();
+                    for (i = 0, iLimit = result.length; i < iLimit; i++) {
+                        var newChild = thymol.thDocument.importNode(result[i], true);
+                        newNode.appendChild(newChild);
+                    }
+                    result = newNode;
+                } else {
+                    result = result[0];
+                }
+            }
+            return result;
+        },
+        getFilePath: function(part, element) {
+            var result = thymol.substitute(part, element), mapped = null, slashpos;
+            if (result) {
+                if (thymol.mappings) {
+                    mapped = thymol.getMapped(result, false);
+                }
+            }
+            if (mapped) {
+                result = mapped;
+            } else {
+                var dotFirst = result.charAt(0) === ".";
+                if (result && (thymol.useAbsolutePath || !dotFirst)) {
+                    slashpos = result.indexOf("/");
+                    if (thymol.useAbsolutePath || slashpos >= 0) {
+                        if (slashpos == 0 && !thymol.useAbsolutePath) {
+                            result = result.substring(1);
+                        }
+                        var proto = "";
+                        if (thymol.useAbsolutePath) {
+                            proto = thymol.protocol;
+                        }
+                        if (thymol.useAbsolutePath && !!thymol.absolutePath) {
+                            result = proto + thymol.absolutePath + result;
+                        } else {
+                            if (dotFirst) {
+                                result = thymol.templatePath + result;
+                            } else {
+                                result = proto + thymol.root + thymol.path + result;
+                            }
+                        }
+                    }
+                }
+            }
+            return result;
+        },
+        doLiteralSubstExpr: function(param, primary) {
+            var result = param.trim(), term, subst, lsp;
+            if (thymol.ThUtils.isLiteralSubst(result)) {
+                result = this.decodeLiteralSubst(result);
+            } else {
+                term = primary;
+                while (term != null) {
+                    if (thymol.ThUtils.isLiteralSubst(term)) {
+                        subst = this.decodeLiteralSubst(term);
+                        result = result.replace(term, subst);
+                        lsp = result.match(litSubstExpr);
+                        if (lsp && lsp.length > 0) {
+                            term = lsp[1];
+                        } else {
+                            break;
+                        }
+                    } else {
+                        break;
+                    }
+                }
+            }
+            return result;
+        },
+        decodeLiteralSubst: function(param) {
+            var result = param, parts, rep, i, iLimit;
+            result = result.trim();
+            result = result.substring(1, result.length - 1);
+            result = result.replace(/[\']/g, "&#39;");
+            parts = result.split(varRefExpr);
+            if (parts && parts.length > 0) {
+                rep = "";
+                for (i = 0, iLimit = parts.length; i < iLimit; i++) {
+                    if (parts[i] != "") {
+                        if (!parts[i].match(varRefExpr)) {
+                            parts[i] = "'" + parts[i] + "'";
+                        }
+                        if (rep == "") {
+                            rep = parts[i];
+                        } else {
+                            rep = rep + "+" + parts[i];
+                        }
+                    }
+                }
+                result = rep;
+            }
+            return result;
+        },
+        doReplace: function(isNode, element, content) {
+            if (isNode) {
+                var parent = element.parentNode;
+                if (content.nodeName.toLowerCase() == "html") {
+                    this.doInsertion(element, content, function(e, n) {
+                        if (n.nodeType == 1) {
+                            n.removeAttribute(thymol.thFragment.name);
+                            n.removeAttribute(thymol.thFragment.synonym);
+                        }
+                        e.parentNode.insertBefore(n, e);
+                    });
+                    parent.removeChild(element);
+                } else {
+                    var node = this.doClone(content, parent.ownerDocument);
+                    if (node.nodeType == 1) {
+                        node.removeAttribute(thymol.thFragment.name);
+                        node.removeAttribute(thymol.thFragment.synonym);
+                    }
+                    parent.replaceChild(node, element);
+                    node.parentNode = parent;
+                }
+            } else {
+                try {
+                    while (element.firstChild != null) {
+                        element.removeChild(element.firstChild);
+                        if (element.firstChild == null) {
+                            break;
+                        }
+                    }
+                    this.doInsertion(element, content, function(e, n) {
+                        if (n.nodeType == 1) {
+                            n.removeAttribute(thymol.thFragment.name);
+                            n.removeAttribute(thymol.thFragment.synonym);
+                        }
+                        e.appendChild(n);
+                    });
+                } catch (err) {
+                    element.innerHTML = content.innerHTML;
+                }
+            }
+        },
+        doClone: function(old, targetDoc) {
+            var node, cNodes, i, iNode, aNode;
+            if (!!old.parentNode && old.parentNode.ownerDocument === targetDoc) {
+                node = old.cloneNode(false);
+            } else {
+                node = targetDoc.importNode(old, false);
+            }
+            if (node !== null) {
+                if (node.nodeType == 1) {
+                    if (old.thLocalVars !== null) {
+                        node.thLocalVars = old.thLocalVars;
+                    }
+                }
+                if (old.childNodes !== null) {
+                    cNodes = old.childNodes.length;
+                    if (cNodes > 0) {
+                        for (i = 0; i < cNodes; i++) {
+                            iNode = old.childNodes[i];
+                            if (iNode !== null) {
+                                aNode = this.doClone(iNode, targetDoc);
+                                if (aNode !== null) {
+                                    node.appendChild(aNode);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            return node;
+        },
+        doInsertion: function(element, content, func) {
+            var topLevel = true, parent = element.parentElement, i, iLimit, iNode, elementName, j, jLimit, jNode, cJNode, cINode;
+            if (parent != null) {
+                topLevel = element.parentElement.nodeName.toLowerCase() == "html";
+            }
+            for (i = 0, iLimit = content.childNodes.length; i < iLimit; i++) {
+                iNode = content.childNodes[i];
+                if (iNode) {
+                    if (!topLevel) {
+                        elementName = iNode.nodeName.toLowerCase();
+                        if (elementName != "head") {
+                            if (elementName == "body") {
+                                for (j = 0, jLimit = iNode.childNodes.length; j < jLimit; j++) {
+                                    jNode = iNode.childNodes[j];
+                                    if (jNode) {
+                                        cJNode = this.doClone(jNode, parent.ownerDocument);
+                                        func(element, cJNode);
+                                    }
+                                }
+                            } else {
+                                cINode = this.doClone(iNode, parent.ownerDocument);
+                                func(element, cINode);
+                            }
+                        }
+                    } else {
+                        cINode = this.doClone(iNode, parent.ownerDocument);
+                        func(element, cINode);
+                    }
+                }
+            }
+        },
+        getThParam: function(paramName, isBoolean, isPath, defaultValue) {
+            var localValue = defaultValue, globalValue = thymol.thWindow[paramName], theParam = thymol.ThUtils.getParameter(paramName);
+            if (typeof globalValue === "undefined") {
+                globalValue = thymol.applicationContext.javascriptify(paramName);
+            }
+            if (!!theParam) {
+                if (theParam instanceof ThParam) {
+                    if (theParam.globalValue !== globalValue) {
+                        theParam.globalValue = globalValue;
+                        theParam.value = globalValue;
+                        localValue = globalValue;
+                    }
+                }
+                if (isBoolean) {
+                    localValue = theParam.getBooleanValue();
+                }
+            } else {
+                if (!(typeof globalValue === "undefined")) {
+                    if (globalValue != null) {
+                        if (isBoolean) {
+                            localValue = globalValue == true;
+                        } else {
+                            localValue = globalValue;
+                        }
+                    }
+                }
+            }
+            if (!isBoolean && isPath && localValue.length > 0 && localValue.charAt(localValue.length - 1) != "/") {
+                localValue = localValue + "/";
+            }
+            thymol.applicationContext.createVariable(paramName, localValue);
+            return localValue;
+        }
+    };
+    function addDialect(spec) {
+        var i, iLimit, prec = thymol.thDefaultPrecedence;
+        if (spec !== null && typeof spec !== "undefined") {
+            if (spec.attributeProcessors !== null && typeof spec.attributeProcessors !== "undefined") {
+                for (i = 0, iLimit = spec.attributeProcessors.length; i < iLimit; i++) {
+                    if (spec.attributeProcessors[i].precedence !== null && typeof spec.attributeProcessors[i].precedence !== "undefined") {
+                        prec = spec.attributeProcessors[i].precedence;
+                    } else {
+                        prec = thymol.thDefaultPrecedence;
+                    }
+                    configureAttributeProcessor(spec.prefix, spec.attributeProcessors[i].name, spec.attributeProcessors[i].processor, prec, null);
+                }
+            }
+            if (spec.elementProcessors !== null && typeof spec.elementProcessors !== "undefined") {
+                for (i = 0, iLimit = spec.elementProcessors.length; i < iLimit; i++) {
+                    configureElementProcessor(spec.prefix, spec.elementProcessors[i].name, spec.elementProcessors[i].processor);
+                }
+            }
+            if (spec.objects !== null && typeof spec.objects !== "undefined") {
+                for (i = 0, iLimit = spec.objects.length; i < iLimit; i++) {
+                    if (spec.objects[i].name !== null && typeof spec.objects[i].name !== "undefined") {
+                        spec.objects[i].object.thExpressionObjectName = spec.objects[i].name;
+                        configureModule(spec.objects[i].object);
+                    } else {
+                        configureModule(spec.objects[i]);
+                    }
+                }
+            }
+        }
+    }
+    function ThNode(thDocParam, visitedParam, parentDocParam, firstChildParam, nextSiblingParam, fileNameParam, fragNameParam, isNodeParam, elementParam) {
+        this.thDoc = thDocParam;
+        this.visited = visitedParam;
+        this.parentDoc = parentDocParam;
+        this.firstChild = firstChildParam;
+        this.nextSibling = nextSiblingParam;
+        this.fileName = fileNameParam;
+        this.fragName = fragNameParam;
+        this.isNode = isNodeParam;
+        this.element = elementParam;
+    }
+    function ThError(message, element, source) {
+        this.name = "ThError";
+        this.message = message || "Default Message";
+        if (element !== null && typeof element !== "undefined" && element.isBlockChild) {
+            this.suppress = true;
+        } else {
+            this.element = element || {};
+            this.suppress = false;
+        }
+        if (!!source) {
+            if (!!source.stack) {
+                this.stack = source.stack;
+            }
+        }
+    }
+    ThError.prototype = new Error();
+    ThError.prototype.constructor = ThError;
+    function ThParam(valueArg) {
+        this.value = valueArg;
+        this.globalValue;
+        this["class"] = new thymol.ThClass("Thymol.ThParam");
+        this.getBooleanValue = function() {
+            return !thymol.ThUtils.testLiteralFalse(this.value);
+        };
+        this.toString = function() {
+            return this.value;
+        };
+        this.getNumericValue = function() {
+            return Number(this.value);
+        };
+    }
+    function ThAttr(suffix, func, prec, list, pref, dataAttr) {
+        var prefix = "", dataPrefix = null, escpPrefix = "";
+        if (typeof pref !== "undefined" && pref !== null) {
+            prefix = pref + ":";
+            if (thymol.thThymeleafPrefixList.indexOf(prefix) < 0) {
+                thymol.thThymeleafPrefixList.push(prefix);
+            }
+            escpPrefix = pref + "\\:";
+            if (typeof dataAttr === "undefined" || dataAttr === null) {
+                dataPrefix = thymol.dataPrefix + "-" + pref + "-";
+                if (thymol.thThymeleafPrefixList.indexOf(dataPrefix) < 0) {
+                    thymol.thThymeleafPrefixList.push(dataPrefix);
+                }
+            } else {
+                dataPrefix = dataAttr;
+            }
+        }
+        this.suffix = suffix;
+        this.name = prefix + suffix;
+        this.regex = null;
+        if (suffix.indexOf("*") >= 0 || suffix.indexOf("?") >= 0 || suffix.indexOf("+") >= 0 || suffix.indexOf("\\") >= 0 || suffix.indexOf("|") >= 0 || suffix.indexOf("[") >= 0 || suffix.indexOf("]") >= 0 || suffix.indexOf("{") >= 0 || suffix.indexOf("}") >= 0) {
+            if ("*" === suffix) {
+                suffix = ".*";
+            }
+            suffix = prefix + suffix;
+            this.regex = new RegExp(suffix);
+        }
+        this.escpName = "[" + escpPrefix + suffix + "]";
+        if (dataPrefix !== null) {
+            this.synonym = dataPrefix + suffix;
+            this.escpSynonym = "[" + this.synonym + "]";
+        } else {
+            this.synonym = null;
+            this.escpSynonym = null;
+        }
+        if (typeof prec !== "undefined" && prec !== null) {
+            this.precedence = prec;
+        } else {
+            this.precedence = thymol.thDefaultPrecedence;
+        }
+        if (!!list) {
+            var attrList = list[pref];
+            if (!attrList) {
+                attrList = [];
+                list[pref] = attrList;
+                if (dataPrefix !== null) {
+                    list[dataPrefix] = attrList;
+                }
+            }
+            attrList.push(this);
+        }
+        this.process = function() {
+            thymol.thWindow.alert('unsupported processing function for attribute "' + this.name + '"');
+        };
+        if (!(typeof func === "undefined")) {
+            this.process = func;
+        }
+        this.disable = function() {
+            this.name = null;
+            this.escpName = null;
+            this.escpSynonym = null;
+            this.process = function() {};
+        };
+    }
+    function ThElement(suffix, func, pref) {
+        var tha = new thymol.ThAttr(suffix, null, 0, null, pref);
+        this.name = tha.name;
+        this.synonym = tha.synonym;
+        this.endName = "/" + tha.name;
+        this.endSynonym = "/" + tha.synonym;
+        this.process = function() {
+            thymol.thWindow.alert('unsupported processing function for element "' + this.name + '"');
+        };
+        if (!(typeof func === "undefined")) {
+            this.process = func;
+        }
+        this.disable = function() {
+            this.name = null;
+            this.synonym = null;
+            this.endName = null;
+            this.endSynonym = null;
+            this.process = null;
+        };
+        thymol.thThymeleafElementsList.push(this);
+    }
+    function ThSet() {
+        this.that = this;
+        this.setSize = 0;
+        this.isContent = function(k) {
+            return this.hasOwnProperty(k) && typeof this[k] !== "function" && k !== "that" && k !== "setSize";
+        };
+        this.add = function(k) {
+            var contained = typeof this[k] !== "undefined";
+            this[k] = k;
+            if (contained !== (typeof this[k] !== "undefined")) {
+                this.setSize++;
+            }
+        };
+        this.addAll = function(other) {
+            var k = null, value;
+            for (k in other) {
+                if (other.hasOwnProperty(k)) {
+                    value = other[k];
+                    if (typeof value !== "function") {
+                        add(value);
+                    }
+                }
+            }
+        };
+        this.clear = function() {
+            for (var k in this) {
+                if (this.hasOwnProperty(k)) {
+                    delete this[k];
+                }
+            }
+            setSize = 0;
+        };
+        this.contains = function(k) {
+            return typeof this[k] !== "undefined";
+        };
+        this.containsAll = function(keys) {
+            var keySet = keys, k = null;
+            if (typeof keys === "Array" || Object.prototype.toString.call(keys) === "[object Array]") {
+                keySet = ThSet.prototype.fromArray(keys);
+            }
+            for (k in keySet) {
+                if (keySet.hasOwnProperty(k)) {
+                    if (typeof this[k] === "undefined") {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        };
+        this.isEmpty = function() {
+            return this.setSize === 0;
+        };
+        this.size = function() {
+            return this.setSize;
+        };
+        this.remove = function(k) {
+            var contained = typeof this[k] !== "undefined";
+            delete this[k];
+            if (contained !== (typeof this[k] !== "undefined")) {
+                this.setSize--;
+            }
+        };
+        this.toArray = function() {
+            return getArray(this);
+        };
+        this.toString = function() {
+            var array = getArray();
+            return array.toString();
+        };
+        function getArray(obj) {
+            var array = [], k = null, value;
+            for (k in obj) {
+                if (obj.hasOwnProperty(k) && k !== "that" && k !== "setSize") {
+                    value = obj[k];
+                    if (typeof value !== "function") {
+                        array.push(value);
+                    }
+                }
+            }
+            return array;
+        }
+    }
+    ThSet.prototype.fromArray = function(array) {
+        var set = new thymol.ThSet(), i, iLimit;
+        for (i = 0, iLimit = array.length; i < iLimit; i++) {
+            set.add(array[i]);
+        }
+        return set;
+    };
+    function ThMap() {
+        ThSet.apply(this);
+        this.containsKey = function(k) {
+            return this.contains(k);
+        };
+        this.containsValue = function(target) {
+            var k = null, value;
+            for (k in this.that) {
+                if (this.that.hasOwnProperty(k) && k !== "that") {
+                    value = this.that[k];
+                    if (value === target) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        };
+        this.entrySet = function() {
+            return this.that;
+        };
+        this.get = function(k) {
+            return this.that[k];
+        };
+        this.keySet = function() {
+            return this.that;
+        };
+        this.put = function(k, v) {
+            var contained = typeof this[k] !== "undefined";
+            this.that[k] = v;
+            if (contained !== (typeof this[k] !== "undefined")) {
+                this.setSize++;
+            }
+        };
+        this.putAll = function(t) {
+            for (var k in t) {
+                put(k, t[k]);
+            }
+        };
+        this.values = function() {
+            return this.that;
+        };
+    }
+    ThMap.prototype = new ThSet();
+    ThMap.prototype.constructor = ThMap;
+    function ThObject(dolly) {
+        for (prop in dolly) {
+            if (dolly.hasOwnProperty(prop)) {
+                if (prop) {
+                    if (!this[prop]) {
+                        this[prop] = dolly[prop];
+                    }
+                }
+            }
+        }
+        this["class"] = new thymol.ThClass("Thymol.ThObject");
+        this.toNonThObject = function() {
+            var plain = {};
+            for (prop in this) {
+                if (this.hasOwnProperty(prop)) {
+                    if (prop) {
+                        if (!plain[prop]) {
+                            if (prop !== "toNonThObject") {
+                                if (prop !== "class" || prop === "class" && this[prop] !== null && this[prop].name !== "Thymol.ThObject") {
+                                    plain[prop] = this[prop];
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            return plain;
+        };
+    }
+    function ThVarsAccessor(storeArg, storeNameArg) {
+        this.store = storeArg;
+        this.arrayName = storeNameArg;
+        this.length = function() {
+            return this.store.length;
+        };
+        this.get = function(name) {
+            return this.store[name];
+        };
+        this.set = function(name, value) {
+            this.store[name] = value;
+        };
+    }
+    function ThClass(nValue) {
+        this.name = nValue;
+    }
+    return {
+        Thymol: Thymol,
+        ThError: ThError,
+        ThParam: ThParam,
+        ThAttr: ThAttr,
+        ThElement: ThElement,
+        ThSet: ThSet,
+        ThMap: ThMap,
+        ThObject: ThObject,
+        ThVarsAccessor: ThVarsAccessor,
+        ThClass: ThClass,
+        thDomParser: thymol.thDomParser,
+        thDocument: thymol.thDocument,
+        thWindow: thymol.thWindow,
+        thTop: thymol.thTop,
+        thRequest: thymol.thRequest,
+        thVersion: thymol.thVersion,
+        thReleaseDate: thymol.thReleaseDate,
+        thURL: thymol.thURL,
+        thAltURL: thymol.thAltURL,
+        thInclude: thymol.thInclude,
+        thReplace: thymol.thReplace,
+        thSubstituteby: thymol.thSubstituteby,
+        thFragment: thymol.thFragment,
+        thRemove: thymol.thRemove,
+        thBlock: thymol.thBlock,
+        thScriptName: thymol.thScriptName,
+        thDefaultPrefix: thymol.thDefaultPrefix,
+        thDefaultDataPrefix: thymol.thDefaultDataPrefix,
+        thDefaultPrecision: thymol.thDefaultPrecision,
+        thDefaultProtocol: thymol.thDefaultProtocol,
+        thDefaultLocale: thymol.thDefaultLocale,
+        thDefaultPrecedence: thymol.thDefaultPrecedence,
+        thDefaultMessagePath: thymol.thDefaultMessagePath,
+        thDefaultResourcePath: thymol.thDefaultResourcePath,
+        thDefaultMessagesBaseName: thymol.thDefaultMessagesBaseName,
+        thDefaultRelativeRootPath: thymol.thDefaultRelativeRootPath,
+        thDefaultExtendedMapping: thymol.thDefaultExtendedMapping,
+        thDefaultLocalMessages: thymol.thDefaultLocalMessages,
+        thDefaultDisableMessages: thymol.thDefaultDisableMessages,
+        thDefaultTemplateSuffix: thymol.thDefaultTemplateSuffix,
+        thThymeleafPrefixList: thymol.thThymeleafPrefixList,
+        thThymeleafElementsList: thymol.thThymeleafElementsList,
+        thLocation: thymol.thLocation,
+        messagePath: thymol.messagePath,
+        resourcePath: thymol.resourcePath,
+        relativeRootPath: thymol.relativeRootPath,
+        messagesBaseName: thymol.messagesBaseName,
+        extendedMapping: thymol.extendedMapping,
+        scriptPath: thymol.scriptPath,
+        absolutePath: thymol.absolutePath,
+        useAbsolutePath: thymol.useAbsolutePath,
+        useFullURLPath: thymol.useFullURLPath,
+        localMessages: thymol.localMessages,
+        indexFile: thymol.indexFile,
+        disableMessages: thymol.disableMessages,
+        templateSuffix: thymol.templateSuffix,
+        prefix: thymol.prefix,
+        dataPrefix: thymol.dataPrefix,
+        templateName: thymol.templateName,
+        templatePath: thymol.templatePath,
+        objects: thymol.objects,
+        jqSetup: jqSetup,
+        isClientSide: isClientSide,
+        execute: execute,
+        updatePrefix: updatePrefix,
+        init: init,
+        ready: ready,
+        addDialect: addDialect,
+        isFragmentChild: isFragmentChild,
+        preProcess: preProcess,
+        substitute: substitute,
+        substituteParam: substituteParam,
+        configureModule: configureModule,
+        configureAttributeProcessor: configureAttributeProcessor,
+        configureElementProcessor: configureElementProcessor,
+        configurePreExecution: configurePreExecution,
+        configurePostExecution: configurePostExecution,
+        getStandardURL: getStandardURL,
+        getMessage: getMessage,
+        getExpression: getExpression,
+        getWith: getWith,
+        getParsedExpr: getParsedExpr,
+        getLocale: getLocale,
+        getMapped: getMapped,
+        getBooleanValue: getBooleanValue,
+        setLocale: setLocale
+    };
+}();
+
+thymol.makeContext = function(contextNameParam, varAccessorParam) {
+    var jsonDeclSpec = "(?:\\W*([\\'][A-Za-z]+(?:\\w|[$])*[\\'])\\s*[:])?\\s*([#][A-Za-z]+(?:\\w|[$])*)(?:\\W|[^$])*", jsonDeclExpr = new RegExp(jsonDeclSpec), context = new Array();
+    context.contextName = contextNameParam;
+    context.varAccessor = varAccessorParam;
+    context.varStore = [];
+    context.varNamePrefix = "";
+    if (typeof varAccessorParam === "undefined") {
+        context.varAccessor = new thymol.ThVarsAccessor(context.varStore, "varStore");
+    }
+    context.varNamePrefix = context.varAccessor.arrayName + "[";
+    context.getJSONView = function(param, rootVal) {
+        var pType = typeof param, view = "", objType;
+        if (pType === "string") {
+            view = view + "'" + param + "'";
+        } else if (pType === "number" || pType === "boolean") {
+            view = view + param;
+        } else if (pType === "object") {
+            if (param instanceof Object) {
+                objType = Object.prototype.toString.call(param);
+                if ("[object Array]" === objType) {
+                    view = this.getJSONViewArray(param, false);
+                } else if ("[object Object]" === objType) {
+                    view = this.getJSONViewObject(param, false);
+                }
+                view = "#" + view;
+            }
+        }
+        return view;
+    };
+    context.init = function() {
+        var persisted = thymol.thTop.name, paramRow, paramName, params, i, iLimit, paramValue;
+        if (persisted && persisted !== "") {
+            params = this.javascriptify(persisted);
+            if (params && params.length > 0) {
+                for (i = 0, iLimit = params.length; i < iLimit; i++) {
+                    paramRow = params[i];
+                    if (paramRow) {
+                        paramName = paramRow[0];
+                        if (paramName) {
+                            paramValue = paramRow[1];
+                            this.createVariable(paramName, paramValue);
+                        }
+                    }
+                }
+            }
+        }
+    };
+    context.getJSONViewObject = function(param, rootVal) {
+        var isRoot = true, key = null, view = "{", value, identifier, definition, suffix, instanceNamePrefix, isTaken, i, iLimit, instanceValue;
+        if (typeof rootVal === "boolean") {
+            isRoot = rootVal;
+        }
+        for (key in param) {
+            if (key) {
+                value = param[key];
+                if (typeof value !== "function") {
+                    if (view != "{") {
+                        view = view + ",";
+                    }
+                    identifier = this.getJSONView(key, false);
+                    definition = this.getJSONView(value, false);
+                    view = view + identifier + ":";
+                    if (!isRoot && typeof value === "object") {
+                        suffix = 1;
+                        instanceNamePrefix = key + "$";
+                        instanceName = null;
+                        isTaken = false;
+                        do {
+                            instanceName = instanceNamePrefix + suffix++;
+                            instanceValue = context[instanceName];
+                            if (instanceValue === null || typeof instanceValue === "undefined") {
+                                isTaken = false;
+                                for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
+                                    if (instanceName === varStore[i][0]) {
+                                        isTaken = true;
+                                        break;
+                                    }
+                                }
+                                if (!isTaken) {
+                                    this.addAttribute(instanceName, definition);
+                                }
+                            }
+                        } while (isTaken);
+                        if (instanceName !== null) {
+                            view = view + "#" + instanceName;
+                        }
+                    } else {
+                        view = view + definition;
+                    }
+                }
+            }
+        }
+        view = view + "}";
+        return view;
+    };
+    context.getJSONViewArray = function(param, rootVal) {
+        var view = "[", i;
+        for (i = 0; i < param.length; i++) {
+            view = view + this.getJSONView(param[i], false);
+            if (i < param.length - 1) {
+                view = view + ",";
+            }
+        }
+        view = view + "]";
+        return view;
+    };
+    context.getAttribute = function(name) {
+        return context[name];
+    };
+    context.addAttribute = function(name, value) {
+        var entry = [];
+        entry[0] = name;
+        entry[1] = value;
+        varStore.push(entry);
+    };
+    context.serialise = function() {
+        varStore = [];
+        var serialised = "[", key = null, value, cn, view, name, i, iLimit;
+        for (key in context) {
+            if (key) {
+                value = context[key];
+                if (value != null && typeof value === "object") {
+                    cn = Object.prototype.toString.call(value);
+                    if ("[object Array]" !== cn && !(value instanceof thymol.ThClass) && !(value instanceof thymol.ThVarsAccessor)) {
+                        if (serialised !== "[") {
+                            serialised = serialised + ",";
+                        }
+                        view = this.getJSONView(value, true);
+                        serialised = serialised + "[";
+                        serialised = serialised + '"' + key + '"';
+                        serialised = serialised + ",";
+                        serialised = serialised + '"' + view + '"';
+                        serialised = serialised + "]";
+                    }
+                }
+            }
+        }
+        for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
+            name = varStore[i][0];
+            view = varStore[i][1];
+            serialised = serialised + ",[";
+            serialised = serialised + '"' + name + '"';
+            serialised = serialised + ",";
+            serialised = serialised + '"' + view + '"';
+            serialised = serialised + "]";
+        }
+        serialised = serialised + "]";
+        return serialised;
+    };
+    context.javascriptify = function(fn) {
+        try {
+            return new Function("return " + fn)();
+        } catch (err) {
+            return undefined;
+        }
+    };
+    context.createVariable = function(name, valParam, isReq) {
+        var value = valParam, param, tt, literalBoolean, strValue, initial, existing, newArray;
+        param = value;
+        if (!(value instanceof thymol.ThParam)) {
+            tt = typeof valParam;
+            if (tt !== "function" && tt !== "object") {
+                if (tt === "string") {
+                    try {
+                        value = isReq ? decodeURIComponent(value) : decodeURI(value);
+                    } catch (err) {}
+                }
+                if (tt === "boolean" || tt === "number") {
+                    param = new thymol.ThParam(value);
+                } else if (value || value === "") {
+                    literalBoolean = thymol.ThUtils.testLiteralFalse(value);
+                    if (literalBoolean) {
+                        param = false;
+                    } else {
+                        strValue = new String(value);
+                        initial = strValue.trim();
+                        if (initial.charAt(0) === "#") {
+                            initial = initial.substring(1);
+                            try {
+                                param = this.createJSONVariable(initial);
+                            } catch (err) {
+                                if (err instanceof ReferenceError) {}
+                                if (err instanceof EvalError) {}
+                                if (param == null || isReq) {
+                                    param = new thymol.ThParam(value);
+                                }
+                            }
+                        } else {
+                            param = new thymol.ThParam(strValue.toString());
+                        }
+                    }
+                }
+            }
+        }
+        if (isReq) {
+            existing = context[name];
+            if (typeof existing !== "undefined" && existing !== null) {
+                if (Object.prototype.toString.call(existing) === "[object Array]") {
+                    existing.push(param);
+                } else {
+                    if (thymol.debug) {
+                        thymol.thWindow.alert('request parameters should be of type string array "' + name + '"');
+                    }
+                }
+            } else {
+                newArray = new Array();
+                newArray["class"] = {};
+                newArray["class"]["name"] = "[Thymol.ThParam]";
+                newArray.push(param);
+                context[name] = newArray;
+            }
+        } else {
+            context[name] = param;
+        }
+        return param;
+    };
+    context.createJSONVariable = function(initial) {
+        var current = initial.trim(), parts = " ", substIndex, token, re, vName, obj, result;
+        substIndex = this.varAccessor.length() + 1;
+        while (parts) {
+            parts = current.match(jsonDeclExpr);
+            if (parts && parts.length > 2) {
+                token = parts[2];
+                token = token.replace(/[\']/g, "[']").replace(/[$]/g, "[$]");
+                re = new RegExp(token);
+                vName = this.varNamePrefix + substIndex + "]";
+                obj = new Object();
+                obj.name = parts[2].substring(1);
+                this.varAccessor.set(substIndex, obj);
+                substIndex = substIndex + 1;
+                current = current.replace(re, "'" + vName + "'", "g");
+            }
+        }
+        current = current.replace(/[\']/g, '"');
+        result = $.parseJSON(current);
+        if ("[object Array]" !== Object.prototype.toString.call(result)) {
+            result = new thymol.ThObject(result);
+        }
+        return result;
+    };
+    context.resolveJSONReferences = function() {
+        var key = null, param, prop = null, val, ref, subst, isReq = "request" === this.contextName;
+        for (key in context) {
+            if (key) {
+                param = context[key];
+                if (param != null && typeof param === "object") {
+                    if (!(param instanceof thymol.ThVarsAccessor) && !(param instanceof thymol.ThClass)) {
+                        if (!(param instanceof thymol.ThParam)) {
+                            if (isReq && Object.prototype.toString.call(param) === "[object Array]") {
+                                for (var i = 0, iLimit = param.length; i < iLimit; i++) {
+                                    var pi = param[i];
+                                    if (!!pi && typeof pi.value === "string" && pi.value.charAt(0) == "#") {
+                                        var pv = thymol.ThUtils.getParameter(pi.value.substring(1));
+                                        param[i] = pv;
+                                    }
+                                }
+                            } else {
+                                for (prop in param) {
+                                    if (prop) {
+                                        val = param[prop];
+                                        if (typeof val === "string") {
+                                            if (val.indexOf(this.varNamePrefix) == 0) {
+                                                subst = null;
+                                                if (prop.match(/\d*/)) {
+                                                    ref = val.substring(this.varNamePrefix.length, val.length - 1);
+                                                    ref = this.varAccessor.get(ref);
+                                                    subst = context[ref.name];
+                                                } else {
+                                                    subst = context[prop];
+                                                }
+                                                param[prop] = subst;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        } else if (typeof param.value === "string" && param.value.charAt(0) == "#") {
+                            subst = context[param.value.substring(1)];
+                            context[key] = subst;
+                        }
+                    }
+                }
+            }
+        }
+    };
+    return context;
+};
+
+thymol.ThUtils = function() {
+    function mergeVars(thiz, other) {
+        var current = thiz, prop = null;
+        if (!current) {
+            current = {};
+        }
+        for (prop in other) {
+            if (other.hasOwnProperty(prop)) {
+                if (prop) {
+                    if (!current[prop]) {
+                        current[prop] = other[prop];
+                    }
+                }
+            }
+        }
+        return current;
+    }
+    function processElement(func, element, arg, obj) {
+        var result = null, parent = element.parentElement;
+        if (!thymol.isFragmentChild(element)) {
+            if (!element.thObjectVar) {
+                parent = element.parentElement;
+                while (parent) {
+                    if (parent.thObjectVar) {
+                        element.thObjectVar = parent.thObjectVar;
+                        break;
+                    }
+                    parent = parent.parentElement;
+                }
+            }
+            parent = element.parentElement;
+            while (parent) {
+                if (parent.thLocalVars) {
+                    element.thLocalVars = mergeVars(element.thLocalVars, parent.thLocalVars);
+                    break;
+                }
+                parent = parent.parentElement;
+            }
+            result = func(element, arg, obj);
+        }
+        return result;
+    }
+    function unQuote(param) {
+        var par = param, pared;
+        if (par) {
+            if (typeof par === "string") {
+                par = par.trim();
+                if (par.charAt(0) == '"') {
+                    if (par.charAt(par.length - 1) == '"') {
+                        pared = par.substring(1, par.length - 1);
+                        if (pairParity(pared, '"', '"') == 0) {
+                            par = pared;
+                        }
+                    }
+                } else if (par.charAt(0) == "'") {
+                    if (par.charAt(par.length - 1) == "'") {
+                        pared = par.substring(1, par.length - 1);
+                        if (pairParity(pared, "'", "'") == 0) {
+                            par = pared;
+                        }
+                    }
+                }
+            }
+        }
+        return par;
+    }
+    function unParenthesise(param) {
+        var par = param, pared;
+        if (par) {
+            if (typeof par === "string") {
+                par = par.trim();
+                if (par.charAt(0) == "(") {
+                    if (par.charAt(par.length - 1) == ")") {
+                        pared = par.substring(1, par.length - 1).trim();
+                        if (pairParity(pared, "(", ")") == 0) {
+                            par = pared;
+                        }
+                    }
+                }
+            }
+        }
+        return par;
+    }
+    function pairParity(str, left, right) {
+        var i, ch, strLength = str.length, parity = 0;
+        for (i = 0; i < strLength; i++) {
+            ch = str.charAt(i);
+            if (ch == left) {
+                parity++;
+            } else if (ch == right) {
+                parity--;
+                if (parity < 0) {
+                    break;
+                }
+            }
+        }
+        return parity;
+    }
+    function unBracket(param) {
+        var par = param, pared;
+        if (typeof par === "string") {
+            par = par.trim();
+        }
+        if (par) {
+            if (par.charAt(0) == "[") {
+                if (par.charAt(par.length - 1) == "]") {
+                    pared = par.substring(1, par.length - 1);
+                    if (pairParity(pared, "[", "]") == 0) {
+                        par = pared;
+                    }
+                }
+            }
+        }
+        return par;
+    }
+    function getToPrecision(n, p) {
+        if (typeof p === "undefined") {
+            return n;
+        }
+        var up = thymol.thDefaultPrecision, ndp = 0, s, sl, dp, v;
+        if (p > up) {
+            up = p;
+        } else {
+            s = n.toString();
+            sl = s.length;
+            dp = s.indexOf(".");
+            if (dp >= 0) {
+                ndp = sl - 1 - dp;
+            }
+            if (ndp > up) {
+                v = n.toPrecision(ndp + 1);
+                v = truncateDecimals(v);
+                s = v.toString();
+                sl = s.length;
+                if (dp >= 0) {
+                    ndp = sl - 1 - dp;
+                }
+            }
+            if (p > ndp) {
+                up = p;
+            } else if (ndp < up) {
+                up = ndp;
+            }
+        }
+        v = parseFloat(n);
+        v = v.toFixed(up);
+        if (p === 0) {
+            v = Number(v);
+        }
+        return v;
+    }
+    function truncateDecimals(valp) {
+        var val = valp, iLimit = valp.length - 1, i;
+        for (i = iLimit; i >= 0; i--) {
+            if (val.charAt(i) === "0") {
+                val = val.substr(0, i);
+            } else {
+                break;
+            }
+        }
+        return val;
+    }
+    function getDecimalDigits(val) {
+        var digits = 0, s, dp;
+        s = val.toString();
+        dp = s.indexOf(".") + 1;
+        if (dp > 0) {
+            digits = s.length - dp;
+        }
+        return digits;
+    }
+    function testLiteralFalse(initial) {
+        var result = false, val;
+        if (typeof initial === "string") {
+            val = initial.toLowerCase();
+            result = val == "false" || val == "off" || val == "no";
+        } else if (typeof initial === "boolean") {
+            result = !initial;
+        }
+        return result;
+    }
+    function renderMessage(msg, values) {
+        var result = msg, i, iLimit;
+        if (Object.prototype.toString.call(values) == "[object Array]") {
+            for (i = 0, iLimit = values.length; i < iLimit; i++) {
+                result = renderMessageArg(result, i, values[i]);
+            }
+        } else {
+            result = renderMessageArg(msg, 0, values);
+        }
+        return result;
+    }
+    function renderMessageArg(msg, index, value) {
+        var result = msg, splits, i, iLimit, iUpper;
+        splits = msg.split("{" + index + "}");
+        if (splits.length > 0) {
+            result = "";
+            for (i = 0, iLimit = splits.length, iUpper = iLimit - 1; i < iLimit; i++) {
+                result += splits[i];
+                if (i < iUpper) {
+                    result += value;
+                }
+            }
+        }
+        return result;
+    }
+    function getParameter(name) {
+        var result, tor;
+        result = thymol.requestContext[name];
+        tor = typeof result;
+        if (tor === "undefined") {
+            result = thymol.sessionContext[name];
+            if (typeof result === "undefined") {
+                result = thymol.applicationContext[name];
+            }
+        } else if (tor === "object") {
+            if (Object.prototype.toString.call(result) === "[object Array]") {
+                if (result.length === 1) {
+                    result = result[0];
+                }
+            }
+        }
+        return result;
+    }
+    function charOcurrences(str, chr) {
+        var count = 0, i = 0, iLimit = str.length;
+        for (;i < iLimit; i++) {
+            if (str.charAt(i) === chr) {
+                count++;
+            }
+        }
+        return count;
+    }
+    function isLiteral(val) {
+        var first, last;
+        if (typeof val === "string") {
+            first = val.charAt(0);
+            last = val.charAt(val.length - 1);
+            if (first == "'" && last == "'") {
+                return true;
+            }
+            if (first == '"' && last == '"') {
+                return true;
+            }
+        }
+        return false;
+    }
+    function isLiteralSubst(param) {
+        var result = false, par = param;
+        if (typeof par === "string") {
+            par = par.trim();
+        }
+        if (par) {
+            if (par.charAt(0) == "|") {
+                if (par.charAt(par.length - 1) == "|") {
+                    result = true;
+                }
+            }
+        }
+        return result;
+    }
+    function loadScript(file) {
+        var script = thymol.Thymol.prototype.getFilePath(file);
+        var status = "";
+        var jqxhr = $.ajax({
+            type: "GET",
+            url: script,
+            dataType: "script",
+            cache: true,
+            async: false
+        }).done(function() {
+            status = "success";
+        }).fail(function() {
+            status = "error";
+        });
+    }
+    function unescape(text) {
+        var result = text, i, iLimit, iUpper, c, cc;
+        if (text !== null && typeof text !== "undefined") {
+            result = "";
+            iLimit = text.length;
+            iUpper = iLimit - 3;
+            for (i = 0; i < iLimit; i++) {
+                c = text.charAt(i);
+                if (i < iUpper) {
+                    if (c === "&") {
+                        cc = text.charAt(i + 1).toLowerCase();
+                        if ((cc === "g" || cc === "l") && text.charAt(i + 2).toLowerCase() === "t" && text.charAt(i + 3) === ";") {
+                            i += 3;
+                            if (cc === "g") {
+                                c = ">";
+                            } else {
+                                c = "<";
+                            }
+                        } else if (i < iUpper - 1 && cc === "a" && text.charAt(i + 2).toLowerCase() === "m" && text.charAt(i + 3).toLowerCase() === "p" && text.charAt(i + 4) === ";") {
+                            i += 4;
+                        } else if (i < iUpper - 2) {
+                            if (cc === "q" && text.charAt(i + 2).toLowerCase() === "u" && text.charAt(i + 3).toLowerCase() === "o" && text.charAt(i + 4).toLowerCase() === "t" && text.charAt(i + 5) === ";") {
+                                i += 5;
+                                c = '"';
+                            } else if (cc === "a" && text.charAt(i + 2).toLowerCase() === "p" && text.charAt(i + 3).toLowerCase() === "o" && text.charAt(i + 4).toLowerCase() === "s" && text.charAt(i + 5) === ";") {
+                                i += 5;
+                                c = "'";
+                            }
+                        }
+                    }
+                }
+                result += c;
+            }
+        }
+        return result;
+    }
+    function unicodeUnescape(initial) {
+        var result = initial.replace(/\\u([\da-f]{4})/gi, function(match, grp) {
+            return String.fromCharCode(parseInt(grp, 16));
+        });
+        result = unescape(result);
+        return result;
+    }
+    function removeTag(element) {
+        var parent = element.parentNode, i, iLimit, savedObject = element.thObjectVar, savedLocals = element.thLocalVars;
+        if (!!parent) {
+            for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
+                var newNode = element.childNodes[i].cloneNode(true);
+                if (newNode.nodeType === 1) {
+                    if (!!savedObject) {
+                        newNode.thObjectVar = savedObject;
+                    }
+                    if (!!savedLocals) {
+                        newNode.thLocalVars = savedLocals;
+                    }
+                }
+                parent.insertBefore(newNode, element);
+            }
+            parent.removeChild(element);
+        }
+    }
+    function getRequestEncoded(initial) {
+        var result = initial;
+        result = encodeURIComponent(result);
+        result = result.replace(/%20/g, "+");
+        result = result.replace(/%26/g, "&");
+        result = result.replace(/%3A/g, ":");
+        result = result.replace(/!/g, "%21");
+        result = result.replace(/'/g, "%27");
+        result = result.replace(/\(/g, "%28");
+        result = result.replace(/\)/g, "%29");
+        result = result.replace(/\*/g, "%2A");
+        result = result.replace(/~/g, "%7E");
+        return result;
+    }
+    return {
+        getParameter: getParameter,
+        processElement: processElement,
+        unQuote: unQuote,
+        unParenthesise: unParenthesise,
+        unBracket: unBracket,
+        getToPrecision: getToPrecision,
+        getDecimalDigits: getDecimalDigits,
+        testLiteralFalse: testLiteralFalse,
+        renderMessage: renderMessage,
+        charOcurrences: charOcurrences,
+        isLiteral: isLiteral,
+        isLiteralSubst: isLiteralSubst,
+        loadScript: loadScript,
+        unescape: unescape,
+        unicodeUnescape: unicodeUnescape,
+        removeTag: removeTag,
+        getRequestEncoded: getRequestEncoded
+    };
+}();
+
+thymol.ThParser = function(scope) {
+    function object(o) {
+        function F() {}
+        F.prototype = o;
+        return new F();
+    }
+    function NullReturn(varName) {
+        this.varName = varName;
+    }
+    var TNUMBER = 0;
+    var TOP1 = 1;
+    var TOP2 = 2;
+    var TVAR = 3;
+    var TFUNCALL = 4;
+    var MSGSUBST = 5;
+    var ARGLIST = 6;
+    function Token(type_p, index_p, prio_p, number_p, mode_p, meta_p) {
+        this.type_ = type_p;
+        this.index_ = index_p || 0;
+        this.prio_ = prio_p || 0;
+        this.number_ = number_p !== undefined && number_p !== null ? number_p : 0;
+        this.mode_ = mode_p !== undefined && mode_p !== null ? mode_p : 0;
+        this.meta_ = meta_p;
+        this.toString = function() {
+            switch (this.type_) {
+              case TNUMBER:
+                return this.number_;
+
+              case TOP1:
+              case TOP2:
+              case TVAR:
+                return this.index_;
+
+              case TFUNCALL:
+              case MSGSUBST:
+              case ARGLIST:
+                return "CALL";
+
+              default:
+                return "Invalid Token";
+            }
+        };
+    }
+    function Expression(tokens, ops1, ops2, functions, precision, position) {
+        this.tokens = tokens;
+        this.ops1 = ops1;
+        this.ops2 = ops2;
+        this.functions = functions;
+        this.precision = precision;
+        this.position = position;
+    }
+    Expression.prototype = {
+        simplify: function(valuesParam) {
+            var values = valuesParam || {};
+            var nstack = [];
+            var newexpression = [];
+            var n1;
+            var n2;
+            var f;
+            var L = this.tokens.length;
+            var item;
+            var i = 0;
+            for (i = 0; i < L; i++) {
+                item = this.tokens[i];
+                var type_ = item.type_;
+                if (type_ === TNUMBER) {
+                    nstack.push(item);
+                } else if (type_ === TVAR && !(item.index_ in new Object()) && item.index_ in values) {
+                    item = new Token(TNUMBER, 0, 0, values[item.index_]);
+                    nstack.push(item);
+                } else if (type_ === TOP2 && nstack.length > 1) {
+                    f = this.ops2[item.index_];
+                    if (!!f) {
+                        n2 = nstack.pop();
+                        n1 = nstack.pop();
+                        item = new Token(TNUMBER, 0, 0, f(n1.number_, n2.number_));
+                    }
+                    nstack.push(item);
+                } else if (type_ === TOP1 && nstack.length > 0) {
+                    if ("{" == item.index_) {
+                        if (item.mode_ == 2) {
+                            nstack.push(item);
+                        }
+                    } else {
+                        n1 = nstack.pop();
+                        f = this.ops1[item.index_];
+                        item = new Token(TNUMBER, 0, 0, f(n1.number_));
+                        nstack.push(item);
+                    }
+                } else {
+                    while (nstack.length > 0) {
+                        newexpression.push(nstack.shift());
+                    }
+                    newexpression.push(item);
+                }
+            }
+            while (nstack.length > 0) {
+                newexpression.push(nstack.shift());
+            }
+            var res = new Expression(newexpression, object(this.ops1), object(this.ops2), object(this.functions), this.precision);
+            return res;
+        },
+        evaluate: function(element) {
+            var nstack = [];
+            var n1;
+            var n2;
+            var f;
+            var res = null;
+            var L = this.tokens.length;
+            var item;
+            var i = 0;
+            var result;
+            for (i = 0; i < L; i++) {
+                item = this.tokens[i];
+                if (i === 0 && thymol.disableMessages && item.mode_ === 4) {
+                    var nullReturn = new thymol.ThClass();
+                    nullReturn.abort = true;
+                    return nullReturn;
+                }
+                var type_ = item.type_;
+                if (type_ === TNUMBER) {
+                    nstack.push(item.number_);
+                    if (i == L - 1) {
+                        break;
+                    }
+                } else if (type_ === TOP2) {
+                    n2 = nstack.pop();
+                    if (typeof n2 === "undefined" || n2 instanceof NullReturn) {
+                        n2 = null;
+                    }
+                    n1 = nstack.pop();
+                    if (typeof n1 === "undefined" || n1 instanceof NullReturn) {
+                        n1 = null;
+                    }
+                    f = this.ops2[item.index_];
+                    var pathMatch = false;
+                    try {
+                        if (item.mode_ === 6) {
+                            if (f === dot) {
+                                res = n1 + "[" + n2 + "]";
+                            } else if (f === append) {
+                                if (!!item.meta_) {
+                                    if (!!item.meta_.paths) {
+                                        var values = item.meta_.paths[n1];
+                                        if (!!values) {
+                                            values.push(n2);
+                                            pathMatch = true;
+                                            res = null;
+                                        }
+                                    }
+                                }
+                                if (!pathMatch) {
+                                    if (!item.meta_) {
+                                        item.meta_ = {};
+                                    }
+                                    if (!item.meta_.params) {
+                                        item.meta_.params = [];
+                                    }
+                                    var values = item.meta_.params[n1];
+                                    if (!values) {
+                                        values = [];
+                                        item.meta_.params[n1] = values;
+                                    }
+                                    values.push(n2);
+                                    pathMatch = true;
+                                }
+                            } else {
+                                res = n2;
+                                nstack.push(n1);
+                            }
+                        } else {
+                            if (f === dot && "class" === n2 && !!n1 && !n1["class"]) {
+                                var tn2 = typeof n2;
+                                if (tn2 === "object" && n2 instanceof thymol.ThParam) {
+                                    res = f(n1, n2);
+                                } else {
+                                    res = new thymol.ThClass("JavaScript:" + tn2);
+                                }
+                            } else {
+                                res = f(n1, n2);
+                                if (typeof res === "function") {
+                                    if (L - 1 > i) {
+                                        next = this.tokens[i + 1];
+                                        if (next.type_ === TNUMBER && Object.prototype.toString.call(next.number_) == "[object Array]" && next.number_.length == 0) {
+                                            i += 1;
+                                            nstack.push(res);
+                                            n1.isDirect = true;
+                                            res = n1;
+                                        }
+                                    }
+                                }
+                            }
+                            if (f !== append) {
+                                if (Object.prototype.toString.call(res) == "[object Array]") {
+                                    res.arrayResult = true;
+                                }
+                            }
+                        }
+                    } catch (err) {
+                        if (!element.isBlockChild) {
+                            var aValue = n1 == null ? "null" : n1;
+                            var bValue = n2 == null ? "null" : n2;
+                            var message = "while evaluating expression: " + this.tokens[i - 2].index_ + ": " + aValue + ", " + this.tokens[i - 1].index_ + ": " + bValue;
+                            throw new thymol.ThError(message, element, err);
+                        }
+                    }
+                    if (!pathMatch) {
+                        nstack.push(res);
+                    }
+                } else if (type_ === TVAR) {
+                    var next = null, pushed = nstack.length;
+                    if (item.index_ != null) {
+                        if (L - 1 > i) {
+                            next = this.tokens[i + 1];
+                            if (next.type_ === TOP2 && next.index_ === ".") {
+                                nstack.push(item.index_);
+                            }
+                        }
+                        if (pushed === nstack.length) {
+                            var val = thymol.substituteParam(item.index_, item.mode_, element);
+                            if (Object.prototype.toString.call(val) == "[object Array]") {
+                                val.arrayResult = true;
+                            }
+                            this.updatePrecision(val);
+                            if (val === null) {
+                                val = new NullReturn(item.index_);
+                            }
+                            nstack.push(val);
+                        }
+                    } else if (pushed === nstack.length && item.index_ in this.functions) {
+                        nstack.push(this.functions[item.index_]);
+                    } else {
+                        if (!element.isBlockChild) {
+                            throw new thymol.ThError("Exception undefined variable: " + item.index_, element);
+                        }
+                    }
+                } else if (type_ === TOP1) {
+                    n1 = nstack.pop();
+                    if (typeof n1 === "undefined" || n1 instanceof NullReturn) {
+                        if (item.mode_ === 2) {
+                            n1 = "";
+                        } else {
+                            n1 = null;
+                        }
+                    }
+                    res = n1;
+                    if ("{" === item.index_) {
+                        var prev = this.tokens[i - 1];
+                        if (prev.mode_ == 7) {
+                            if (thymol.conversionService) {
+                                n1 = thymol.conversionService(n1);
+                                res = n1;
+                            }
+                        }
+                        if (typeof n1 === "string") {
+                            if (item.mode_ === 2) {
+                                res = thymol.getStandardURL(n1);
+                            } else {
+                                var subst = thymol.substituteParam(n1, item.mode_, element);
+                                if (subst != null) {
+                                    this.updatePrecision(subst);
+                                    res = subst;
+                                }
+                            }
+                        }
+                    } else {
+                        f = this.ops1[item.index_];
+                        try {
+                            res = f(n1);
+                        } catch (err) {
+                            if (!element.isBlockChild) {
+                                var aValue = n1 == null ? "null" : n1;
+                                var message = "while evaluating expression: " + this.tokens[i - 2].index_ + ": " + aValue;
+                                throw new thymol.ThError(message, element, err);
+                            }
+                        }
+                    }
+                    if (Object.prototype.toString.call(res) == "[object Array]") {
+                        res.arrayResult = true;
+                    }
+                    nstack.push(res);
+                } else if (type_ === TFUNCALL || type_ === MSGSUBST || type_ === ARGLIST) {
+                    n1 = nstack.pop();
+                    f = nstack.pop();
+                    if (type_ === MSGSUBST) {
+                        if (f instanceof NullReturn) {
+                            res = "??" + f.varName + "_" + thymol.locale.value + "??";
+                        } else {
+                            res = thymol.ThUtils.renderMessage(f, n1);
+                        }
+                        nstack.push(res);
+                    } else if (type_ === ARGLIST) {
+                        var pathMatch = false;
+                        n2 = nstack.pop();
+                        if (typeof n2 === "undefined") {
+                            n2 = f;
+                            f = n1;
+                            n1 = "";
+                        }
+                        if (!!item.meta_) {
+                            if (!!item.meta_.paths) {
+                                var values = item.meta_.paths[f];
+                                if (!!values) {
+                                    values.push(n1);
+                                    pathMatch = true;
+                                }
+                                for (var j in item.meta_.paths) {
+                                    if (item.meta_.paths.hasOwnProperty(j)) {
+                                        var values = item.meta_.paths[j];
+                                        var isReq = n2.indexOf("?") >= 0;
+                                        if (!!values && values.length > 0) {
+                                            var pathVar = "{" + j + "}";
+                                            var repReg = new RegExp(pathVar, "g");
+                                            var rep = "";
+                                            values.reverse();
+                                            for (var k = 0, kLimit = values.length; k < kLimit; k++) {
+                                                if (rep.length > 0) {
+                                                    rep = rep + ",";
+                                                }
+                                                if (isReq) {
+                                                    rep = rep + thymol.ThUtils.getRequestEncoded(values[k]);
+                                                } else {
+                                                    rep = rep + encodeURIComponent(values[k]);
+                                                }
+                                            }
+                                            n2 = n2.replace(repReg, rep);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (pathMatch) {
+                            res = n2;
+                        } else {
+                            if (typeof f === "undefined" || f instanceof NullReturn) {
+                                f = "";
+                            } else {
+                                f = f.toString();
+                            }
+                            f = thymol.ThUtils.getRequestEncoded(f);
+                            f = "?" + f;
+                            n1 = n1.toString();
+                            if (f != "?" && n1 != "") {
+                                f = f + "=";
+                            }
+                            if (n1 != "") {
+                                n1 = thymol.ThUtils.getRequestEncoded(n1);
+                                f = f + n1;
+                            }
+                            if (typeof n2 === "undefined" || n2 instanceof NullReturn) {
+                                n2 = "";
+                            } else {
+                                n2 = n2.toString();
+                            }
+                            res = n2 + f;
+                        }
+                        if (!!item.meta_) {
+                            var separator = res.indexOf("?") >= 0 ? "&" : "?";
+                            for (var j in item.meta_.params) {
+                                if (item.meta_.params.hasOwnProperty(j)) {
+                                    var values = item.meta_.params[j];
+                                    if (!!values && values.length > 0) {
+                                        for (var k = 0, kLimit = values.length; k < kLimit; k++) {
+                                            res = res + separator + thymol.ThUtils.getRequestEncoded(j) + "=" + thymol.ThUtils.getRequestEncoded(values[k]);
+                                            if (k == 0) {
+                                                separator = "&";
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                            if (!!item.meta_.urlFragment) {
+                                res = res + item.meta_.urlFragment;
+                            }
+                        }
+                        nstack.push(res);
+                    } else if (f.apply && f.call) {
+                        if (!!n1 && !!n1.isDirect) {
+                            res = f.call(n1);
+                        } else {
+                            if (n1 instanceof NullReturn) {
+                                n1 = null;
+                            }
+                            if (n1 != null && (n1.arrayResult || Object.prototype.toString.call(n1) !== "[object Array]")) {
+                                res = f.call(element, n1);
+                            } else {
+                                res = f.apply(element, n1);
+                            }
+                        }
+                        if (res instanceof String) {
+                            if (res.precision) {
+                                if (typeof this.precision === "undefined" || res.precision > this.precision) {
+                                    this.precision = res.precision;
+                                }
+                            }
+                            res = res.toString();
+                        } else if (Object.prototype.toString.call(res) == "[object Array]") {
+                            res.arrayResult = true;
+                        }
+                        nstack.push(res);
+                    } else {
+                        if (!element.isBlockChild) {
+                            throw new thymol.ThError(f + " is not a function", element);
+                        }
+                    }
+                } else {
+                    if (!element.isBlockChild) {
+                        throw new thymol.ThError("invalid expression item type: " + type_, element);
+                    }
+                }
+            }
+            if (nstack.length > 1) {
+                if (!element.isBlockChild) {
+                    throw new thymol.ThError("invalid Expression (parity)", element);
+                }
+            }
+            result = nstack[0];
+            return result;
+        },
+        updatePrecision: function(val) {
+            if (typeof val === "number") {
+                var p = thymol.ThUtils.getDecimalDigits(val);
+                if (typeof this.precision === "undefined" || p > this.precision) {
+                    this.precision = p;
+                }
+            }
+        }
+    };
+    function add(a, b) {
+        return a + b;
+    }
+    function assign(a) {
+        return a;
+    }
+    function sub(a, b) {
+        return a - b;
+    }
+    function mul(a, b) {
+        return a * b;
+    }
+    function div(a, b) {
+        return a / b;
+    }
+    function mod(a, b) {
+        return a % b;
+    }
+    function concat(a, b) {
+        return "" + a + b;
+    }
+    function neg(a) {
+        return -a;
+    }
+    function not(a) {
+        var v = thymol.getBooleanValue(a);
+        return !v;
+    }
+    function random(a) {
+        return Math.random() * (a || 1);
+    }
+    function fac(a) {
+        var aa = Math.floor(a);
+        var b = aa;
+        while (aa > 1) {
+            b = b * --aa;
+        }
+        return b;
+    }
+    function append(a, b) {
+        if (a != null) {
+            if (a.arrayResult === true || Object.prototype.toString.call(a) != "[object Array]") {
+                return [ a, b ];
+            }
+        } else {
+            if (b != null) {
+                if (b.arrayResult === true || Object.prototype.toString.call(b) != "[object Array]") {
+                    return [ a, b ];
+                }
+                return b;
+            }
+            return null;
+        }
+        var aa = a.slice();
+        aa.push(b);
+        return aa;
+    }
+    function equal(a, b) {
+        return a == b;
+    }
+    function notEqual(a, b) {
+        return a != b;
+    }
+    function gt(a, b) {
+        return a > b;
+    }
+    function ge(a, b) {
+        return a >= b;
+    }
+    function lt(a, b) {
+        return a < b;
+    }
+    function le(a, b) {
+        return a <= b;
+    }
+    function and(a, b) {
+        return a && b;
+    }
+    function or(a, b) {
+        return a || b;
+    }
+    function dot(a, b) {
+        return a[b];
+    }
+    function binary(a, b) {
+        return a ? b : null;
+    }
+    function elvis(a, b) {
+        return a != null ? a : b;
+    }
+    function getStr(pos, expression, mode, partial, preprocessed) {
+        var localMode = mode;
+        var s = "";
+        var c = expression.charAt(pos);
+        var start = pos + 1;
+        var end = expression.length;
+        var stopChar = c;
+        if (localMode === 4 || c === "#") {
+            stopChar = "}";
+            localMode = 4;
+        }
+        var i = start;
+        var inCurly = false;
+        var curlyPos = null;
+        var urlFragPos = -1;
+        var meta = null;
+        if (localMode !== 4 && c !== "'" && c !== '"') {
+            for (;i <= end; i++) {
+                if (c.toUpperCase() === c.toLowerCase()) {
+                    if (c === "{") {
+                        inCurly = true;
+                        curlyPos = i;
+                        if (meta === null) {
+                            meta = {};
+                            meta.paths = [];
+                        }
+                    } else if (mode === 2 && c === "#") {
+                        urlFragPos = i;
+                    }
+                    if (i === pos || !inCurly && c === "}" || c !== "_" && c !== "?" && c !== ":" && (c < "0" || c > "9")) {
+                        if (!(partial && c == "-") && !((mode === 2 || mode === 6) && (c === "/" || c === "." || c === "~" || c === "?" || c === "=" || c === ":" || c === "-" || c === "_" || c === "[" || c === "]" || c === "#" || inCurly && c === "{" || inCurly && c === "}")) || mode === 6 && c === "=") {
+                            i = i - 1;
+                            break;
+                        }
+                    }
+                    if (inCurly && c === "}") {
+                        inCurly = false;
+                        if (meta === null) {
+                            var message = 'bad path variable definition in expression: "' + expression + '" near column ' + pos;
+                            throw new thymol.ThError(message, element);
+                        }
+                        var curlyVar = expression.substring(curlyPos, i - 1);
+                        var values = [];
+                        meta.paths[curlyVar] = values;
+                    }
+                }
+                s += c;
+                c = expression.charAt(i);
+            }
+            if (urlFragPos >= 0) {
+                var urlFrag = expression.substring(urlFragPos - 1, i);
+                s = s.substring(0, s.length - urlFrag.length);
+                if (meta === null) {
+                    meta = {};
+                    meta.urlFragment = urlFrag;
+                }
+            }
+        } else {
+            var quoted = false;
+            var preprocessing = false;
+            if (c === "'" || c === '"') {
+                quoted = true;
+                stopChar = c;
+            }
+            while (i <= end) {
+                if (c === stopChar && i > start && !preprocessing) {
+                    if (localMode !== 4 || quoted) {
+                        s += c;
+                    } else {
+                        i = i - 1;
+                    }
+                    break;
+                }
+                var nc = expression.charAt(i);
+                if (c === "_" && nc === "_" && !preprocessed) {
+                    preprocessing = !preprocessing;
+                }
+                if (c === "\\") {
+                    if (nc === "'" && s.charAt(s.length - 1) !== "\\") {
+                        c = "&#39;";
+                        if (i + 1 > end) {
+                            break;
+                        }
+                        i = i + 1;
+                        nc = expression.charAt(i);
+                    }
+                }
+                if (!quoted) {
+                    if (c === ".") {
+                        var exp = thymol.thExpressionObjects[s];
+                        if (typeof exp !== "undefined" && exp !== null) {
+                            i -= 1;
+                            break;
+                        }
+                    }
+                    if (c === "(") {
+                        i -= 1;
+                        break;
+                    }
+                }
+                s += c;
+                if (i + 1 > end) {
+                    break;
+                }
+                i = i + 1;
+                c = nc;
+            }
+        }
+        var str = new Object();
+        str.str = s;
+        str.pos = i;
+        if (meta !== null) {
+            str.meta = meta;
+        }
+        return str;
+    }
+    function ThParser() {
+        this.precision;
+        this.success = false;
+        this.errormsg = "";
+        this.expression = "";
+        this.pos = 0;
+        this.tokennumber = 0;
+        this.tokenprio = 0;
+        this.tokenindex = 0;
+        this.tmpprio = 0;
+        this.ops1 = {
+            sin: Math.sin,
+            cos: Math.cos,
+            tan: Math.tan,
+            asin: Math.asin,
+            acos: Math.acos,
+            atan: Math.atan,
+            sqrt: Math.sqrt,
+            log: Math.log,
+            abs: Math.abs,
+            ceil: Math.ceil,
+            floor: Math.floor,
+            round: Math.round,
+            "-": neg,
+            "!": not,
+            not: not,
+            exp: Math.exp,
+            "=": assign
+        };
+        this.ops2 = {
+            "?": binary,
+            ":": elvis,
+            "?:": elvis,
+            "+": add,
+            "-": sub,
+            "*": mul,
+            "/": div,
+            "%": mod,
+            "^": Math.pow,
+            ",": append,
+            "||": concat,
+            "==": equal,
+            eq: equal,
+            "!=": notEqual,
+            ne: notEqual,
+            neq: notEqual,
+            div: div,
+            mod: mod,
+            and: and,
+            or: or,
+            ">": gt,
+            gt: gt,
+            ">=": ge,
+            "=>": ge,
+            ge: ge,
+            "<": lt,
+            lt: lt,
+            "<=": le,
+            "=<": le,
+            le: le,
+            ".": dot,
+            "[": dot
+        };
+        this.functions = {
+            random: random,
+            fac: fac,
+            min: Math.min,
+            max: Math.max,
+            pow: Math.pow
+        };
+        this.consts = {
+            E: Math.E,
+            PI: Math.PI
+        };
+    }
+    ThParser.parse = function(expr, partial, preprocessed) {
+        return new thymol.ThParser().parse(expr, partial, preprocessed);
+    };
+    ThParser.evaluate = function(expr, partial, element) {
+        return thymol.ThParser.parse(expr, partial, false).evaluate(element);
+    };
+    ThParser.Expression = Expression;
+    ThParser.values = {
+        sin: Math.sin,
+        cos: Math.cos,
+        tan: Math.tan,
+        asin: Math.asin,
+        acos: Math.acos,
+        atan: Math.atan,
+        sqrt: Math.sqrt,
+        log: Math.log,
+        abs: Math.abs,
+        ceil: Math.ceil,
+        floor: Math.floor,
+        round: Math.round,
+        random: random,
+        fac: fac,
+        exp: Math.exp,
+        min: Math.min,
+        max: Math.max,
+        pow: Math.pow,
+        E: Math.E,
+        PI: Math.PI
+    };
+    var PRIMARY = 1 << 0;
+    var OPERATOR = 1 << 1;
+    var FUNCTION = 1 << 2;
+    var LPAREN = 1 << 3;
+    var RPAREN = 1 << 4;
+    var COMMA = 1 << 5;
+    var SIGN = 1 << 6;
+    var CALL = 1 << 7;
+    var NULLARY_CALL = 1 << 8;
+    var LBRACK = 1 << 9;
+    var RBRACK = 1 << 10;
+    var LVARBRK = 1 << 11;
+    var RVARBRK = 1 << 11;
+    var OPTION = 1 << 12;
+    var ASSIGN = 1 << 13;
+    ThParser.prototype = {
+        parse: function(expr, partial, preprocessed) {
+            this.errormsg = "";
+            this.success = true;
+            var operstack = [];
+            var tokenstack = [];
+            var modestack = [];
+            this.tmpprio = 0;
+            var expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | OPERATOR | SIGN | OPTION;
+            var noperators = 0;
+            this.expression = expr;
+            this.pos = 0;
+            this.mode = 0;
+            while (this.pos < this.expression.length) {
+                if (this.isWhite()) {} else if (this.isOperator()) {
+                    if (this.isSign() && expected & SIGN) {
+                        if (this.isNegativeSign()) {
+                            this.tokenprio = 6;
+                            this.tokenindex = "-";
+                            noperators++;
+                            this.addfunc(tokenstack, operstack, TOP1);
+                        }
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                    } else if (this.isAssign() && expected & ASSIGN) {
+                        noperators++;
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                    } else if (this.isComment()) {} else {
+                        if (this.tokenindex == "!") {
+                            if ((expected & SIGN) === 0) {
+                                this.error_parsing(this.pos, "unexpected sign");
+                            }
+                            noperators += 1;
+                            this.addfunc(tokenstack, operstack, TOP1);
+                        } else {
+                            if ((expected & OPERATOR) === 0) {
+                                this.error_parsing(this.pos, "unexpected operator");
+                            }
+                            noperators += 2;
+                            this.addfunc(tokenstack, operstack, TOP2);
+                        }
+                        if (this.expression.charAt(this.pos - 1) === "[") {
+                            this.tmpprio += 20;
+                        }
+                        expected = PRIMARY | OPERATOR | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                    }
+                } else if (this.isNumber()) {
+                    if ((expected & PRIMARY) === 0) {
+                        this.error_parsing(this.pos, "unexpected number");
+                    }
+                    var token = new Token(TNUMBER, 0, 0, this.tokennumber);
+                    tokenstack.push(token);
+                    expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA;
+                } else if (this.isLeftParenth()) {
+                    if ((expected & LPAREN) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "("');
+                    }
+                    modestack.push(this.mode);
+                    if (expected & CALL) {
+                        noperators += 2;
+                        this.tokenprio = -2;
+                        this.tokenindex = -1;
+                        this.tmpprio += 2;
+                        var ft = TFUNCALL;
+                        if (this.mode === 4) {
+                            ft = MSGSUBST;
+                            this.mode = 5;
+                        } else if (this.mode === 2) {
+                            ft = ARGLIST;
+                            this.mode = 6;
+                            var url = tokenstack[tokenstack.length - 1];
+                            if (!url.meta_) {
+                                url.meta_ = {};
+                            }
+                            this.meta = url.meta_;
+                        } else {
+                            this.mode = 5;
+                        }
+                        this.addfunc(tokenstack, operstack, ft);
+                        this.tmpprio -= 2;
+                    }
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio += 10;
+                    }
+                    expected = PRIMARY | OPERATOR | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION | NULLARY_CALL;
+                } else if (this.isRightParenth()) {
+                    if (expected & NULLARY_CALL) {
+                        var token = new Token(TNUMBER, 0, 0, []);
+                        tokenstack.push(token);
+                    } else if ((expected & RPAREN) === 0) {
+                        this.error_parsing(this.pos, 'unexpected ")"');
+                    }
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio -= 10;
+                    }
+                    this.mode = modestack.pop();
+                    expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
+                } else if (this.isRightBracket()) {
+                    if ((expected & RBRACK) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "]"');
+                    }
+                    expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
+                } else if (this.isLeftVarBrk(modestack)) {
+                    if ((expected & LVARBRK) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "{"');
+                    }
+                    noperators += 1;
+                    this.addfunc(tokenstack, operstack, TOP1);
+                    expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                } else if (this.isRightVarBrk()) {
+                    if ((expected & RVARBRK) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "}"');
+                    }
+                    this.mode = modestack.pop();
+                    expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
+                } else if (this.isLeftCurly()) {
+                    if (this.mode == 1 || this.mode == 2 || this.mode == 3 || this.mode == 4) {
+                        modestack.push(this.mode);
+                        this.mode = 7;
+                    } else {
+                        this.error_parsing(this.pos, 'unexpected "{"');
+                    }
+                } else if (this.isRightCurly()) {
+                    if (this.mode == 7) {
+                        this.mode = modestack.pop();
+                    } else {
+                        this.error_parsing(this.pos, 'unexpected "}"');
+                    }
+                } else if (this.isComma()) {
+                    if ((expected & COMMA) === 0) {
+                        this.error_parsing(this.pos, 'unexpected ","');
+                    }
+                    if (!!partial) {
+                        break;
+                    }
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio -= 10;
+                    }
+                    this.tmpprio += 2;
+                    this.addfunc(tokenstack, operstack, TOP2);
+                    this.tmpprio -= 2;
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio += 10;
+                    }
+                    noperators += 2;
+                    expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                } else if (this.isConst()) {
+                    if ((expected & PRIMARY) === 0) {
+                        this.error_parsing(this.pos, "unexpected constant");
+                    }
+                    var consttoken = new Token(TNUMBER, 0, 0, this.tokennumber);
+                    tokenstack.push(consttoken);
+                    expected = OPERATOR | RPAREN | RVARBRK | RBRACK | COMMA;
+                } else {
+                    var str = getStr(this.pos, this.expression, this.mode, partial, preprocessed);
+                    if (this.isOpX(str, this.ops2) && (this.mode !== 2 && "/" !== str)) {
+                        if ("and" === str.str || "or" === str.str) {
+                            this.tokenprio = 3;
+                        }
+                        if ((expected & OPERATOR) === 0) {
+                            this.error_parsing(this.pos, "unexpected binary operator");
+                        }
+                        this.addfunc(tokenstack, operstack, TOP2);
+                        noperators += 2;
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | OPERATOR | SIGN | OPTION;
+                    } else if (this.isOpX(str, this.ops1)) {
+                        if ((expected & OPERATOR) === 0) {
+                            this.error_parsing(this.pos, "unexpected unary operator");
+                        }
+                        this.addfunc(tokenstack, operstack, TOP1);
+                        noperators++;
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION;
+                    } else if (this.isLiteralValue(str)) {
+                        if ((expected & PRIMARY) === 0) {
+                            this.error_parsing(this.pos, "unexpected literal value");
+                        }
+                        var token = new Token(TNUMBER, 0, 0, this.tokennumber);
+                        tokenstack.push(token);
+                        expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | RVARBRK | LBRACK | CALL | OPTION;
+                        if (this.mode === 6) {
+                            expected = expected | ASSIGN;
+                        }
+                    } else if (this.isVar(str)) {
+                        if ((expected & PRIMARY) === 0) {
+                            this.error_parsing(this.pos, "unexpected variable");
+                        }
+                        var vartoken = new Token(TVAR, this.tokenindex, 0, 0, this.mode, str.meta);
+                        tokenstack.push(vartoken);
+                        expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | RVARBRK | LBRACK | CALL | OPTION | ASSIGN;
+                    } else {
+                        if (this.errormsg === "") {
+                            this.error_parsing(this.pos, "unknown character");
+                        } else {
+                            this.error_parsing(this.pos, this.errormsg);
+                        }
+                    }
+                }
+            }
+            if (this.tmpprio < 0 || this.tmpprio >= 10) {
+                this.error_parsing(this.pos, 'unmatched "() or []"');
+            }
+            while (operstack.length > 0) {
+                var tmp = operstack.pop();
+                tokenstack.push(tmp);
+            }
+            if (noperators + 1 !== tokenstack.length) {
+                this.error_parsing(this.pos, "parity");
+            }
+            var res = new Expression(tokenstack, object(this.ops1), object(this.ops2), object(this.functions), this.precision, this.pos);
+            return res;
+        },
+        evaluate: function(expr, element) {
+            return this.parse(expr).evaluate(element);
+        },
+        error_parsing: function(column, msg) {
+            this.success = false;
+            this.errormsg = "parse error [column " + column + "]: " + msg;
+            throw new Error(this.errormsg);
+        },
+        addfunc: function(tokenstack, operstack, type_) {
+            var operator = new Token(type_, this.tokenindex, this.tokenprio + this.tmpprio, 0, this.mode, this.meta);
+            while (operstack.length > 0) {
+                if (operator.prio_ <= operstack[operstack.length - 1].prio_) {
+                    tokenstack.push(operstack.pop());
+                } else {
+                    break;
+                }
+            }
+            operstack.push(operator);
+        },
+        isNumber: function() {
+            var r = false;
+            var str = "";
+            var prec = -1;
+            while (this.pos < this.expression.length) {
+                var code = this.expression.charCodeAt(this.pos);
+                if (code >= 48 && code <= 57 || code === 46) {
+                    str += this.expression.charAt(this.pos);
+                    if (prec >= 0 || code === 46) {
+                        prec++;
+                    }
+                    this.pos++;
+                    r = true;
+                } else {
+                    break;
+                }
+            }
+            if (r) {
+                if (prec >= 0 && (typeof this.precision === "undefined" || prec > this.precision)) {
+                    this.precision = prec;
+                }
+                this.tokennumber = parseFloat(str);
+            }
+            return r;
+        },
+        isConst: function() {
+            var str;
+            for (var i in this.consts) {
+                if (true) {
+                    var L = i.length;
+                    str = this.expression.substr(this.pos, L);
+                    if (i === str) {
+                        this.tokennumber = this.consts[i];
+                        this.pos += L;
+                        return true;
+                    }
+                }
+            }
+            return false;
+        },
+        isOperator: function() {
+            var ch = this.expression.charAt(this.pos);
+            if (ch === "+") {
+                this.tokenprio = 0;
+                this.tokenindex = "+";
+            } else if (ch === "-") {
+                this.tokenprio = 0;
+                this.tokenindex = "-";
+            } else if (ch === "|") {
+                if (this.expression.charAt(this.pos + 1) === "|") {
+                    this.pos++;
+                    this.tokenprio = 0;
+                    this.tokenindex = "||";
+                } else {
+                    return false;
+                }
+            } else if (ch === "*") {
+                if (this.expression.charAt(this.pos + 1) === "{") {
+                    return false;
+                }
+                this.tokenprio = 1;
+                this.tokenindex = "*";
+            } else if (ch === "/" && this.mode != 2 && this.pos > 0) {
+                this.tokenprio = 2;
+                this.tokenindex = "/";
+            } else if (ch === "%") {
+                this.tokenprio = 2;
+                this.tokenindex = "%";
+            } else if (ch === "^") {
+                this.tokenprio = 3;
+                this.tokenindex = "^";
+            } else if (ch === "=" || ch === "!") {
+                if (this.expression.charAt(this.pos + 1) === "=") {
+                    if (ch === "=") {
+                        this.tokenindex = "==";
+                    } else if (ch === "!") {
+                        this.tokenindex = "!=";
+                    } else {
+                        return false;
+                    }
+                    this.pos++;
+                    this.tokenprio = 6;
+                } else if (ch === "!") {
+                    this.tokenprio = 7;
+                    this.tokenindex = "!";
+                } else if (ch === "=") {
+                    this.tokenindex = "=";
+                } else {
+                    return false;
+                }
+            } else if (ch === "<") {
+                if (this.expression.charAt(this.pos + 1) === "=") {
+                    this.tokenindex = "<=";
+                    this.pos++;
+                } else {
+                    this.tokenindex = "<";
+                }
+                this.tokenprio = 4;
+            } else if (ch === ">") {
+                if (this.expression.charAt(this.pos + 1) === "=") {
+                    this.tokenindex = ">=";
+                    this.pos++;
+                } else {
+                    this.tokenindex = ">";
+                }
+                this.tokenprio = 4;
+            } else if (ch === "." || ch === "[") {
+                this.tokenprio = 10;
+                this.tokenindex = ".";
+            } else {
+                return false;
+            }
+            this.pos++;
+            return true;
+        },
+        isRightBracket: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 93) {
+                this.pos++;
+                this.tmpprio -= 20;
+                return true;
+            }
+            return false;
+        },
+        isSign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 45 || code === 43) {
+                return true;
+            }
+            return false;
+        },
+        isAssign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 61) {
+                var cha = this.expression.charAt(this.pos - 2);
+                if (cha === "!" || cha === ">" || cha === "<" || cha === "=") {
+                    return false;
+                }
+                cha = this.expression.charAt(this.pos);
+                if (cha === ">" || cha === "<" || cha === "=") {
+                    return false;
+                }
+                return true;
+            }
+            return false;
+        },
+        isPositiveSign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 43) {
+                return true;
+            }
+            return false;
+        },
+        isNegativeSign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 45) {
+                return true;
+            }
+            return false;
+        },
+        isLeftParenth: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 40) {
+                this.pos++;
+                this.tmpprio += 10;
+                return true;
+            }
+            return false;
+        },
+        isRightParenth: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 41) {
+                this.pos++;
+                this.tmpprio -= 10;
+                return true;
+            }
+            return false;
+        },
+        isLeftCurly: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 123) {
+                this.pos++;
+                this.tmpprio += 10;
+                return true;
+            }
+            return false;
+        },
+        isRightCurly: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 125) {
+                this.pos++;
+                this.tmpprio -= 10;
+                return true;
+            }
+            return false;
+        },
+        isComma: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 44) {
+                this.pos++;
+                this.tokenprio = -1;
+                this.tokenindex = ",";
+                return true;
+            }
+            return false;
+        },
+        isWhite: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 32 || code === 9 || code === 10 || code === 13) {
+                this.pos++;
+                return true;
+            }
+            return false;
+        },
+        isLeftVarBrk: function(modestack) {
+            var pp = this.pos, ch = this.expression.charAt(pp);
+            if (ch === "$" || ch === "@" || ch === "*" || ch === "#") {
+                pp++;
+                var ch2 = this.expression.charAt(pp);
+                if (ch2 === "{") {
+                    pp++;
+                    this.tmpprio += 10;
+                    this.tokenprio = -4;
+                    var oldMode = this.mode;
+                    modestack.push(oldMode);
+                    if (ch === "$") {
+                        this.mode = 1;
+                    } else if (ch === "@") {
+                        this.mode = 2;
+                    } else if (ch === "*") {
+                        this.mode = 3;
+                    } else if (ch === "#") {
+                        this.mode = 4;
+                    }
+                    this.tokenindex = "{";
+                    this.pos = pp;
+                    return true;
+                }
+            }
+            return false;
+        },
+        isRightVarBrk: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 125) {
+                this.pos++;
+                this.tmpprio -= 10;
+                return true;
+            }
+            return false;
+        },
+        isOpX: function(str, group) {
+            if (str.str.length > 0) {
+                if (str.str in new Object()) {
+                    return false;
+                }
+                if (str.str in group) {
+                    this.tokenindex = str.str;
+                    this.tokenprio = 5;
+                    this.pos = str.pos;
+                    return true;
+                }
+            }
+            return false;
+        },
+        isLiteralValue: function(str) {
+            if (typeof str.str === "string") {
+                var first = str.str.charAt(0);
+                var last = str.str.charAt(str.str.length - 1);
+                if (first == "'" && last == "'" || first == '"' && last == '"') {
+                    this.tokennumber = str.str.substring(1, str.str.length - 1);
+                    this.pos = str.pos;
+                    return true;
+                }
+            }
+            return false;
+        },
+        isVar: function(str) {
+            if (str.str.length > 0) {
+                this.tokenindex = str.str;
+                this.tokenprio = 4;
+                this.pos = str.pos;
+                return true;
+            }
+            return false;
+        },
+        isComment: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 47 && this.expression.charCodeAt(this.pos) === 42) {
+                this.pos = this.expression.indexOf("*/", this.pos) + 2;
+                if (this.pos === 1) {
+                    this.pos = this.expression.length;
+                }
+                return true;
+            }
+            return false;
+        }
+    };
+    return ThParser;
+}();
+
+(function() {
+    var specAttrModList = [ "abbr", "accept", "accept-charset", "accesskey", "action", "align", "alt", "archive", "audio", "autocomplete", "axis", "background", "bgcolor", "border", "cellpadding", "cellspacing", "challenge", "charset", "cite", "class", "classid", "codebase", "codetype", "cols", "colspan", "compact", "content", "contenteditable", "contextmenu", "data", "datetime", "dir", "draggable", "dropzone", "enctype", "for", "form", "formaction", "formenctype", "formmethod", "formtarget", "frame", "frameborder", "headers", "height", "high", "href", "hreflang", "hspace", "http-equiv", "icon", "id", "keytype", "kind", "label", "lang", "list", "longdesc", "low", "manifest", "marginheight", "marginwidth", "max", "maxlength", "media", "method", "min", "name", "optimum", "pattern", "placeholder", "poster", "preload", "radiogroup", "rel", "rev", "rows", "rowspan", "rules", "sandbox", "scheme", "scope", "scrolling", "size", "sizes", "span", "spellcheck", "src", "srclang", "standby", "start", "step", "style", "summary", "tabindex", "target", "title", "type", "usemap", "value", "valuetype", "vspace", "width", "wrap", "xmlbase", "xmllang", "xmlspace" ];
+    var fixedValBoolAttrList = [ "async", "autofocus", "autoplay", "checked", "controls", "declare", "default", "defer", "disabled", "formnovalidate", "hidden", "ismap", "loop", "multiple", "novalidate", "nowrap", "open", "pubdate", "readonly", "required", "reversed", "scoped", "seamless", "selected" ];
+    var eventAttrList = [ "onabort", "onafterprint", "onbeforeprint", "onbeforeunload", "onblur", "oncanplay", "oncanplaythrough", "onchange", "onclick", "oncontextmenu", "ondblclick", "ondrag", "ondragend", "ondragenter", "ondragleave", "ondragover", "ondragstart", "ondrop", "ondurationchanged", "onemptied", "onended", "onerror", "onfocus", "onformchange", "onforminput", "onhashchange", "oninput", "oninvalid", "onkeydown", "onkeypress", "onkeyup", "onload", "onloadeddata", "onloadedmetadata", "onloadstart", "onmessage", "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onmousewheel", "onoffline", "ononline", "onpause", "onplay", "onplaying", "onpopstate", "onprogress", "onratechange", "onreadystatechange", "onredo", "onreset", "onresize", "onscroll", "onseeked", "onseeking", "onselect", "onshow", "onstalled", "onstorage", "onsubmit", "onsuspend", "ontimeupdate", "onundo", "onunload", "onvolumechange", "onwaiting" ];
+    var literalTokenExpr = /^[a-zA-Z0-9\[\]\.\-_]*$/;
+    var numericExpr = /^[+\-]?[0-9]*?[.]?[0-9]*?$/;
+    var nonURLExpr = /[\$\*#]{1}\{(?:!?[^}]*)\}/;
+    var varExpr = /[\$\*#@]{1}\{(!?[^}]*)\}/;
+    var textInlineCommentExpr = /\[\[(.*)\]\]/;
+    var javascriptInlineCommentExpr = /\/\*\[\[(.*)\]\]\*\//;
+    var javascriptInlineRemainderExpr = /\s*(?:['][^']*['])*(?:["][^"]*["])*(?:[\(][^\(\)]*[\)])*(?:[\{][^\{\}]*[\}])*(?:[\[][^\[\]]*[\]])*((?:[;,\(\)\[\]:\{\}](?=(?:\s*\/\/.*?(?:\n|$)))(?:\s*\/\/.*?(?:\n|$)))|(?:\s*\/\/.*?(?:\n|$))|(?:[;,\(\)\[\]:\{\}](?=(?:\s*(?:\n|$)))(?:\s*(?:\n|$)))|(?:\s*(?:\n|$)))/;
+    var thCase;
+    thymol.getThAttribute = function(part, element) {
+        var result = thymol.ThUtils.unParenthesise(part);
+        result = thymol.doExpression(result, element);
+        if (Object.prototype.toString.call(result) === "[object Array]") {
+            if (result.length === 1) {
+                result = result[0];
+            }
+        }
+        if (result instanceof thymol.ThParam) {
+            result = result.value;
+        }
+        return result;
+    };
+    thymol.doExpression = function(part, element) {
+        var result = thymol.ThUtils.unParenthesise(part), expr, unq, token, mapped;
+        expr = null;
+        unq = thymol.ThUtils.unQuote(result);
+        if (unq != result) {
+            result = thymol.preProcess(unq, element);
+        } else {
+            if (literalTokenExpr.test(result)) {
+                token = thymol.booleanAndNullTokens[result];
+                if (!(typeof token === "undefined")) {
+                    result = token;
+                } else {
+                    if (result.match(numericExpr)) {
+                        result = thymol.ThUtils.getToPrecision(result, thymol.ThUtils.getDecimalDigits(result));
+                    } else {
+                        expr = thymol.getExpression(result, element);
+                        if (expr !== undefined && expr !== null && !(expr != expr)) {
+                            result = expr;
+                        }
+                    }
+                }
+            } else {
+                expr = thymol.getExpression(result, element);
+                if (expr !== null && !(expr != expr)) {
+                    result = expr;
+                } else {
+                    result = null;
+                }
+            }
+        }
+        return result;
+    };
+    thymol.processText = function(element, thUrlAttr, thAttr) {
+        var url = thymol.getThAttribute(thUrlAttr.value, element), updated = false, text, newTextNode, i, iLimit, iUpper;
+        if (url == null) {
+            if (!thymol.allowNullText) {
+                if (thymol.debug) {
+                    thymol.thWindow.alert("thymol.processText cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
+                }
+                return updated;
+            }
+            url = "";
+        } else {
+            if (url instanceof thymol.ThParam || url instanceof thymol.ThObject) {
+                if (url.value) {
+                    url = url.value;
+                }
+            } else if (url instanceof thymol.ThClass && url.abort) {
+                element.removeAttribute(thUrlAttr.name);
+                return true;
+            }
+        }
+        try {
+            while (element.firstChild != null) {
+                element.removeChild(element.firstChild);
+                updated = true;
+                if (element.firstChild == null) {
+                    break;
+                }
+            }
+            if ("text" == thAttr.suffix) {
+                if (Object.prototype.toString.call(url) === "[object Array]") {
+                    text = "[";
+                    for (i = 0, iLimit = url.length, iUpper = url.length - 1; i < iLimit; i++) {
+                        text += url[i].toString();
+                        if (i < iUpper) {
+                            text += ", ";
+                        }
+                    }
+                    text += "]";
+                } else {
+                    text = url.toString();
+                }
+                text = thymol.ThUtils.unescape(text);
+                newTextNode = element.ownerDocument.createTextNode(text);
+                element.appendChild(newTextNode);
+                updated = true;
+            }
+            if ("utext" == thAttr.suffix) {
+                element.innerHTML = url;
+            }
+            element.removeAttribute(thUrlAttr.name);
+        } catch (err) {
+            if (thymol.debug) {
+                thymol.thWindow.alert("text replace error");
+            }
+        }
+        return updated;
+    };
+    thymol.processSpecAttrMod = function(element, thUrlAttr, thAttrObj) {
+        var url = thymol.getThAttribute(thUrlAttr.value, element);
+        if (!url || !(url instanceof thymol.ThClass) || !url.abort) {
+            element.setAttribute(thAttrObj.suffix, url);
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processAttr = function(element, thUrlAttr, thAttrObj) {
+        var argValue = thUrlAttr.value.trim(), argsExpr, expr, identifier, attrName = null, ep, lp, url, tt;
+        if (argValue) {
+            do {
+                argsExpr = thymol.ThParser.parse(argValue, true, false);
+                identifier = argsExpr.tokens.shift();
+                if (identifier.type_ === 3) {
+                    attrName = identifier.index_;
+                    if (!!attrName) {
+                        ep = argValue.indexOf("=");
+                        if (ep >= 0) {
+                            lp = argsExpr.position - 1;
+                            if (argsExpr.position === argValue.length) {
+                                lp = argValue.position;
+                            }
+                            expr = argValue.substring(ep + 1, lp).trim();
+                            if (fixedValBoolAttrList.indexOf(attrName) >= 0) {
+                                thymol.doFixedValBoolAttr(expr, element, attrName);
+                            } else {
+                                url = thymol.getThAttribute(expr, element);
+                                tt = typeof url;
+                                if (thAttrObj.suffix == "attrappend" || thAttrObj.suffix == "attrprepend") {
+                                    if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                                        existing = element.getAttribute(attrName);
+                                        if (existing) {
+                                            if (thAttrObj.suffix == "attrappend") {
+                                                url = existing + url;
+                                            } else if (thAttrObj.suffix == "attrprepend") {
+                                                url = url + existing;
+                                            }
+                                        }
+                                    }
+                                }
+                                if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                                    element.setAttribute(attrName, url);
+                                }
+                            }
+                        }
+                    }
+                    argValue = argValue.substring(argsExpr.position);
+                } else {
+                    break;
+                }
+            } while (argValue.length > 0);
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processCSSAttr = function(element, thUrlAttr, thAttrObj) {
+        var parts = thUrlAttr.value.split(","), i, iLimit, expr, attrName, url, tt, existing;
+        for (i = 0, iLimit = parts.length; i < iLimit; i++) {
+            expr = parts[i];
+            attrName = thAttrObj.suffix == "classappend" ? "class" : "style";
+            if (!!attrName) {
+                if (!!expr) {
+                    url = thymol.getThAttribute(expr, element);
+                    tt = typeof url;
+                    if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                        existing = element.getAttribute(attrName);
+                        if (existing) {
+                            url = existing + " " + url;
+                        }
+                    }
+                    if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                        element.setAttribute(attrName, url);
+                    }
+                }
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processFixedValBoolAttr = function(element, thUrlAttr, thAttrObj) {
+        var val = thymol.doFixedValBoolAttr(thUrlAttr.value, element, thAttrObj.suffix);
+        if (val != null) {
+            element.removeAttribute(thUrlAttr.name);
+        } else {
+            if (thymol.debug) {
+                thymol.thWindow.alert("thymol.processFixedValBoolAttr cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
+            }
+        }
+    };
+    thymol.doFixedValBoolAttr = function(valParam, element, attr) {
+        var val = thymol.getBoolean(valParam, element);
+        if (val) {
+            element.setAttribute(attr, attr);
+        }
+        return val;
+    };
+    thymol.processPairedAttr = function(element, thUrlAttr, thAttrObj) {
+        var url = thymol.getThAttribute(thUrlAttr.value, element);
+        if (url != "") {
+            if (thAttrObj.suffix === "alt-title") {
+                element.setAttribute("alt", url);
+                element.setAttribute("title", url);
+            }
+            if (thAttrObj.suffix === "lang-xmllang") {
+                element.setAttribute("lang", url);
+                element.setAttribute("xml:lang", url);
+            }
+            element.removeAttribute(thUrlAttr.name);
+        } else {
+            if (thymol.debug) {
+                thymol.thWindow.alert("thymol.processPairedAttr cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
+            }
+        }
+    };
+    thymol.processConditional = function(element, attr, thAttrObj) {
+        var removed = false;
+        if (attr.value) {
+            removed = thymol.doIfOrUnless(element, attr.value, thAttrObj.suffix === "if");
+        }
+        element.removeAttribute(attr.name);
+        return removed;
+    };
+    thymol.doIfOrUnless = function(element, value, isIf) {
+        var processed = false, flag;
+        if (value) {
+            flag = thymol.getBoolean(value, element);
+            processed = true;
+            if (!flag) {
+                if (isIf) {
+                    element.parentNode.removeChild(element);
+                    return true;
+                }
+            } else {
+                if (!isIf) {
+                    element.parentNode.removeChild(element);
+                    return true;
+                }
+            }
+        }
+        if (!processed && thymol.debug) {
+            thymol.thWindow.alert("thymol.processConditional cannot process conditional: " + value + "\n" + element.innerHTML);
+        }
+        return false;
+    };
+    thymol.processEach = function(element, thUrlAttr, junk) {
+        var elementsUpdated = false, initial = thUrlAttr.value.trim(), colonPos, varName, varNames, statVarName, expr, root, node, i, iLimit, tho, stat, count, newNode, next;
+        colonPos = initial.indexOf(":");
+        if (colonPos > 0) {
+            varName = initial.substring(0, colonPos);
+            if (varName) {
+                varName = varName.trim();
+                varNames = varName.split(",");
+                varName = varNames[0].trim();
+                if (varNames.length > 1) {
+                    statVarName = varNames[1].trim();
+                } else {
+                    statVarName = varName + "Stat";
+                }
+                expr = initial.substr(colonPos + 1);
+                if (expr) {
+                    expr = expr.trim();
+                    expr = thymol.getExpression(expr, element);
+                    if (expr instanceof thymol.ThSet) {
+                        expr = expr.toArray();
+                    }
+                    root = element.parentNode;
+                    if (expr && expr instanceof Object && expr.length > 0) {
+                        node = element;
+                        iLimit = expr.length;
+                        element.removeAttribute(thUrlAttr.name);
+                        for (i = 0; i < iLimit; i++) {
+                            tho = expr[i];
+                            stat = new Object();
+                            stat.current = tho;
+                            stat.size = expr.length;
+                            stat.index = i;
+                            count = i + 1;
+                            stat.count = count;
+                            if (i == 0) {
+                                stat.first = true;
+                            } else {
+                                stat.first = false;
+                            }
+                            if (i == expr.length - 1) {
+                                stat.last = true;
+                            } else {
+                                stat.last = false;
+                            }
+                            if (i % 2) {
+                                stat.odd = true;
+                                stat.even = false;
+                            } else {
+                                stat.odd = false;
+                                stat.even = true;
+                            }
+                            if (!node.thLocalVars) {
+                                node.thLocalVars = {};
+                            }
+                            node.thLocalVars[varName] = tho;
+                            node.thLocalVars[statVarName] = stat;
+                            if (count < expr.length) {
+                                newNode = element.cloneNode(true);
+                                if (node.nextElementSibling != null) {
+                                    next = root.insertBefore(newNode, node.nextElementSibling);
+                                } else {
+                                    next = root.appendChild(newNode);
+                                }
+                                node = next;
+                                elementsUpdated = true;
+                            }
+                        }
+                    } else {
+                        if (root !== null) {
+                            if (!element.thLocalVars) {
+                                element.thLocalVars = {};
+                            }
+                            if (!element.thLocalVars[varName]) {
+                                element.thLocalVars[varName] = new Object();
+                            }
+                            if (!element.thLocalVars[statVarName]) {
+                                element.thLocalVars[statVarName] = new Object();
+                            }
+                            root.removeChild(element);
+                            elementsUpdated = true;
+                        }
+                    }
+                }
+            }
+        }
+        return elementsUpdated;
+    };
+    thymol.processObject = function(element, thUrlAttr) {
+        var argValue = thUrlAttr.value.trim(), val;
+        if (argValue) {
+            val = thymol.getExpression(argValue, element);
+            if (val) {
+                element.thObjectVar = val;
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processInline = function(element, thUrlAttr, thAttrObj) {
+        var mode = thymol.getThAttribute(thUrlAttr.value, element);
+        if (mode == "text") {
+            thymol.doInlineText(element);
+        } else if (mode == "javascript" || mode == "dart") {
+            thymol.doInlineJavascript(element);
+        } else {
+            if (thymol.debug) {
+                thymol.thWindow.alert('thymol.processInline cannot process scripting mode: "' + mode + '" - it isn\'t supported by version "' + thymol.thVersion + '"\n');
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.doInlineText = function(element) {
+        var changed, value, i, iLimit, expr, term, result;
+        for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
+            do {
+                changed = false;
+                if (element.childNodes[i].nodeType == 1) {
+                    thymol.doInlineText(element.childNodes[i]);
+                } else if (element.childNodes[i].nodeType == 3) {
+                    value = element.childNodes[i].nodeValue;
+                    if (value) {
+                        expr = textInlineCommentExpr.exec(value);
+                        if (expr) {
+                            term = "";
+                            if (expr.length > 1) {
+                                term = "[[" + expr[1] + "]]";
+                            }
+                            if (expr.length > 1) {
+                                result = thymol.getThAttribute(expr[1], element);
+                                result = value.replace(term, result);
+                                element.childNodes[i].nodeValue = result;
+                                changed = true;
+                            }
+                            expr = null;
+                        }
+                    }
+                }
+            } while (changed);
+        }
+    };
+    thymol.doInlineJavascript = function(element) {
+        var changed, value, second, i, iLimit, expr, scraps, remainder, termIndx, term, secondIndx, result;
+        for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
+            do {
+                second = null;
+                changed = false;
+                value = element.childNodes[i].nodeValue;
+                if (value) {
+                    expr = javascriptInlineCommentExpr.exec(value);
+                    if (expr) {
+                        termIndx = expr.index;
+                        term = "";
+                        if (expr.length > 1) {
+                            term = "/*[[" + expr[1] + "]]*/";
+                        }
+                        termIndx = termIndx + term.length;
+                        remainder = value.substring(termIndx);
+                        scraps = javascriptInlineRemainderExpr.exec(remainder);
+                        if (scraps) {
+                            if (scraps.length > 1) {
+                                secondIndx = remainder.indexOf(scraps[1]);
+                                second = remainder.substring(secondIndx);
+                                value = value.substring(0, termIndx);
+                                value = value + second;
+                            }
+                        }
+                        if (expr.length > 1) {
+                            result = thymol.getExpression(expr[1], element);
+                            if (result instanceof thymol.ThObject) {
+                                result = result.toNonThObject();
+                            }
+                            if (!thymol.ThUtils.isLiteral(result)) {
+                                result = thymol.getStringView(result);
+                            }
+                            result = value.replace(term, result);
+                            element.childNodes[i].nodeValue = result;
+                            changed = true;
+                        }
+                        expr = null;
+                        scraps = null;
+                    }
+                }
+            } while (changed);
+        }
+    };
+    thymol.getStringView = function(param) {
+        var view = "", objType;
+        if (typeof param === "string") {
+            view = view + "'" + param + "'";
+        } else if (typeof param === "number" || typeof param === "boolean") {
+            view = view + param;
+        } else if (typeof param === "object") {
+            if (param instanceof Object) {
+                objType = Object.prototype.toString.call(param);
+                if ("[object Array]" == objType) {
+                    view = thymol.getStringViewArray(param);
+                } else if ("[object Object]" == objType) {
+                    view = thymol.getStringViewObject(param);
+                }
+            }
+        }
+        return view;
+    };
+    thymol.getStringViewArray = function(param) {
+        var view = "[", i, iLimit;
+        for (i = 0, iLimit = param.length; i < iLimit; i++) {
+            view = view + thymol.getStringView(param[i]);
+            if (i < param.length - 1) {
+                view = view + ",";
+            }
+        }
+        view = view + "]";
+        return view;
+    };
+    thymol.getStringViewObject = function(param) {
+        var view = "{", key = null;
+        for (key in param) {
+            if (key) {
+                if (view != "{") {
+                    view = view + ",";
+                }
+                view = view + thymol.getStringView(key) + ":";
+                view = view + thymol.getStringView(param[key]);
+            }
+        }
+        view = view + "}";
+        return view;
+    };
+    thymol.processRemove = function(element, thUrlAttr) {
+        var haveRemoved = false;
+        var locals = element.thLocalVars, savedLocals = element.thLocalVars, arg, nodes, first;
+        if (!locals) {
+            locals = {};
+        }
+        if (!locals["tag"]) {
+            locals["tag"] = "tag";
+        }
+        if (!locals["body"]) {
+            locals["body"] = "body";
+        }
+        if (!locals["none"]) {
+            locals["none"] = "none";
+        }
+        if (!locals["all"]) {
+            locals["all"] = "all";
+        }
+        if (!locals["all-but-first"]) {
+            locals["all-but-first"] = "all-but-first";
+        }
+        element.thLocalVars = locals;
+        arg = thymol.getThAttribute(thUrlAttr.value, element);
+        element.thLocalVars = savedLocals;
+        element.removeAttribute(thUrlAttr.name);
+        if ("all" == arg) {
+            if (element.parentNode != null) {
+                element.parentNode.removeChild(element);
+                haveRemoved = true;
+            }
+        } else if ("body" == arg) {
+            element.innerHTML = "";
+            haveRemoved = true;
+        } else if ("tag" == arg) {
+            thymol.ThUtils.removeTag(element);
+            haveRemoved = true;
+        } else if ("all-but-first" == arg) {
+            nodes = element.childNodes;
+            first = true;
+            $(nodes).each(function() {
+                if (this.nodeType == 1) {
+                    if (!first) {
+                        element.removeChild(this);
+                        haveRemoved = true;
+                    }
+                    first = false;
+                }
+            });
+        } else if ("none" == arg || null == arg) {}
+        return haveRemoved;
+    };
+    thymol.processSwitch = function(element, attr) {
+        var val = thymol.ThUtils.unParenthesise(attr.value), updated = false, args, matched = false, thCaseSpecs, caseClause, remove, ccAttr;
+        val = thymol.getThAttribute(val, element);
+        if (typeof val === "string") {
+            args = val.match(nonURLExpr);
+            if (args) {
+                val = args[1];
+            }
+        }
+        val = thymol.ThUtils.unQuote(val);
+        thCaseSpecs = $(thCase.escpName, element);
+        thCaseSpecs.each(function() {
+            caseClause = this;
+            remove = true;
+            $(caseClause.attributes).each(function() {
+                ccAttr = this;
+                if (thCase.name == ccAttr.name || thCase.synonym == ccAttr.name) {
+                    if (!matched) {
+                        matched = thymol.processCase(element, ccAttr, val);
+                        if (matched) {
+                            remove = false;
+                        }
+                    }
+                    caseClause.removeAttribute(ccAttr.name);
+                }
+            });
+            if (remove) {
+                element.removeChild(caseClause);
+                updated = true;
+            }
+        });
+        return updated;
+    };
+    thymol.processCase = function(element, attr, param) {
+        var val = thymol.substitute(attr.value, element);
+        val = thymol.ThUtils.unQuote(val);
+        if (val == "*" || param && param == val) {
+            return true;
+        }
+        return false;
+    };
+    thymol.processWith = function(element, thUrlAttr) {
+        thymol.getWith(element, thUrlAttr.value);
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processAssert = function(element, thUrlAttr) {
+        var argValue = thUrlAttr.value.trim(), result = true, term = "", terms, i, iLimit, expr, val, flag;
+        if (argValue) {
+            terms = argValue.split(",");
+            for (i = 0, iLimit = terms.length; i < iLimit; i++) {
+                term = terms[i];
+                expr = thymol.ThUtils.unParenthesise(term);
+                if (expr != null) {
+                    val = thymol.getExpression(expr, element);
+                    if (val) {
+                        flag = thymol.getBoolean(val, element);
+                        if (!flag) {
+                            result = false;
+                            break;
+                        }
+                    } else {
+                        result = false;
+                        break;
+                    }
+                } else {
+                    result = false;
+                    break;
+                }
+            }
+        }
+        if (!result) {
+            if (argValue != term) {
+                argValue = " list is: " + argValue;
+            } else {
+                argValue = "";
+            }
+            if (term != "") {
+                term = ' false term is: "' + term + '"';
+            }
+            if (thymol.debug) {
+                thymol.thWindow.alert("thymol.processAssert assertion failure -" + argValue + term + "\n");
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processFragment = function(element, thUrlAttr, thAttrObj) {
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.getBoolean = function(param, element) {
+        if (param == null) {
+            return false;
+        }
+        if (typeof param === "boolean") {
+            return param;
+        } else if (typeof param === "number") {
+            return param != 0;
+        }
+        var initial = thymol.ThUtils.unParenthesise(param), negate = false, val, args, flag;
+        if (initial.charAt(0) == "!") {
+            negate = true;
+            initial = initial.substring(1, initial.length);
+            initial = thymol.ThUtils.unParenthesise(initial);
+        }
+        val = thymol.getThAttribute(initial, element);
+        if (val == null) {
+            args = initial.match(varExpr);
+            if (args) {
+                if (args[1].charAt(0) == "!") {
+                    negate = !negate;
+                }
+            }
+        }
+        flag = thymol.getBooleanValue(val);
+        if (negate) {
+            flag = !flag;
+        }
+        return flag;
+    };
+    thymol.appendToAttrList = function(func, prec, attrArray) {
+        var j, jLimit = attrArray.length, tha = null;
+        for (j = 0; j < jLimit; j++) {
+            tha = new thymol.ThAttr(attrArray[j], func, prec, thymol.thThymeleafPrefixList, thymol.prefix);
+        }
+        j = tha;
+    };
+    thymol.setupAttrList = function() {
+        thCase = new thymol.ThAttr("case", null, 275, thymol.thThymeleafPrefixList, thymol.prefix);
+        thymol.addDialect({
+            prefix: thymol.prefix,
+            attributeProcessors: [ {
+                name: "each",
+                processor: thymol.processEach,
+                precedence: 200
+            }, {
+                name: "switch",
+                processor: thymol.processSwitch,
+                precedence: 250
+            }, {
+                name: "if",
+                processor: thymol.processConditional,
+                precedence: 300
+            }, {
+                name: "unless",
+                processor: thymol.processConditional,
+                precedence: 400
+            }, {
+                name: "object",
+                processor: thymol.processObject,
+                precedence: 500
+            }, {
+                name: "with",
+                processor: thymol.processWith,
+                precedence: 600
+            }, {
+                name: "attr",
+                processor: thymol.processAttr,
+                precedence: 700
+            }, {
+                name: "attrprepend",
+                processor: thymol.processAttr,
+                precedence: 800
+            }, {
+                name: "attrappend",
+                processor: thymol.processAttr,
+                precedence: 900
+            }, {
+                name: "alt-title",
+                processor: thymol.processPairedAttr,
+                precedence: 990
+            }, {
+                name: "lang-xmllang",
+                processor: thymol.processPairedAttr,
+                precedence: 990
+            }, {
+                name: "inline",
+                processor: thymol.processInline,
+                precedence: 1e3
+            }, {
+                name: "classappend",
+                processor: thymol.processCSSAttr,
+                precedence: 1100
+            }, {
+                name: "styleappend",
+                processor: thymol.processCSSAttr,
+                precedence: 1100
+            }, {
+                name: "text",
+                processor: thymol.processText,
+                precedence: 1300
+            }, {
+                name: "utext",
+                processor: thymol.processText,
+                precedence: 1400
+            }, {
+                name: "fragment",
+                processor: thymol.processFragment,
+                precedence: 1500
+            }, {
+                name: "assert",
+                processor: thymol.processAssert,
+                precedence: 1550
+            }, {
+                name: "remove",
+                processor: thymol.processRemove,
+                precedence: 1600
+            } ]
+        });
+        thymol.appendToAttrList(thymol.processSpecAttrMod, 1e3, specAttrModList);
+        thymol.appendToAttrList(thymol.processSpecAttrMod, 1e3, eventAttrList);
+        thymol.appendToAttrList(thymol.processFixedValBoolAttr, 1e3, fixedValBoolAttrList);
+    };
+})();
+
+thymol.objects.thHttpSessionObject = function() {
+    var thExpressionObjectName = "#httpSession";
+    function getAttribute(name) {
+        var result = thymol.sessionContext[name];
+        return result;
+    }
+    function getParameter(name) {
+        var result = thymol.sessionContext[name];
+        return result;
+    }
+    function getServletContext() {
+        var result = thymol.applicationContext;
+        return result;
+    }
+    function getSessionContext() {
+        var result = thymol.sessionContext;
+        return result;
+    }
+    function getContextPath() {
+        var result = "";
+        return result;
+    }
+    function getRequestName() {
+        var result = "";
+        return result;
+    }
+    function getParameterValues(name) {
+        var result = thymol.sessionContext[name];
+        return result;
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        getAttribute: getAttribute,
+        getParameter: getParameter,
+        getServletContext: getServletContext,
+        getSessionContext: getSessionContext,
+        getContextPath: getContextPath,
+        getRequestName: getRequestName,
+        getParameterValues: getParameterValues
+    };
+}();
+
+thymol.objects.thHttpServletRequestObject = function() {
+    var thExpressionObjectName = "#httpServletRequest";
+    function getAttribute(name) {
+        var result = thymol.requestContext[name][0];
+        if (result instanceof thymol.ThParam) {
+            result = thymol.ThUtils.unQuote(result.value);
+        }
+        return result;
+    }
+    function getParameter(name) {
+        var result = thymol.requestContext[name];
+        return result;
+    }
+    function getContextPath() {
+        var result = "";
+        return result;
+    }
+    function getRequestName() {
+        var result = "";
+        return result;
+    }
+    function getParameterValues(name) {
+        var result = thymol.requestContext[name];
+        return result;
+    }
+    function getSession(create) {
+        return thymol.objects.thHttpSessionObject;
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        getAttribute: getAttribute,
+        getParameter: getParameter,
+        getContextPath: getContextPath,
+        getRequestName: getRequestName,
+        getParameterValues: getParameterValues,
+        getSession: getSession
+    };
+}();
+
+(function() {
+    var DOMParser_proto = thymol.thDomParser.prototype, real_parseFromString = DOMParser_proto.parseFromString;
+    try {
+        if (new thymol.thDomParser().parseFromString("", "text/html")) {
+            return;
+        }
+    } catch (ignore) {}
+    DOMParser_proto.parseFromString = function(markup, type) {
+        var res, doc;
+        if (/^\s*text\/html\s*(?:;|$)/i.test(type)) {
+            doc = thymol.thDocument.implementation.createHTMLDocument("");
+            if (markup.toLowerCase().indexOf("<!doctype") > -1) {
+                doc.documentElement.innerHTML = markup;
+            } else {
+                doc.body.innerHTML = markup;
+            }
+            res = doc;
+        } else {
+            res = real_parseFromString.apply(this, arguments);
+        }
+        return res;
+    };
+})();
+
+if (!Array.indexOf) {
+    Array.prototype.indexOf = function(obj, start) {
+        for (var i = start || 0; i < this.length; i++) {
+            if (this[i] === obj) {
+                return i;
+            }
+        }
+        return -1;
+    };
+}
+
+$(function() {
+    thymol.jqSetup($);
+    thymol.execute(document);
+});
+
+$(window).unload(function() {
+    if (thymol.sessionContext && thymol.sessionContext.persist) {
+        thymol.sessionContext.persist();
+    }
+});
\ No newline at end of file
diff --git a/dist/js/thymol-load.js b/dist/js/thymol-load.js
new file mode 100644 (file)
index 0000000..a82492b
--- /dev/null
@@ -0,0 +1,3 @@
+var thProtocol = "";
+var thRelativeRootPath = "..";
+var thPath="";
diff --git a/dist/js/thymol-node.js b/dist/js/thymol-node.js
new file mode 100644 (file)
index 0000000..b129c32
--- /dev/null
@@ -0,0 +1,8265 @@
+/*-------------------- Thymol - the flavour of Thymeleaf --------------------*
+
+   Thymol version 2.0.0 Copyright (C) 2012-2015 James J. Benson
+   jjbenson .AT. users.sf.net (http://www.thymoljs.org/)
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" basis,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ *---------------------------------------------------------------------------*/
+
+thymol = function() {
+    thymol.thVersion = "2.0.0";
+    thymol.thReleaseDate = "2015-03-31";
+    thymol.thURL = "http://www.thymoljs.org";
+    thymol.thAltURL = "http://www.thymeleaf.org";
+    thymol.thUsingNullPrefix = false;
+    thymol.thThymeleafPrefixList = [];
+    thymol.thThymeleafElementsList = [];
+    thymol.objects = {};
+    var textFuncSynonym = "~~~~", varRefExpr = /([$#]{.*?})/, literalTokenExpr = /^[a-zA-Z0-9\[\]\.\-_]*$/, startParserLevelCommentExpr = /^\s*\/\*\s*$/, endParserLevelCommentExpr = /^\s*\*\/\s*$/, startParserLevelCommentExpr2 = /^\/\*[^\/].*/, endParserLevelCommentExpr2 = /.*[^\/]\*\/$/, prototypeOnlyCommentEscpExpr = /\/\*\/(.*)\/\*\//, varExpr3 = /[\$\*#@]{1}\{(.*)\}$/, nonURLExpr = /[\$\*#]{1}\{(?:!?[^}]*)\}/, numericExpr = /^[+\-]?[0-9]*?[.]?[0-9]*?$/, varParExpr = /([^(]*)\s*[(]([^)]*?)[)]/, domSelectExpr = /([\/]{1,2})?([A-Za-z0-9_\-]*(?:[\(][\)])?)?([^\[]\S[A-Za-z0-9_\-]*(?:[\(][\)])?[\/]*(?:[\.\/#]?[^\[]\S[A-Za-z0-9_\-]*(?:[\(][\)])?[\/]*)*)?([\[][^\]]*?[\]])?/, litSubstExpr = /\.*?([\|][^\|]*?[\|])\.*?/;
+    function Thymol() {}
+    function isClientSide() {
+        if (typeof thymol.isServerSide !== "undefined" && !!thymol.isServerSide()) {
+            thymol.isClientSide = function() {
+                return false;
+            };
+            return false;
+        }
+        thymol.isClientSide = function() {
+            return true;
+        };
+        return true;
+    }
+    function execute(doc) {
+        if (typeof thymol.protocol === "undefined") {
+            thymol.protocol = "";
+        }
+        if (typeof thymol.root === "undefined") {
+            thymol.root = "";
+        }
+        if (typeof thymol.path === "undefined") {
+            thymol.path = "";
+        }
+        thymol.thDocument = doc;
+        var theWindow = thymol.thWindow;
+        if (typeof thymol.thWindow === "undefined") {
+            if (typeof doc.defaultView !== "undefined") {
+                theWindow = doc.defaultView;
+            } else if (typeof doc.parentWindow !== "undefined") {
+                theWindow = doc.parentWindow;
+            }
+        }
+        thymol.thWindow = theWindow;
+        var theTop = thymol.thTop;
+        if (typeof thymol.thTop === "undefined") {
+            if (typeof top !== "undefined") {
+                theTop = top;
+            }
+        }
+        thymol.thTop = theTop;
+        thymol.init();
+        var base = new ThNode(thymol.thDocument, false, null, null, null, thymol.thDocument.nodeName, "::", false, thymol.thDocument);
+        Thymol.prototype.process(base);
+        postExecute();
+        return thymol.thDocument;
+    }
+    function jqSetup(jq) {
+        jq.fn.extend({
+            getComments: function() {
+                return this.filter(function() {
+                    return this.nodeType === 8;
+                });
+            },
+            getThDecorated: function(thInst) {
+                var i, iAttrName, iLength, j, jLength, instances = [], result = null, expanded = false;
+                if (thInst.escpName !== null) {
+                    instances = this.filter(thInst.escpName);
+                }
+                if (thInst.escpSynonym !== null) {
+                    instances = instances.add(this.filter(thInst.escpSynonym));
+                }
+                for (i = 0, iLength = instances.length; i < iLength; i++) {
+                    if (instances[i]) {
+                        for (j = 0, jLength = instances[i].attributes.length; j < jLength; j++) {
+                            if (instances[i].attributes[j]) {
+                                iAttrName = instances[i].attributes[j].name;
+                                if (iAttrName && (thInst.name == iAttrName || thInst.synonym == iAttrName)) {
+                                    expanded = thymol.ThUtils.processElement(thInst.process, instances[i], instances[i].attributes[j], thInst);
+                                    if (expanded) {
+                                        if (result === null) {
+                                            result = [];
+                                        }
+                                        result.push(instances[i]);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                return result;
+            }
+        });
+    }
+    function ready(func) {
+        if (typeof thymolDeferredFunctions === "undefined" || thymolDeferredFunctions === null) {
+            thymolDeferredFunctions = [];
+        }
+        thymolDeferredFunctions.push(func);
+    }
+    function setupEnv() {
+        thymol.prefix = Thymol.prototype.getThParam("thPrefix", false, false, thymol.thDefaultPrefix);
+        thymol.dataPrefix = Thymol.prototype.getThParam("thDataPrefix", false, false, thymol.thDefaultDataPrefix);
+        thymol.messagePath = Thymol.prototype.getThParam("thMessagePath", false, true, thymol.thDefaultMessagePath);
+        thymol.resourcePath = Thymol.prototype.getThParam("thResourcePath", false, true, thymol.thDefaultResourcePath);
+        thymol.messagesBaseName = Thymol.prototype.getThParam("thMessagesBaseName", false, false, thymol.thDefaultMessagesBaseName);
+        thymol.relativeRootPath = Thymol.prototype.getThParam("thRelativeRootPath", false, true, thymol.thDefaultRelativeRootPath);
+        thymol.extendedMapping = Thymol.prototype.getThParam("thExtendedMapping", true, false, thymol.thDefaultExtendedMapping);
+        thymol.localMessages = Thymol.prototype.getThParam("thLocalMessages", true, false, thymol.thDefaultLocalMessages);
+        thymol.disableMessages = Thymol.prototype.getThParam("thDisableMessages", true, false, thymol.thDefaultDisableMessages);
+        thymol.templateSuffix = Thymol.prototype.getThParam("thTemplateSuffix", false, false, thymol.thDefaultTemplateSuffix);
+        thymol.scriptPath = "";
+        if (typeof thymol.thScriptPath !== "undefined") {
+            thymol.scriptPath = Thymol.prototype.getThParam("thScriptPath", false, true, thymol.thScriptPath);
+        }
+        thymol.absolutePath = "";
+        if (typeof thymol.thAbsolutePath !== "undefined") {
+            thymol.absolutePath = Thymol.prototype.getThParam("thAbsolutePath", false, true, thymol.thAbsolutePath);
+        }
+        thymol.useAbsolutePath = false;
+        if (typeof thymol.thUseAbsolutePath !== "undefined") {
+            thymol.useAbsolutePath = Thymol.prototype.getThParam("thUseAbsolutePath", true, false, thymol.thUseAbsolutePath);
+        }
+        thymol.useFullURLPath = true;
+        if (typeof thymol.thUseFullURLPath !== "undefined") {
+            thymol.useFullURLPath = Thymol.prototype.getThParam("thUseFullURLPath", true, false, thymol.thUseFullURLPath);
+        }
+        thymol.indexFile = Thymol.prototype.getThParam("thIndexFile", false, false, null);
+        thymol.debug = Thymol.prototype.getThParam("thDebug", true, false, false);
+        thymol.allowNullText = Thymol.prototype.getThParam("thAllowNullText", true, false, true);
+        thymol.location = thymol.thLocation;
+        if ("" !== thymol.relativeRootPath) {
+            thymol.root = thymol.location + thymol.relativeRootPath;
+            thymol.messagePath = thymol.root + thymol.messagePath;
+        } else {
+            if (typeof thymol.thMessagePath !== "undefined") {
+                thymol.messagePath = Thymol.prototype.getThParam("thMessagePath", false, true, thymol.thMessagePath);
+            }
+            if (typeof thymol.thRoot !== "undefined") {
+                thymol.root = Thymol.prototype.getThParam("thRoot", false, true, thymol.thRoot);
+            }
+        }
+        thymol.root = Thymol.prototype.getThParam("thRoot", false, true, thymol.root);
+        if (typeof thymol.thPath !== "undefined") {
+            thymol.path = Thymol.prototype.getThParam("thPath", false, true, thymol.thPath);
+        }
+        thymol.path = Thymol.prototype.getThParam("thPath", false, true, thymol.path);
+        thymol.protocol = thymol.thDocument.location.protocol;
+        if ("" == thymol.protocol) {
+            thymol.protocol = thymol.thDefaultProtocol;
+        } else {
+            thymol.protocol += "//";
+            if ("" == thymol.thDocument.location.host) {
+                thymol.protocol += "/";
+            }
+        }
+        thymol.protocol = Thymol.prototype.getThParam("thProtocol", false, false, thymol.protocol);
+        thymol.resourcePath = Thymol.prototype.getThParam("thResourcePath", false, true, thymol.resourcePath);
+    }
+    function updatePrefix(pref) {
+        thymol.prefix = pref;
+        thymol.thThymeleafPrefixList = [];
+        thymol.thThymeleafElementsList = [];
+    }
+    function init() {
+        this.messages = null;
+        this.mappings = null;
+        this.debug = null;
+        getLocations(this);
+        this.locale = new thymol.ThObject();
+        getLanguage();
+        var accessor = undefined, i, iLimit, j, jLimit;
+        if (typeof thVars !== "undefined") {
+            accessor = new thymol.ThVarsAccessor(thVars, "thVars");
+        }
+        this.applicationContext = thymol.makeContext("application", accessor);
+        this.sessionContext = thymol.makeContext("session", undefined);
+        this.sessionContext.persist = function() {
+            var save = this.serialise();
+            thymol.thTop.name = save;
+        };
+        this.requestContext = thymol.makeContext("request", undefined);
+        this.booleanAndNullTokens = new Array();
+        this.booleanAndNullTokens["null"] = this.applicationContext.createVariable("null", null);
+        this.booleanAndNullTokens["true"] = this.applicationContext.createVariable("true", true);
+        this.booleanAndNullTokens["false"] = this.applicationContext.createVariable("false", false);
+        this.allowNullText = null;
+        setupEnv();
+        this.thCache = {};
+        this.thExpressionObjects;
+        this.thDeferredFunctions;
+        this.thPreExecutionFunctions;
+        this.thPostExecutionFunctions;
+        if (typeof this.thExpressionObjects === "undefined" || this.thExpressionObjects === null) {
+            this.thExpressionObjects = {};
+        }
+        this.thExpressionObjects["#object"] = {};
+        this.thExpressionObjects["#locale"] = {};
+        this.thExpressionObjects["#ctx"] = [];
+        this.thExpressionObjects["#ctx"]["variables"] = {};
+        thymol.configureModule(thymol.objects.thHttpServletRequestObject);
+        thymol.configureModule(thymol.objects.thHttpSessionObject);
+        if (typeof thymol.thObjectsConfigureModules !== "undefined") {
+            thymol.thObjectsConfigureModules();
+        }
+        var scripts = thymol.thDocument.getElementsByTagName("script");
+        for (var i = 0, iLimit = scripts.length; i < iLimit; i++) {
+            var parameters = scripts[i].getAttribute("data-thymol-load");
+            if (!!parameters) {
+                var splits = parameters.split(",");
+                for (var j = 0, jLimit = splits.length; j < jLimit; j++) {
+                    thymol.ThUtils.loadScript(splits[j]);
+                }
+            }
+        }
+        setupEnv();
+        if (typeof thymol.thPreExecutionFunctions === "undefined" || thymol.thPreExecutionFunctions === null) {
+            thymol.thPreExecutionFunctions = [];
+        }
+        if (typeof thymol.thPostExecutionFunctions === "undefined" || thymol.thPostExecutionFunctions === null) {
+            thymol.thPostExecutionFunctions = [];
+        }
+        $.ajaxSetup({
+            async: false,
+            isLocal: true,
+            dataType: "text"
+        });
+        if (!(typeof thVars === "undefined")) {
+            for (i = 0, iLimit = thVars.length; i < iLimit; i++) {
+                this.applicationContext.createVariable(thVars[i][0], thVars[i][1]);
+            }
+        }
+        executeDeferred();
+        (function() {
+            var htmlTagAttrs = $("html")[0].attributes, tp = null, tu, nsspec;
+            $([ thymol.thURL, thymol.thAltURL ]).each(function() {
+                tu = this;
+                $(htmlTagAttrs).each(function() {
+                    if (this.value == tu) {
+                        nsspec = this.localName.split(":");
+                        if (nsspec.length > 0) {
+                            tp = nsspec[nsspec.length - 1];
+                            return false;
+                        }
+                    }
+                });
+                if (tp) {
+                    thymol.updatePrefix(tp);
+                    return false;
+                }
+            });
+        })();
+        var defaultScriptUrl = "";
+        if (!!thymol.thRequest) {
+            thymol.thWindow.location.search = thymol.thRequest;
+        }
+        (function(app, req) {
+            var e, f, a = /\+/g, r = /([^&=]+)=?([^&]*)/g, d = function(s) {
+                return decodeURIComponent(s.replace(a, " "));
+            }, q = thymol.thWindow.location.search.substring(1), surl, scriptUrl = defaultScriptUrl;
+            $("script").each(function() {
+                surl = this.src;
+                if (surl.indexOf(thymol.thScriptName) >= 0) {
+                    scriptUrl = d(surl);
+                    return false;
+                }
+            });
+            while (e = r.exec(scriptUrl)) {
+                f = e[1].split("?");
+                switch (f[1]) {
+                  case "thPrefix":
+                    thymol.prefix = e[2];
+                    break;
+
+                  case "thDataPrefix":
+                    thymol.dataPrefix = e[2];
+                    break;
+
+                  case "thMessagePath":
+                    thymol.messagePath = e[2];
+                    break;
+
+                  case "thResourcePath":
+                    thymol.resourcePath = e[2];
+                    break;
+
+                  case "thMessagesBaseName":
+                    thymol.messagesBaseName = e[2];
+                    break;
+
+                  case "thRelativeRootPath":
+                    thymol.relativeRootPath = e[2];
+                    break;
+
+                  case "thExtendedMapping":
+                    thymol.extendedMapping = e[2];
+                    break;
+
+                  case "thTemplateSuffix":
+                    thymol.templateSuffix = e[2];
+                    break;
+
+                  case "thLocalMessages":
+                    thymol.localMessages = e[2];
+                    break;
+
+                  case "thDisableMessages":
+                    thymol.disableMessages = e[2];
+                    break;
+
+                  case "thIndexFile":
+                    thymol.indexFile = e[2];
+                    break;
+
+                  case "thProtocol":
+                    thymol.protocol = e[2];
+                    break;
+
+                  case "thDebug":
+                    thymol.debug = e[2];
+                    break;
+
+                  case "thRoot":
+                    thymol.root = e[2];
+                    break;
+
+                  case "thPath":
+                    thymol.path = e[2];
+                    break;
+
+                  case "thAllowNullText":
+                    thymol.allowNullText = e[2];
+                    break;
+
+                  case "thLocale":
+                    thymol.locale.value = e[2];
+                    break;
+
+                  case "thDefaultPrecision":
+                    thymol.thDefaultPrecision = e[2];
+                    break;
+
+                  case "thDefaultPrecedence":
+                    thymol.thDefaultPrecedence = e[2];
+                    break;
+
+                  default:
+                    app.createVariable(e[1], e[2]);
+                }
+            }
+            while (e = r.exec(q)) {
+                req.createVariable(d(e[1]), e[2], true);
+            }
+        })(this.applicationContext, this.requestContext);
+        thymol.thInclude = new thymol.ThAttr("include", null, 100, null, thymol.prefix);
+        thymol.thReplace = new thymol.ThAttr("replace", null, 100, null, thymol.prefix);
+        thymol.thSubstituteby = new thymol.ThAttr("substituteby", null, 100, null, thymol.prefix);
+        thymol.thFragment = new thymol.ThAttr("fragment", null, 2e4, null, thymol.prefix);
+        thymol.thRemove = null;
+        thymol.thBlock = new thymol.ThElement("block", function(element) {
+            var i, limit = element.childNodes.length;
+            for (i = 0; i < limit; i++) {
+                if (element.childNodes[i].nodeType === 1) {
+                    element.childNodes[i].isBlockChild = true;
+                }
+            }
+        }, thymol.prefix);
+        this.applicationContext.resolveJSONReferences();
+        thymol.setupAttrList();
+        preExecute(this.applicationContext);
+        this.thExpressionObjects["#vars"] = this.applicationContext;
+        this.thExpressionObjects["#root"] = this.applicationContext;
+        this.sessionContext.init();
+        this.sessionContext.resolveJSONReferences();
+        this.requestContext.resolveJSONReferences();
+        this.thExpressionObjects["#ctx"]["variables"] = this.applicationContext;
+        this.thExpressionObjects["#ctx"]["requestParameters"] = this.requestContext;
+        this.thExpressionObjects["#ctx"]["servletContext"] = this.applicationContext;
+        this.thExpressionObjects["#ctx"]["httpServletRequest"] = this.thExpressionObjects["#httpServletRequest"];
+        this.thExpressionObjects["#ctx"]["httpSession"] = this.thExpressionObjects["#httpSession"];
+        this.protocol = Thymol.prototype.override("thProtocol", this.protocol);
+        this.debug = Thymol.prototype.override("thDebug", this.debug);
+        this.root = Thymol.prototype.override("thRoot", this.root);
+        if ("" !== this.relativeRootPath) {
+            var rootURI = thymol.thDocument.location.href;
+            var quePos = rootURI.indexOf("?");
+            if (quePos >= 0) {
+                rootURI = rootURI.substring(0, quePos);
+            }
+            var sepPos = rootURI.lastIndexOf("/");
+            if (sepPos >= 0) {
+                rootURI = rootURI.substring(0, sepPos + 1);
+            }
+            var newThRoot = rootURI + this.thLocation + this.relativeRootPath;
+            this.thRoot = Thymol.prototype.getThParam("thRoot", false, true, newThRoot);
+        }
+        this.path = Thymol.prototype.override("thPath", this.path);
+        this.allowNullText = Thymol.prototype.override("thAllowNullText", this.allowNullText);
+        this.locale.value = Thymol.prototype.override("thLocale", this.locale.value);
+        if (!(typeof thMappings === "undefined")) {
+            this.mappings = [];
+            for (j = 0, jLimit = thMappings.length; j < jLimit; j++) {
+                this.mappings.push([ thMappings[j][0], thMappings[j][1] ]);
+            }
+            this.mappings.sort(function(a, b) {
+                return a[0].length > b[0].length ? -1 : 1;
+            });
+        }
+        this.messages = {};
+        setLocaleValue();
+        if (!(typeof thMessages === "undefined")) {
+            this.messages[""] = [];
+            for (j = 0, jLimit = thMessages.length; j < jLimit; j++) {
+                this.messages[""][thMessages[j][0]] = thMessages[j][1];
+            }
+            for (var k in thMessages) {
+                if (thMessages.hasOwnProperty(k)) {
+                    if (!k.match(numericExpr)) {
+                        this.messages[k] = [];
+                        for (j = 0, jLimit = thMessages[k].length; j < jLimit; j++) {
+                            this.messages[k][thMessages[k][j][0]] = thMessages[k][j][1];
+                        }
+                    }
+                }
+            }
+        }
+        if (!(typeof thDisable === "undefined")) {
+            for (j = 0, jLimit = thDisable.length; j < jLimit; j++) {
+                Thymol.prototype.doDisable(thDisable[j]);
+            }
+        }
+        thymol.thRemove = Thymol.prototype.getThAttrByName("remove");
+    }
+    function getLocations(thiz) {
+        thiz.templateName = "";
+        thiz.templatePath = "";
+        if (!!thymol.thDocument.location.href) {
+            var templateName = templatePath = thymol.thDocument.location.href;
+            thiz.templateName = templateName.substring(0, templateName.indexOf(".") == -1 ? templateName.length : templateName.lastIndexOf("."));
+            thiz.templatePath = templatePath.substring(0, templatePath.indexOf("/") == -1 ? 0 : templatePath.lastIndexOf("/") + 1);
+        }
+    }
+    function getCtx() {
+        return thymol.thExpressionObjects["#ctx"];
+    }
+    function configureModule(module) {
+        if (typeof thymol.thExpressionObjects === "undefined" || thymol.thExpressionObjects === null) {
+            thymol.thExpressionObjects = {};
+        }
+        thymol.thExpressionObjects[module.thExpressionObjectName] = module;
+    }
+    function configureAttributeProcessor(prefix, suffix, func, prec, dataAttr) {
+        var p = prefix + ":";
+        if (p !== null) {
+            if (thymol.thThymeleafPrefixList.indexOf(p) < 0) {
+                thymol.thThymeleafPrefixList.push(p);
+            }
+        } else {
+            thymol.thUsingNullPrefix = true;
+        }
+        p = new thymol.ThAttr(suffix, func, prec, thymol.thThymeleafPrefixList, prefix, dataAttr);
+    }
+    function configureElementProcessor(prefix, suffix, func) {
+        var p = new thymol.ThElement(suffix, func, prefix);
+    }
+    function configurePreExecution(func) {
+        if (typeof thymol.thPreExecutionFunctions === "undefined" || thymol.thPreExecutionFunctions === null) {
+            thymol.thPreExecutionFunctions = [];
+        }
+        thymol.thPreExecutionFunctions.push(func);
+    }
+    function configurePostExecution(func) {
+        if (typeof thymol.thPostExecutionFunctions === "undefined" || thymol.thPostExecutionFunctions === null) {
+            thymol.thPostExecutionFunctions = [];
+        }
+        thymol.thPostExecutionFunctions.push(func);
+    }
+    function executeDeferred() {
+        if (typeof thymolDeferredFunctions !== "undefined" && thymolDeferredFunctions !== null) {
+            while (thymolDeferredFunctions.length > 0) {
+                var func = thymolDeferredFunctions.pop();
+                func();
+            }
+        }
+    }
+    function preExecute(context) {
+        while (thymol.thPreExecutionFunctions.length > 0) {
+            var func = thymol.thPreExecutionFunctions.pop();
+            func();
+            context.resolveJSONReferences();
+        }
+    }
+    function postExecute() {
+        while (thymol.thPostExecutionFunctions.length > 0) {
+            var func = thymol.thPostExecutionFunctions.pop();
+            func();
+        }
+    }
+    function preProcess(expr, element) {
+        var result = expr, fp, lp;
+        do {
+            fp = result.indexOf("__");
+            if (fp >= 0) {
+                lp = -1;
+                if (result.length > 4) {
+                    lp = result.lastIndexOf("__");
+                }
+                if (lp <= 0) {
+                    throw new thymol.ThError("Mismatched pre-processing indicators", element);
+                }
+                var head = result.substring(0, fp);
+                var centre = result.substring(fp + 2, lp);
+                centre = this.getParsedExpr(centre, element);
+                var tail = result.substring(lp + 2);
+                result = head + centre + tail;
+                fp = result.indexOf("__");
+            }
+        } while (fp >= 0);
+        result = result.replace(/\\_\\_/g, "__");
+        return result;
+    }
+    function substituteParam(argValue, mode, element) {
+        var result = argValue, varName = argValue, subs = null, msg, expo;
+        if (result) {
+            if (mode === 4) {
+                msg = thymol.getMessage(varName);
+                if (msg) {
+                    subs = msg;
+                }
+            } else if (mode === 6) {
+                subs = argValue;
+            } else {
+                var token = thymol.booleanAndNullTokens[result];
+                if (!(typeof token === "undefined")) {
+                    if (token === null) {
+                        subs = null;
+                    } else {
+                        subs = token.value;
+                    }
+                } else {
+                    if (varName.charAt(0) === "#") {
+                        if ("#object" === varName) {
+                            if (element.thObjectVar) {
+                                subs = element.thObjectVar;
+                            }
+                        } else {
+                            expo = thymol.thExpressionObjects[varName];
+                            if (typeof expo !== "undefined" && expo !== null) {
+                                subs = expo;
+                            }
+                        }
+                    }
+                    if ((typeof subs === "undefined" || subs == null) && element.thObjectVar) {
+                        subs = element.thObjectVar[varName];
+                    }
+                    if ((typeof subs === "undefined" || subs == null) && element.thLocalVars) {
+                        subs = element.thLocalVars[varName];
+                    }
+                    if (typeof subs === "undefined" || subs == null) {
+                        subs = thymol.ThUtils.getParameter(varName);
+                    }
+                    if (typeof subs === "undefined" || subs == null) {
+                        if ("param" === varName) {
+                            subs = thymol.requestContext;
+                        }
+                        if ("session" === varName) {
+                            subs = thymol.sessionContext;
+                        }
+                        if ("application" === varName) {
+                            subs = thymol.applicationContext;
+                        }
+                    }
+                    if (mode === 2 && (typeof subs === "undefined" || subs == null)) {
+                        subs = argValue;
+                    }
+                }
+            }
+            result = subs;
+            if (subs instanceof thymol.ThParam) {
+                result = subs.value;
+            }
+        }
+        return result;
+    }
+    function getStandardURL(initial) {
+        var result = initial.trim(), mapped, head;
+        mapped = thymol.getMapped(result, thymol.extendedMapping);
+        if (mapped) {
+            result = mapped;
+        }
+        if ("/" === result && !!thymol.indexFile) {
+            result += thymol.indexFile;
+        }
+        if (!/.*:\/\/.*/.test(result)) {
+            if (/^~?\/.*$/.test(result)) {
+                if (/^~.*$/.test(result)) {
+                    result = result.substring(1);
+                }
+                if (!/^\/\/.*$/.test(result)) {
+                    if (thymol.useFullURLPath) {
+                        head = thymol.root + thymol.resourcePath;
+                        if (head != "") {
+                            if (head.charAt(head.length - 1) !== "/") {
+                                head = head + "/";
+                            }
+                            if (result.charAt(0) === "/") {
+                                result = head + result.substring(1);
+                            } else {
+                                result = head + result;
+                            }
+                        }
+                    } else {
+                        result = thymol.resourcePath + result;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    function getExpression(argValue, element) {
+        var result = argValue, subst = false, initial, shortCut, args, negate, token, lsp;
+        if (typeof argValue === "string") {
+            initial = argValue.trim();
+            result = initial;
+            if (result) {
+                shortCut = thymol.ThUtils.getParameter(result);
+                if (!shortCut) {
+                    args = result.match(varExpr3);
+                    if (args) {
+                        if (args[1] && args[1].length > 0) {
+                            shortCut = thymol.ThUtils.getParameter(args[1]);
+                        }
+                    }
+                }
+                if (shortCut) {
+                    if (shortCut instanceof thymol.ThParam) {
+                        result = shortCut.value;
+                    } else {
+                        result = shortCut;
+                    }
+                    if (typeof result === "string" && result.match(numericExpr)) {
+                        result = parseInt(result);
+                    }
+                } else {
+                    initial = thymol.ThUtils.unParenthesise(result);
+                    negate = false;
+                    if (initial.charAt(0) == "!") {
+                        negate = true;
+                        initial = initial.substring(1, initial.length);
+                        initial = thymol.ThUtils.unParenthesise(initial);
+                    }
+                    if (literalTokenExpr.test(initial)) {
+                        token = thymol.booleanAndNullTokens[initial];
+                        if (!(typeof token === "undefined")) {
+                            result = token.value;
+                            subst = true;
+                        }
+                    }
+                    lsp = null;
+                    if (!subst) {
+                        lsp = initial.match(litSubstExpr);
+                        if (lsp && lsp.length > 0) {
+                            if (thymol.ThUtils.charOcurrences(lsp[1], "'") < 2) {
+                                initial = Thymol.prototype.doLiteralSubstExpr(initial, lsp[1]);
+                            }
+                        }
+                        result = "";
+                        if (initial != "") {
+                            initial = thymol.ThUtils.unParenthesise(initial);
+                            initial = thymol.preProcess(initial, element);
+                            result = thymol.getParsedExpr(initial, element, true);
+                        }
+                    }
+                    if (result == initial && typeof result == typeof initial) {
+                        result = null;
+                    } else if (typeof result === "string") {
+                        if (!lsp) {
+                            result = result.replace(/[\\][\\]/g, "\\");
+                        }
+                        result = result.replace(/&#39;/g, "'").replace(/&apos;/gi, "'");
+                    }
+                    if (negate) {
+                        if (typeof result === "boolean") {
+                            result = !result;
+                        } else if (typeof result === "number") {
+                            result = result == 0;
+                        } else if (typeof result === "string") {
+                            result = !thymol.ThUtils.testLiteralFalse(result);
+                        }
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    function getMapped(uri, extended) {
+        var mapped = null, i, iLimit, key;
+        if (uri && typeof uri === "string") {
+            if (thymol.mappings) {
+                for (i = 0, iLimit = thymol.mappings.length; i < iLimit; i++) {
+                    key = thymol.mappings[i][0];
+                    if (uri == key) {
+                        mapped = thymol.mappings[i][1];
+                        break;
+                    } else if (extended) {
+                        if (uri.indexOf(key) == 0) {
+                            mapped = uri.substring(key.length);
+                            mapped = thymol.mappings[i][1] + mapped;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        return mapped;
+    }
+    function substitute(initial, element, lenient) {
+        var argValue = initial, result, args, token, re, subs, saved;
+        if (typeof argValue === "string") {
+            argValue = argValue.trim();
+        }
+        result = argValue;
+        args = "";
+        while (args != null) {
+            args = argValue.match(/.*([$\*#@]{(!?[^}]*)}).*/);
+            if (args != null && args.length > 0) {
+                if (args.length == 3) {
+                    token = args[1];
+                    token = token.replace(/[$]/g, "[$]").replace(/[*]/g, "[*]").replace(/[\']/g, "[']").replace(/[+]/g, "[+]").replace(/[\(]/g, "[(]").replace(/[\)]/g, "[)]");
+                    re = new RegExp(token);
+                    subs = this.getExpression(args[2], element);
+                    if (subs != args[2]) {
+                        result = result.replace(re, subs, "g");
+                        if (result == "null") {
+                            result = null;
+                        }
+                    } else {
+                        subs = "";
+                        if (thymol.debug && !lenient) {
+                            thymol.thWindow.alert('thymol variable substitution failed: "' + initial + '"');
+                        }
+                    }
+                    saved = argValue;
+                    argValue = argValue.replace(re, subs, "g");
+                    if (saved == argValue) {
+                        argValue = "";
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    function getWith(element, content) {
+        var argValue = content.trim(), argCount = 0;
+        if (argValue) {
+            do {
+                var argsExpr = thymol.ThParser.parse(argValue, true, false);
+                var identifier = argsExpr.tokens.shift();
+                if (identifier.type_ === 3) {
+                    var result = argsExpr.evaluate(element);
+                    var varName = identifier.index_;
+                    if (!!varName) {
+                        argCount++;
+                        if (!element.thLocalVars) {
+                            element.thLocalVars = {};
+                        }
+                        element.thLocalVars[varName] = result;
+                    }
+                    argValue = argValue.substring(argsExpr.position);
+                } else {
+                    break;
+                }
+            } while (argValue.length > 0);
+        }
+        return argCount;
+    }
+    function getParsedExpr(initial, element, preprocessed) {
+        var expr, result = initial;
+        expr = thymol.ThParser.parse(result, false, preprocessed);
+        expr = expr.simplify();
+        result = expr.evaluate(element);
+        if (typeof result === "number") {
+            result = thymol.ThUtils.getToPrecision(result, expr.precision);
+        }
+        return result;
+    }
+    function getBooleanValue(param) {
+        var flag = false, val, args;
+        if (param != null) {
+            if (typeof param === "boolean") {
+                flag = param;
+            } else if (typeof param === "number") {
+                flag = param != 0;
+            } else {
+                val = param;
+                if (Object.prototype.toString.call(val) === "[object Array]") {
+                    if (val.length === 1) {
+                        val = val[0];
+                    } else {
+                        val = true;
+                    }
+                }
+                if (typeof val === "boolean") {
+                    flag = val;
+                } else if (typeof val === "number") {
+                    flag = val != 0;
+                } else if (typeof val === "string") {
+                    args = val.match(nonURLExpr);
+                    if (args) {
+                        val = args[1];
+                        flag = this.testParam(val);
+                    } else {
+                        flag = !thymol.ThUtils.testLiteralFalse(val);
+                    }
+                } else if (val instanceof thymol.ThParam) {
+                    flag = val.getBooleanValue();
+                } else {
+                    flag = typeof val !== "undefined" && val !== null;
+                }
+            }
+        }
+        return flag;
+    }
+    function isFragmentChild(element) {
+        var result = false, parent = element.parentElement;
+        while (parent) {
+            if (parent.getAttribute(thymol.thFragment.name) || parent.getAttribute(thymol.thFragment.synonym)) {
+                result = true;
+                break;
+            }
+            parent = parent.parentElement;
+        }
+        return result;
+    }
+    function setLocale(locValue) {
+        thymol.locale.value = locValue;
+        setLocaleValue();
+    }
+    function getLocale() {
+        return thymol.locale.value;
+    }
+    function getLanguage() {
+        if (!thymol.locale.value) {
+            if (typeof navigator !== "undefined" && !!navigator) {
+                var userLang = navigator.language || navigator.userLanguage || navigator.browserLanguage || navigator.systemLanguage;
+                if (!!userLang) {
+                    thymol.locale.value = userLang.replace(/\-/g, "_");
+                }
+            }
+        }
+    }
+    function setLocaleValue() {
+        if (!thymol.locale.value) {
+            thymol.locale.value = thymol.thDefaultLocale;
+        }
+        var sepPos;
+        var locale = thymol.locale.value.replace(/\-/g, "_");
+        var level = thymol.locale.value;
+        var levels = [];
+        var part, parts = [];
+        do {
+            levels.push(level);
+            sepPos = locale.lastIndexOf("_");
+            if (sepPos >= 0) {
+                part = locale.substring(sepPos + 1);
+                parts.push(part);
+                locale = locale.substring(0, sepPos);
+                level = level.substring(0, sepPos);
+            }
+        } while (sepPos >= 0);
+        thymol.locale.language = level;
+        if (!!parts) {
+            parts.reverse();
+            for (var i = 0, iLimit = parts.length; i < iLimit; i++) {
+                if (i === 0) {
+                    thymol.locale.country = parts[i];
+                } else if (i === 1) {
+                    thymol.locale.variant = parts[i];
+                }
+            }
+        }
+        thymol.locale.levels = levels;
+        thymol.thExpressionObjects["#ctx"]["locale"] = thymol.locale;
+        thymol.thExpressionObjects["#locale"] = thymol.locale;
+    }
+    function getMessage(varName, parameters, returnStringAlways) {
+        if (thymol.disableMessages) {
+            return undefined;
+        }
+        var msgKey = null;
+        var locale;
+        if (!!thymol.locale.levels) {
+            var prefix = "$";
+            var ident, section, jLower = thymol.localMessages ? 0 : 1;
+            for (var j = jLower; j < 2; j++) {
+                for (var i = 0, iLimit = thymol.locale.levels.length; i < iLimit + 1; i++) {
+                    ident = prefix;
+                    if (i < iLimit) {
+                        locale = thymol.locale.levels[i];
+                    } else {
+                        locale = "";
+                    }
+                    ident = ident + locale;
+                    section = thymol.messages[ident];
+                    if (!section) {
+                        if (j < 1) {
+                            section = getLocalMessages(locale);
+                        } else {
+                            section = getDefaultMessages(locale);
+                        }
+                    }
+                    if (!!section) {
+                        thymol.messages[ident] = section;
+                        msgKey = section[varName];
+                        if (!!msgKey) {
+                            break;
+                        }
+                    }
+                }
+                if (!!msgKey) {
+                    break;
+                }
+                prefix += "$";
+            }
+        }
+        if (!msgKey) {
+            for (var i = 0, iLimit = thymol.locale.levels.length; i <= iLimit; i++) {
+                if (i < iLimit) {
+                    locale = thymol.locale.levels[i];
+                } else {
+                    locale = "";
+                }
+                if (!!thymol.messages[locale]) {
+                    msgKey = thymol.messages[locale][varName];
+                    if (!!msgKey) {
+                        break;
+                    }
+                }
+            }
+        }
+        if (!!msgKey) {
+            if (typeof parameters === "undefined") {
+                return msgKey;
+            } else {
+                return thymol.ThUtils.renderMessage(msgKey, parameters);
+            }
+        } else if (returnStringAlways !== undefined && returnStringAlways) {
+            return "??" + varName + "_" + thymol.locale.value + "??";
+        }
+        return null;
+    }
+    function getProperties(propFile) {
+        var props = null;
+        var messages = [];
+        $.get(propFile, function(textContent, status) {
+            var err = null;
+            try {
+                if ("success" == status) {
+                    props = textContent;
+                } else if (thymol.debug) {
+                    thymol.thWindow.alert("read failed: " + propFile);
+                }
+            } catch (err) {
+                if (thymol.debug) {
+                    thymol.thWindow.alert("properties file read failed: " + propFile + " error: " + err);
+                }
+            }
+        }, "text");
+        if (props !== null) {
+            var splits = props.split("\n");
+            if (splits.length > 0) {
+                for (var i = 0, iLimit = splits.length; i < iLimit; i++) {
+                    var line = splits[i].trim();
+                    if (line.charAt(0) !== "#") {
+                        var p = line.split("=");
+                        if (p.length > 1) {
+                            messages[p[0].trim()] = thymol.ThUtils.unicodeUnescape(p[1].trim());
+                        }
+                    }
+                }
+            }
+        }
+        return messages;
+    }
+    function getLocalMessages(locale) {
+        var messages = [];
+        if (!!thymol.thDocument.location.href) {
+            var propsFile = thymol.templateName;
+            if (!!locale && locale !== "") {
+                propsFile += "_" + locale;
+            }
+            propsFile += ".properties";
+            messages = getProperties(propsFile);
+        }
+        return messages;
+    }
+    function getDefaultMessages(locale) {
+        var messages = null;
+        var propsPath = "";
+        if (thymol.useAbsolutePath) {
+            propsPath += thymol.protocol + thymol.root + thymol.path;
+        }
+        propsPath += thymol.messagePath;
+        if (propsPath !== "") {
+            propsPath += "/";
+        }
+        var propsFile = propsPath + thymol.messagesBaseName;
+        if (!!locale && locale !== "") {
+            propsFile += "_" + locale;
+        }
+        propsFile += ".properties";
+        messages = getProperties(propsFile);
+        return messages;
+    }
+    Thymol.prototype = {
+        process: function(rootNode) {
+            var n = rootNode;
+            try {
+                while (n.thDoc) {
+                    this.getChildren(n);
+                    if (n.firstChild && n.firstChild.thDoc && !n.visited) {
+                        n.visited = true;
+                        n = n.firstChild;
+                    } else {
+                        if (n.element != n.thDoc) {
+                            this.doReplace(n.isNode, n.element, n.thDoc);
+                            if (!n.isNode) {
+                                n.thDoc = n.element;
+                            }
+                        }
+                        if (n.nextSibling && n.nextSibling.thDoc) {
+                            n = n.nextSibling;
+                        } else {
+                            if (n == rootNode) {
+                                break;
+                            }
+                            n = n.parentDoc;
+                        }
+                    }
+                }
+                this.processChildren(rootNode);
+            } catch (err) {
+                if (thymol.debug) {
+                    if (err instanceof thymol.ThError) {
+                        if (!err.suppress) {
+                            thymol.thWindow.alert(err);
+                        }
+                    } else {
+                        thymol.thWindow.alert(err);
+                    }
+                }
+            }
+        },
+        getChildren: function(rootNode) {
+            var count = 0, last = null, changed = false, child, froot, fstar, fchildren, i, iLimit, j, jLimit, element, matches, theAttr;
+            if (!rootNode.visited) {
+                this.processComments(rootNode);
+                var rnd = this.getContentRoot(rootNode);
+                froot = $(rnd);
+                fstar = $(froot).add(froot.find("*"));
+                fchildren = fstar.filter(thymol.thInclude.escpName).add(fstar.filter(thymol.thInclude.escpSynonym)).add(fstar.filter(thymol.thReplace.escpName)).add(fstar.filter(thymol.thReplace.escpSynonym)).add(fstar.filter(thymol.thSubstituteby.escpName)).add(fstar.filter(thymol.thSubstituteby.escpSynonym));
+                for (i = 0, iLimit = fchildren.length; i < iLimit; i++) {
+                    element = fchildren[i], matches = [];
+                    for (j = 0, jLimit = element.attributes.length; j < jLimit; j++) {
+                        theAttr = element.attributes[j];
+                        if (thymol.thInclude.name == theAttr.name || thymol.thInclude.synonym == theAttr.name || thymol.thReplace.name == theAttr.name || thymol.thReplace.synonym == theAttr.name || thymol.thSubstituteby.name == theAttr.name || thymol.thSubstituteby.synonym == theAttr.name) {
+                            matches.push(theAttr);
+                        }
+                    }
+                    for (j = 0, jLimit = matches.length; j < jLimit; j++) {
+                        child = this.processImport(element, rootNode, matches[j]);
+                        if (child != null) {
+                            changed = true;
+                            if (count == 0) {
+                                rootNode.firstChild = child;
+                            } else {
+                                last.nextSibling = child;
+                            }
+                            last = child;
+                            count++;
+                        }
+                    }
+                }
+            }
+            return changed;
+        },
+        processChildren: function(rootNode) {
+            var i, iLimit, j, jLimit, k, kLimit;
+            var elements = rootNode.thDoc.getElementsByTagName("*");
+            for (k = 0, kLimit = elements.length; k < kLimit; k++) {
+                var element = elements[k];
+                for (j = 0, jLimit = thymol.thThymeleafElementsList.length; j < jLimit; j++) {
+                    if (element.localName == thymol.thThymeleafElementsList[j].name || element.localName == thymol.thThymeleafElementsList[j].synonym) {
+                        var updated = thymol.thThymeleafElementsList[j].process(element);
+                        if (updated) {
+                            elements = rootNode.thDoc.getElementsByTagName("*");
+                            k--;
+                            kLimit = elements.length;
+                        }
+                        break;
+                    }
+                }
+                var allAttributes = element.attributes;
+                if (allAttributes && allAttributes.length > 0) {
+                    var attributes = [], aii = 0;
+                    if (!thymol.thUsingNullPrefix) {
+                        for (i = 0, iLimit = allAttributes.length; i < iLimit; i++) {
+                            var ai = allAttributes[i];
+                            if (ai) {
+                                for (j = 0, jLimit = thymol.thThymeleafPrefixList.length; j < jLimit; j++) {
+                                    var attrName = ai.name.toString();
+                                    if (attrName.length > thymol.thThymeleafPrefixList[j].length) {
+                                        attrName = attrName.substring(0, thymol.thThymeleafPrefixList[j].length);
+                                        if (attrName === thymol.thThymeleafPrefixList[j]) {
+                                            ai.order = i;
+                                            attributes[aii++] = ai;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    } else {
+                        attributes = allAttributes;
+                    }
+                    if (attributes.length > 0) {
+                        attributes.sort(function(a, b) {
+                            return b.order - a.order;
+                        });
+                        var matchedAttributes = [];
+                        for (i = 0, iLimit = attributes.length; i < iLimit; i++) {
+                            var splits = attributes[i].name.toString().split(":");
+                            if (splits && splits.length > 0) {
+                                var prefix = "", name;
+                                if (splits.length > 1) {
+                                    prefix = splits[0];
+                                    name = splits[1];
+                                } else {
+                                    name = splits[0];
+                                    var hpos = name.lastIndexOf("-");
+                                    if (hpos >= 0) {
+                                        prefix = name.substring(0, hpos + 1);
+                                    }
+                                }
+                                var attrList = thymol.thThymeleafPrefixList[prefix];
+                                if (splits.length > 1) {
+                                    prefix += ":";
+                                }
+                                if (attrList) {
+                                    for (j = 0, jLimit = attrList.length; j < jLimit; j++) {
+                                        var matched = false;
+                                        if (name === attrList[j].suffix || name === attrList[j].synonym) {
+                                            matched = true;
+                                        } else if (attrList[j].regex !== null) {
+                                            var fqn = prefix + name;
+                                            matched = attrList[j].regex.test(fqn);
+                                        }
+                                        if (matched) {
+                                            var matchedAttribute = {};
+                                            matchedAttribute.attr = attrList[j];
+                                            matchedAttribute.elementAttr = attributes[i];
+                                            matchedAttributes.push(matchedAttribute);
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (matchedAttributes.length > 0) {
+                            matchedAttributes.sort(function(a, b) {
+                                return a.attr.precedence - b.attr.precedence;
+                            });
+                            var updated = false;
+                            for (i = 0, iLimit = matchedAttributes.length; i < iLimit; i++) {
+                                var exp = thymol.ThUtils.processElement(matchedAttributes[i].attr.process, element, matchedAttributes[i].elementAttr, matchedAttributes[i].attr, 1);
+                                updated = exp || updated;
+                            }
+                            if (updated) {
+                                elements = rootNode.thDoc.getElementsByTagName("*");
+                                k--;
+                                kLimit = elements.length;
+                            }
+                        }
+                    }
+                }
+            }
+            elements = rootNode.thDoc.getElementsByTagName("*");
+            var kc = 0;
+            for (k = 0, kLimit = elements.length; k < kLimit; k++) {
+                var element = elements[kc];
+                var elName = element.nodeName.toLowerCase();
+                if (elName == thymol.thBlock.name || elName == thymol.thBlock.synonym) {
+                    thymol.ThUtils.removeTag(element);
+                    elements = rootNode.thDoc.getElementsByTagName("*");
+                } else {
+                    kc++;
+                }
+            }
+        },
+        override: function(paramName, paramValue) {
+            var param = paramValue, thv;
+            thv = thymol.thWindow[paramName];
+            if (typeof thv === "undefined") {
+                thv = thymol.applicationContext.javascriptify(paramName);
+            }
+            if (thv) {
+                if (thv instanceof thymol.ThParam) {
+                    param = thv.value;
+                } else {
+                    param = thv;
+                }
+            }
+            thv = thymol.applicationContext[paramName];
+            if (thv) {
+                if (thv instanceof thymol.ThParam) {
+                    param = thv.value;
+                } else {
+                    param = thv;
+                }
+            }
+            thv = thymol.requestContext[paramName];
+            if (thv) {
+                if (thv instanceof thymol.ThParam) {
+                    param = thv.value;
+                } else {
+                    param = thv;
+                }
+            }
+            return param;
+        },
+        doDisable: function(attrName) {
+            var tha = this.getThAttrByName(attrName);
+            if (tha !== null) {
+                tha.disable();
+            } else {
+                if (thymol.debug) {
+                    thymol.thWindow.alert('cannot disable unknown attribute "' + attrName + '"');
+                }
+            }
+        },
+        getThAttrByName: function(name) {
+            var attrList = thymol.thThymeleafPrefixList[thymol.prefix];
+            attrList.push(thymol.thInclude);
+            attrList.push(thymol.thReplace);
+            attrList.push(thymol.thSubstituteby);
+            attrList.push(thymol.thFragment);
+            var i, iLimit = attrList.length;
+            for (i = 0; i < iLimit; i++) {
+                if (name === attrList[i].suffix) {
+                    return attrList[i];
+                }
+            }
+            return null;
+        },
+        getContents: function(rootNode) {
+            var rnd = this.getContentRoot(rootNode);
+            var froot = $(rnd);
+            var fstar = froot.find("*");
+            return fstar;
+        },
+        getContentRoot: function(rn) {
+            var rnd = rn.thDoc;
+            if (rnd.nodeName !== "#document") {
+                rnd = rnd.childNodes;
+            }
+            return rnd;
+        },
+        processComments: function(rootNode) {
+            var comments = null, fstar, changed, i, iLimit, startComment, parent, startValue, pointer, nextPointer;
+            do {
+                fstar = this.getContents(rootNode);
+                comments = fstar.contents().getComments();
+                changed = false;
+                for (i = 0, iLimit = comments.length; i < iLimit; i++) {
+                    startComment = comments[i];
+                    parent = startComment.parentNode;
+                    startValue = startComment.nodeValue.trim();
+                    if (startParserLevelCommentExpr.test(startValue)) {
+                        pointer = startComment;
+                        while (pointer != null) {
+                            if (endParserLevelCommentExpr.test(pointer.nodeValue)) {
+                                changed = parent.removeChild(pointer) != null;
+                                break;
+                            }
+                            nextPointer = pointer.nextSibling;
+                            changed = parent.removeChild(pointer) != null;
+                            pointer = nextPointer;
+                        }
+                    } else if (startParserLevelCommentExpr2.test(startValue) && endParserLevelCommentExpr2.test(startValue)) {
+                        parent.removeChild(startComment);
+                        changed = true;
+                    }
+                }
+            } while (changed);
+            this.processPrototypeOnlyComments(rootNode);
+        },
+        processPrototypeOnlyComments: function(rootNode) {
+            var comments = null, fstar, changed, indexOfLast, i, iLimit, j, jLimit, k, kLimit, startComment, parent, deletions, res, fullText, innerNodes, done, next, commentText, res2, blockElement, blockDoc, blockDocBody, blockBase, newNode, newDoc;
+            do {
+                fstar = this.getContents(rootNode);
+                comments = fstar.contents().getComments();
+                changed = false;
+                indexOfLast = comments.length - 1;
+                for (i = 0, iLimit = comments.length; i < iLimit; i++) {
+                    startComment = comments[i];
+                    parent = startComment.parentNode;
+                    if (parent != null) {
+                        startValue = startComment.nodeValue.trim();
+                        deletions = [];
+                        deletions.push(startComment);
+                        startValue = startValue.replace(/\n/g, "");
+                        res = startValue.match(prototypeOnlyCommentEscpExpr);
+                        if (res) {
+                            fullText = startValue;
+                            if (parent.localName == "table" || parent.localName == "tbody") {
+                                if (startValue.indexOf(thymol.thBlock.name) >= 0 || startValue.indexOf(thymol.thBlock.synonym) >= 0) {
+                                    if (startValue.indexOf(thymol.thBlock.endName) < 0 || startValue.indexOf(thymol.thBlock.endSynonym) < 0) {
+                                        fullText = fullText.replace(res[0], res[1]);
+                                        innerNodes = [];
+                                        done = false;
+                                        next = startComment;
+                                        do {
+                                            next = next.nextSibling;
+                                            if (next != null) {
+                                                deletions.push(next);
+                                                if (i < indexOfLast) {
+                                                    if (next == comments[i + 1]) {
+                                                        commentText = next.nodeValue;
+                                                        if (commentText.indexOf(thymol.thBlock.endName) >= 0 || commentText.indexOf(thymol.thBlock.endSynonym) >= 0) {
+                                                            res2 = commentText.match(prototypeOnlyCommentEscpExpr);
+                                                            if (res2) {
+                                                                commentText = commentText.replace(res2[0], res2[1]);
+                                                                fullText = fullText + commentText;
+                                                            }
+                                                            done = true;
+                                                        }
+                                                    } else {
+                                                        innerNodes.push(next);
+                                                    }
+                                                }
+                                            } else {
+                                                done = true;
+                                            }
+                                        } while (!done);
+                                        blockElement = null;
+                                        blockDoc = new thymol.thDomParser().parseFromString(fullText, "text/html");
+                                        blockDocBody = $(blockDoc).find("body")[0];
+                                        for (j = 0, jLimit = blockDocBody.childNodes.length; j < jLimit; j++) {
+                                            if (blockDocBody.childNodes[j].localName == thymol.thBlock.name || blockDocBody.childNodes[j].localName == thymol.thBlock.synonym) {
+                                                blockElement = blockDocBody.childNodes[j];
+                                                for (k = 0, kLimit = innerNodes.length; k < kLimit; k++) {
+                                                    newNode = blockDoc.importNode(innerNodes[k], true);
+                                                    blockElement.appendChild(newNode);
+                                                }
+                                            }
+                                        }
+                                        if (blockElement != null) {
+                                            blockBase = new ThNode(blockDoc, false, null, null, null, blockDoc.nodeName, "::", false, blockDoc);
+                                            this.processChildren(blockBase);
+                                            changed = this.insertUncommented(blockBase.thDoc, deletions, parent);
+                                        } else {
+                                            parent.removeChild(startComment);
+                                            changed = true;
+                                        }
+                                    } else {
+                                        parent.removeChild(startComment);
+                                        changed = true;
+                                    }
+                                }
+                            } else {
+                                startValue = startValue.substring(3, startValue.length - 3);
+                                newDoc = new thymol.thDomParser().parseFromString(startValue, "text/html");
+                                changed = this.insertUncommented(newDoc, deletions, parent);
+                            }
+                        }
+                    }
+                }
+            } while (changed);
+        },
+        insertUncommented: function(doc, deletions, parent) {
+            var docBody = $(doc).find("body")[0], i, iLimit, newNode;
+            for (i = 0, iLimit = docBody.childNodes.length; i < iLimit; i++) {
+                if (parent.ownerDocument === doc) {
+                    newNode = docBody.childNodes[i].cloneNode(true);
+                } else {
+                    newNode = parent.ownerDocument.importNode(docBody.childNodes[i], true);
+                    newNode.parentNode = parent;
+                }
+                parent.insertBefore(newNode, deletions[0]);
+            }
+            for (i = 0, iLimit = deletions.length; i < iLimit; i++) {
+                parent.removeChild(deletions[i]);
+            }
+            return true;
+        },
+        getList: function(element, content) {
+            var argValue = content.trim(), argsCount = 0, argsList = [], assigs, i, iLimit, val;
+            if (argValue) {
+                assigs = argValue.split(",");
+                for (i = 0, iLimit = assigs.length; i < iLimit; i++) {
+                    val = thymol.getExpression(assigs[i], element);
+                    argsList[i] = val;
+                }
+                if (!element.thLocalVars) {
+                    element.thLocalVars = {};
+                }
+                element.thLocalVars["..."] = argsList;
+                argsCount = argsList.length;
+            }
+            return argsCount;
+        },
+        testParam: function(param) {
+            var initial = param, result = false, theParam = null, negate = false;
+            if (typeof initial === "boolean") {
+                result = initial;
+            } else {
+                theParam = null;
+                negate = false;
+                if (typeof initial === "object" && initial instanceof thymol.ThParam) {
+                    theParam = initial;
+                } else {
+                    initial = initial.valueOf();
+                    if (initial.charAt(0) == "!") {
+                        negate = true;
+                        initial = initial.substring(1);
+                    }
+                }
+                theParam = thymol.applicationContext[initial];
+                if (theParam != null) {
+                    result = theParam.getBooleanValue();
+                }
+                if (negate) {
+                    result = !result;
+                }
+            }
+            return result ? true : false;
+        },
+        processImport: function(element, rootNode, attr) {
+            var importNode = null, filePart, fragmentPart, names, parts, fragmentArgsList, isNode, fragment, fileName, content, importError;
+            filePart = null;
+            if (attr.value.indexOf("::") < 0) {
+                filePart = attr.value;
+                fragmentPart = "::";
+            } else {
+                names = attr.value.split("::");
+                filePart = names[0].trim();
+                fragmentPart = names[1].trim();
+            }
+            if ("this" === filePart) {
+                filePart = "";
+            } else {
+                filePart = this.getFilePath(filePart, element);
+            }
+            if (filePart != null) {
+                parts = filePart.match(varParExpr);
+                fragmentArgsList = null;
+                if (parts) {
+                    if (parts.length > 1) {
+                        filePart = parts[1].trim();
+                    }
+                    if (parts.length > 2) {
+                        fragmentArgsList = parts[2].trim();
+                    }
+                }
+                if (filePart != "" || !isFragmentChild(element)) {
+                    isNode = thymol.thReplace.name == attr.localName || thymol.thReplace.synonym == attr.localName || thymol.thSubstituteby.name == attr.localName || thymol.thSubstituteby.synonym == attr.localName;
+                    if (thymol.thCache[filePart] != null && thymol.thCache[filePart][fragmentPart] != null) {
+                        isNode = isNode || fragmentPart == "::";
+                        importNode = new ThNode(thymol.thCache[filePart][fragmentPart], false, rootNode, null, null, filePart, fragmentPart, isNode, element);
+                    } else {
+                        fragment = null;
+                        importError = null;
+                        if (filePart != "") {
+                            fileName = filePart + thymol.templateSuffix;
+                            $.get(fileName, function(textContent, status) {
+                                try {
+                                    if ("success" == status) {
+                                        content = new thymol.thDomParser().parseFromString(textContent, "text/html");
+                                        fragment = Thymol.prototype.getImportNode(element, filePart, fragmentPart, fragmentArgsList, content);
+                                    } else if (thymol.debug) {
+                                        thymol.thWindow.alert("thymol.processImport file read failed: " + filePart + " fragment: " + fragmentPart);
+                                    }
+                                } catch (err) {
+                                    importError = err;
+                                }
+                            }, "text");
+                        } else {
+                            fragment = this.getImportNode(element, filePart, fragmentPart, fragmentArgsList, thymol.thDocument);
+                        }
+                        if (fragment == null) {
+                            if (importError !== null) {
+                                throw importError;
+                            }
+                            if (thymol.debug) {
+                                thymol.thWindow.alert("thymol.processImport fragment import failed: " + filePart + " fragment: " + fragmentPart);
+                            }
+                        } else {
+                            importNode = new ThNode(fragment, false, rootNode, null, null, filePart, fragmentPart, isNode, element);
+                        }
+                    }
+                }
+            }
+            element.removeAttribute(attr.name);
+            return importNode;
+        },
+        getImportNode: function(element, filePart, fragmentArg, fragmentArgsList, content) {
+            var result = null, fragmentName = fragmentArg.trim(), fragmentPart = fragmentName, parts, argsCount, matched, fragment, htmlContent, fragArray, i, iLimit, j, jLimit, k, clean, bare, vlParts, vlArgs, argsList, varName, newElement;
+            fragmentName = fragmentName.replace(/text\(\)/g, textFuncSynonym);
+            parts = fragmentName.match(varParExpr);
+            if (parts == null && fragmentArgsList != null) {
+                parts = [];
+                parts[1] = fragmentName;
+                parts[2] = fragmentArgsList;
+            }
+            argsCount = 0;
+            if (parts) {
+                if (parts.length > 1) {
+                    fragmentName = parts[1].trim();
+                    if (parts.length > 2) {
+                        if (parts[2].indexOf("=") > 0) {
+                            argsCount = thymol.getWith(element, parts[2]);
+                        } else {
+                            argsCount = this.getList(element, parts[2]);
+                        }
+                    }
+                }
+            }
+            if (thymol.thCache[filePart] == null) {
+                thymol.thCache[filePart] = new Object();
+            }
+            matched = false;
+            fragment = null;
+            if (fragmentName == "::") {
+                htmlContent = $("html", content)[0];
+                result = htmlContent;
+                matched = true;
+            } else {
+                fragArray = $(thymol.thFragment.escpName, content);
+                for (i = 0, iLimit = fragArray.length; i < iLimit; i++) {
+                    fragment = fragArray[i];
+                    for (j = 0, jLimit = fragment.attributes.length; j < jLimit; j++) {
+                        clean = fragment.attributes[j];
+                        clean = clean.value.replace(/\s/g, "");
+                        bare = null;
+                        vlParts = clean.match(varParExpr);
+                        if (vlParts) {
+                            if (vlParts.length > 1) {
+                                bare = vlParts[1].trim();
+                            }
+                        }
+                        if (fragmentName == bare && argsCount > 0) {
+                            if (vlParts.length > 2) {
+                                vlArgs = vlParts[2].trim().split(",");
+                                if (vlArgs) {
+                                    if (vlArgs.length == argsCount) {
+                                        argsList = element.thLocalVars["..."];
+                                        if (argsList != null) {
+                                            for (k = 0; k < argsCount; k++) {
+                                                varName = vlArgs[k].trim();
+                                                element.thLocalVars[varName] = argsList[k];
+                                            }
+                                            element.thLocalVars["..."] = null;
+                                        }
+                                        matched = true;
+                                        break;
+                                    } else if (vlArgs.length > argsCount) {
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        if (fragmentName == clean || fragmentPart == clean || fragmentName == bare) {
+                            matched = true;
+                            break;
+                        }
+                    }
+                    if (matched) {
+                        result = fragment;
+                        break;
+                    }
+                }
+            }
+            if (!matched) {
+                fragment = this.getDOMSelection(fragmentName, content);
+                if (fragment) {
+                    matched = true;
+                    result = fragment;
+                } else {
+                    if (!element.isBlockChild) {
+                        throw new thymol.ThError('getImportNode cannot match fragment: "' + fragmentName + '"', element);
+                    }
+                }
+            }
+            thymol.thCache[filePart][fragmentPart] = result;
+            if (matched) {
+                newElement = result.cloneNode(true);
+                if (newElement.nodeType == 1) {
+                    newElement.removeAttribute(thymol.thFragment.name);
+                    newElement.removeAttribute(thymol.thFragment.synonym);
+                }
+                result = newElement;
+                result.thLocalVars = element.thLocalVars;
+            }
+            return result;
+        },
+        getDOMSelection: function(initial, content) {
+            var spec = initial, result = null, scope = "", query = new Array(), parts = "", innr = thymol.ThUtils.unBracket(spec), i, iLimit, j, jLimit, k, kLimit, m, mLimit, token, indx, saved, indxed, start, selection, descend, subQuery, exprFrags, classSpecs, qTerms, subSelect, partial, html, newNode;
+            if (spec != innr && innr.charAt(innr.length - 1) == "]") {
+                spec = innr;
+            }
+            while (spec != "") {
+                parts = spec.match(domSelectExpr);
+                if (parts != null && parts.length > 1) {
+                    for (i = 1, iLimit = parts.length; i < iLimit; i++) {
+                        if (parts[i] != null) {
+                            token = parts[i];
+                            indx = null;
+                            innr = thymol.ThUtils.unBracket(token);
+                            if (token != innr) {
+                                if (innr.match(numericExpr)) {
+                                    indx = innr;
+                                }
+                            }
+                            saved = spec;
+                            spec = spec.replace(token, "");
+                            if (saved == spec) {
+                                spec = "";
+                            }
+                            if (indx) {
+                                token = query[query.length - 1];
+                                indxed = new String(token);
+                                indxed.indx = indx;
+                                query[query.length - 1] = indxed;
+                            } else {
+                                query.push(token.trim());
+                            }
+                            break;
+                        }
+                    }
+                } else {
+                    break;
+                }
+            }
+            start = 0;
+            if (query.length > 0 && query[0] != "" && query[0].charAt(0) == "/") {
+                scope = query[0];
+                start = 1;
+            }
+            selection = [];
+            selection.push(content);
+            descend = false;
+            for (i = start, iLimit = query.length; i < iLimit; i++) {
+                subQuery = query[i];
+                innr = thymol.ThUtils.unBracket(subQuery);
+                if (subQuery != innr) {
+                    innr = innr.replace(/[']/g, '"');
+                    subQuery = "";
+                    exprFrags = innr.split(/\s{1}\s*((?:and)|(?:or))\s{1}\s*/);
+                    for (j = 0, jLimit = exprFrags.length; j < jLimit; j++) {
+                        if (exprFrags[j] != "and" && exprFrags[j] != "or") {
+                            classSpecs = exprFrags[j].match(/[@]?\s*(?:class)\s*(\W?[=])\s*[\"]((?:\w*[\-_]*)*)[\"]/);
+                            if (classSpecs && classSpecs.length > 0) {
+                                if (classSpecs[1] == "=") {
+                                    subQuery = subQuery + "[class~='" + classSpecs[2] + "']";
+                                }
+                                if (classSpecs[1] == "^=") {
+                                    subQuery = subQuery + "[class^='" + classSpecs[2] + "'],[class*=' " + classSpecs[2] + "']";
+                                }
+                            } else {
+                                subQuery = subQuery + "[" + exprFrags[j] + "]";
+                            }
+                        } else if (exprFrags[j] == "or") {
+                            subQuery = subQuery + ",";
+                        }
+                    }
+                }
+                qTerms = subQuery.split("/");
+                for (j = 0, jLimit = qTerms.length; j < jLimit; j++) {
+                    if (qTerms[j] != "") {
+                        qTerms[j] = qTerms[j].replace(/[@]/g, "");
+                        if (subQuery.indx != null) {
+                            qTerms[j] = qTerms[j] + ":eq(" + subQuery.indx + ")";
+                        }
+                        subSelect = [];
+                        for (k = 0, kLimit = selection.length; k < kLimit; k++) {
+                            partial = null;
+                            if (qTerms[j] == textFuncSynonym) {
+                                partial = $(selection[k]).contents().filter(function() {
+                                    return this.nodeType === 3;
+                                });
+                            } else if (descend) {
+                                partial = $(selection[k]).children(qTerms[j]);
+                            } else if (j == 0) {
+                                if (scope == "/") {
+                                    html = $("html", selection[k]);
+                                    if (html.length > 0) {
+                                        selection[k] = html;
+                                    }
+                                    partial = $(selection[k]).children("body").children(qTerms[j]);
+                                    scope = "";
+                                } else {
+                                    if (i == 0 || scope == "//") {
+                                        partial = $(selection[k]).find(qTerms[j]);
+                                        scope = "";
+                                    } else {
+                                        partial = $(selection[k]).filter(qTerms[j]);
+                                    }
+                                }
+                            } else {
+                                partial = $(selection[k]).children(qTerms[j]);
+                            }
+                            if (partial != null) {
+                                for (m = 0, mLimit = partial.length; m < mLimit; m++) {
+                                    subSelect.push(partial[m]);
+                                }
+                            }
+                        }
+                        selection = subSelect;
+                    }
+                }
+                descend = qTerms[qTerms.length - 1] == "";
+            }
+            result = selection;
+            if (result != null && !(result.length === undefined)) {
+                if (result.length > 1) {
+                    newNode = thymol.thDocument.createDocumentFragment();
+                    for (i = 0, iLimit = result.length; i < iLimit; i++) {
+                        var newChild = thymol.thDocument.importNode(result[i], true);
+                        newNode.appendChild(newChild);
+                    }
+                    result = newNode;
+                } else {
+                    result = result[0];
+                }
+            }
+            return result;
+        },
+        getFilePath: function(part, element) {
+            var result = thymol.substitute(part, element), mapped = null, slashpos;
+            if (result) {
+                if (thymol.mappings) {
+                    mapped = thymol.getMapped(result, false);
+                }
+            }
+            if (mapped) {
+                result = mapped;
+            } else {
+                var dotFirst = result.charAt(0) === ".";
+                if (result && (thymol.useAbsolutePath || !dotFirst)) {
+                    slashpos = result.indexOf("/");
+                    if (thymol.useAbsolutePath || slashpos >= 0) {
+                        if (slashpos == 0 && !thymol.useAbsolutePath) {
+                            result = result.substring(1);
+                        }
+                        var proto = "";
+                        if (thymol.useAbsolutePath) {
+                            proto = thymol.protocol;
+                        }
+                        if (thymol.useAbsolutePath && !!thymol.absolutePath) {
+                            result = proto + thymol.absolutePath + result;
+                        } else {
+                            if (dotFirst) {
+                                result = thymol.templatePath + result;
+                            } else {
+                                result = proto + thymol.root + thymol.path + result;
+                            }
+                        }
+                    }
+                }
+            }
+            return result;
+        },
+        doLiteralSubstExpr: function(param, primary) {
+            var result = param.trim(), term, subst, lsp;
+            if (thymol.ThUtils.isLiteralSubst(result)) {
+                result = this.decodeLiteralSubst(result);
+            } else {
+                term = primary;
+                while (term != null) {
+                    if (thymol.ThUtils.isLiteralSubst(term)) {
+                        subst = this.decodeLiteralSubst(term);
+                        result = result.replace(term, subst);
+                        lsp = result.match(litSubstExpr);
+                        if (lsp && lsp.length > 0) {
+                            term = lsp[1];
+                        } else {
+                            break;
+                        }
+                    } else {
+                        break;
+                    }
+                }
+            }
+            return result;
+        },
+        decodeLiteralSubst: function(param) {
+            var result = param, parts, rep, i, iLimit;
+            result = result.trim();
+            result = result.substring(1, result.length - 1);
+            result = result.replace(/[\']/g, "&#39;");
+            parts = result.split(varRefExpr);
+            if (parts && parts.length > 0) {
+                rep = "";
+                for (i = 0, iLimit = parts.length; i < iLimit; i++) {
+                    if (parts[i] != "") {
+                        if (!parts[i].match(varRefExpr)) {
+                            parts[i] = "'" + parts[i] + "'";
+                        }
+                        if (rep == "") {
+                            rep = parts[i];
+                        } else {
+                            rep = rep + "+" + parts[i];
+                        }
+                    }
+                }
+                result = rep;
+            }
+            return result;
+        },
+        doReplace: function(isNode, element, content) {
+            if (isNode) {
+                var parent = element.parentNode;
+                if (content.nodeName.toLowerCase() == "html") {
+                    this.doInsertion(element, content, function(e, n) {
+                        if (n.nodeType == 1) {
+                            n.removeAttribute(thymol.thFragment.name);
+                            n.removeAttribute(thymol.thFragment.synonym);
+                        }
+                        e.parentNode.insertBefore(n, e);
+                    });
+                    parent.removeChild(element);
+                } else {
+                    var node = this.doClone(content, parent.ownerDocument);
+                    if (node.nodeType == 1) {
+                        node.removeAttribute(thymol.thFragment.name);
+                        node.removeAttribute(thymol.thFragment.synonym);
+                    }
+                    parent.replaceChild(node, element);
+                    node.parentNode = parent;
+                }
+            } else {
+                try {
+                    while (element.firstChild != null) {
+                        element.removeChild(element.firstChild);
+                        if (element.firstChild == null) {
+                            break;
+                        }
+                    }
+                    this.doInsertion(element, content, function(e, n) {
+                        if (n.nodeType == 1) {
+                            n.removeAttribute(thymol.thFragment.name);
+                            n.removeAttribute(thymol.thFragment.synonym);
+                        }
+                        e.appendChild(n);
+                    });
+                } catch (err) {
+                    element.innerHTML = content.innerHTML;
+                }
+            }
+        },
+        doClone: function(old, targetDoc) {
+            var node, cNodes, i, iNode, aNode;
+            if (!!old.parentNode && old.parentNode.ownerDocument === targetDoc) {
+                node = old.cloneNode(false);
+            } else {
+                node = targetDoc.importNode(old, false);
+            }
+            if (node !== null) {
+                if (node.nodeType == 1) {
+                    if (old.thLocalVars !== null) {
+                        node.thLocalVars = old.thLocalVars;
+                    }
+                }
+                if (old.childNodes !== null) {
+                    cNodes = old.childNodes.length;
+                    if (cNodes > 0) {
+                        for (i = 0; i < cNodes; i++) {
+                            iNode = old.childNodes[i];
+                            if (iNode !== null) {
+                                aNode = this.doClone(iNode, targetDoc);
+                                if (aNode !== null) {
+                                    node.appendChild(aNode);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            return node;
+        },
+        doInsertion: function(element, content, func) {
+            var topLevel = true, parent = element.parentElement, i, iLimit, iNode, elementName, j, jLimit, jNode, cJNode, cINode;
+            if (parent != null) {
+                topLevel = element.parentElement.nodeName.toLowerCase() == "html";
+            }
+            for (i = 0, iLimit = content.childNodes.length; i < iLimit; i++) {
+                iNode = content.childNodes[i];
+                if (iNode) {
+                    if (!topLevel) {
+                        elementName = iNode.nodeName.toLowerCase();
+                        if (elementName != "head") {
+                            if (elementName == "body") {
+                                for (j = 0, jLimit = iNode.childNodes.length; j < jLimit; j++) {
+                                    jNode = iNode.childNodes[j];
+                                    if (jNode) {
+                                        cJNode = this.doClone(jNode, parent.ownerDocument);
+                                        func(element, cJNode);
+                                    }
+                                }
+                            } else {
+                                cINode = this.doClone(iNode, parent.ownerDocument);
+                                func(element, cINode);
+                            }
+                        }
+                    } else {
+                        cINode = this.doClone(iNode, parent.ownerDocument);
+                        func(element, cINode);
+                    }
+                }
+            }
+        },
+        getThParam: function(paramName, isBoolean, isPath, defaultValue) {
+            var localValue = defaultValue, globalValue = thymol.thWindow[paramName], theParam = thymol.ThUtils.getParameter(paramName);
+            if (typeof globalValue === "undefined") {
+                globalValue = thymol.applicationContext.javascriptify(paramName);
+            }
+            if (!!theParam) {
+                if (theParam instanceof ThParam) {
+                    if (theParam.globalValue !== globalValue) {
+                        theParam.globalValue = globalValue;
+                        theParam.value = globalValue;
+                        localValue = globalValue;
+                    }
+                }
+                if (isBoolean) {
+                    localValue = theParam.getBooleanValue();
+                }
+            } else {
+                if (!(typeof globalValue === "undefined")) {
+                    if (globalValue != null) {
+                        if (isBoolean) {
+                            localValue = globalValue == true;
+                        } else {
+                            localValue = globalValue;
+                        }
+                    }
+                }
+            }
+            if (!isBoolean && isPath && localValue.length > 0 && localValue.charAt(localValue.length - 1) != "/") {
+                localValue = localValue + "/";
+            }
+            thymol.applicationContext.createVariable(paramName, localValue);
+            return localValue;
+        }
+    };
+    function addDialect(spec) {
+        var i, iLimit, prec = thymol.thDefaultPrecedence;
+        if (spec !== null && typeof spec !== "undefined") {
+            if (spec.attributeProcessors !== null && typeof spec.attributeProcessors !== "undefined") {
+                for (i = 0, iLimit = spec.attributeProcessors.length; i < iLimit; i++) {
+                    if (spec.attributeProcessors[i].precedence !== null && typeof spec.attributeProcessors[i].precedence !== "undefined") {
+                        prec = spec.attributeProcessors[i].precedence;
+                    } else {
+                        prec = thymol.thDefaultPrecedence;
+                    }
+                    configureAttributeProcessor(spec.prefix, spec.attributeProcessors[i].name, spec.attributeProcessors[i].processor, prec, null);
+                }
+            }
+            if (spec.elementProcessors !== null && typeof spec.elementProcessors !== "undefined") {
+                for (i = 0, iLimit = spec.elementProcessors.length; i < iLimit; i++) {
+                    configureElementProcessor(spec.prefix, spec.elementProcessors[i].name, spec.elementProcessors[i].processor);
+                }
+            }
+            if (spec.objects !== null && typeof spec.objects !== "undefined") {
+                for (i = 0, iLimit = spec.objects.length; i < iLimit; i++) {
+                    if (spec.objects[i].name !== null && typeof spec.objects[i].name !== "undefined") {
+                        spec.objects[i].object.thExpressionObjectName = spec.objects[i].name;
+                        configureModule(spec.objects[i].object);
+                    } else {
+                        configureModule(spec.objects[i]);
+                    }
+                }
+            }
+        }
+    }
+    function ThNode(thDocParam, visitedParam, parentDocParam, firstChildParam, nextSiblingParam, fileNameParam, fragNameParam, isNodeParam, elementParam) {
+        this.thDoc = thDocParam;
+        this.visited = visitedParam;
+        this.parentDoc = parentDocParam;
+        this.firstChild = firstChildParam;
+        this.nextSibling = nextSiblingParam;
+        this.fileName = fileNameParam;
+        this.fragName = fragNameParam;
+        this.isNode = isNodeParam;
+        this.element = elementParam;
+    }
+    function ThError(message, element, source) {
+        this.name = "ThError";
+        this.message = message || "Default Message";
+        if (element !== null && typeof element !== "undefined" && element.isBlockChild) {
+            this.suppress = true;
+        } else {
+            this.element = element || {};
+            this.suppress = false;
+        }
+        if (!!source) {
+            if (!!source.stack) {
+                this.stack = source.stack;
+            }
+        }
+    }
+    ThError.prototype = new Error();
+    ThError.prototype.constructor = ThError;
+    function ThParam(valueArg) {
+        this.value = valueArg;
+        this.globalValue;
+        this["class"] = new thymol.ThClass("Thymol.ThParam");
+        this.getBooleanValue = function() {
+            return !thymol.ThUtils.testLiteralFalse(this.value);
+        };
+        this.toString = function() {
+            return this.value;
+        };
+        this.getNumericValue = function() {
+            return Number(this.value);
+        };
+    }
+    function ThAttr(suffix, func, prec, list, pref, dataAttr) {
+        var prefix = "", dataPrefix = null, escpPrefix = "";
+        if (typeof pref !== "undefined" && pref !== null) {
+            prefix = pref + ":";
+            if (thymol.thThymeleafPrefixList.indexOf(prefix) < 0) {
+                thymol.thThymeleafPrefixList.push(prefix);
+            }
+            escpPrefix = pref + "\\:";
+            if (typeof dataAttr === "undefined" || dataAttr === null) {
+                dataPrefix = thymol.dataPrefix + "-" + pref + "-";
+                if (thymol.thThymeleafPrefixList.indexOf(dataPrefix) < 0) {
+                    thymol.thThymeleafPrefixList.push(dataPrefix);
+                }
+            } else {
+                dataPrefix = dataAttr;
+            }
+        }
+        this.suffix = suffix;
+        this.name = prefix + suffix;
+        this.regex = null;
+        if (suffix.indexOf("*") >= 0 || suffix.indexOf("?") >= 0 || suffix.indexOf("+") >= 0 || suffix.indexOf("\\") >= 0 || suffix.indexOf("|") >= 0 || suffix.indexOf("[") >= 0 || suffix.indexOf("]") >= 0 || suffix.indexOf("{") >= 0 || suffix.indexOf("}") >= 0) {
+            if ("*" === suffix) {
+                suffix = ".*";
+            }
+            suffix = prefix + suffix;
+            this.regex = new RegExp(suffix);
+        }
+        this.escpName = "[" + escpPrefix + suffix + "]";
+        if (dataPrefix !== null) {
+            this.synonym = dataPrefix + suffix;
+            this.escpSynonym = "[" + this.synonym + "]";
+        } else {
+            this.synonym = null;
+            this.escpSynonym = null;
+        }
+        if (typeof prec !== "undefined" && prec !== null) {
+            this.precedence = prec;
+        } else {
+            this.precedence = thymol.thDefaultPrecedence;
+        }
+        if (!!list) {
+            var attrList = list[pref];
+            if (!attrList) {
+                attrList = [];
+                list[pref] = attrList;
+                if (dataPrefix !== null) {
+                    list[dataPrefix] = attrList;
+                }
+            }
+            attrList.push(this);
+        }
+        this.process = function() {
+            thymol.thWindow.alert('unsupported processing function for attribute "' + this.name + '"');
+        };
+        if (!(typeof func === "undefined")) {
+            this.process = func;
+        }
+        this.disable = function() {
+            this.name = null;
+            this.escpName = null;
+            this.escpSynonym = null;
+            this.process = function() {};
+        };
+    }
+    function ThElement(suffix, func, pref) {
+        var tha = new thymol.ThAttr(suffix, null, 0, null, pref);
+        this.name = tha.name;
+        this.synonym = tha.synonym;
+        this.endName = "/" + tha.name;
+        this.endSynonym = "/" + tha.synonym;
+        this.process = function() {
+            thymol.thWindow.alert('unsupported processing function for element "' + this.name + '"');
+        };
+        if (!(typeof func === "undefined")) {
+            this.process = func;
+        }
+        this.disable = function() {
+            this.name = null;
+            this.synonym = null;
+            this.endName = null;
+            this.endSynonym = null;
+            this.process = null;
+        };
+        thymol.thThymeleafElementsList.push(this);
+    }
+    function ThSet() {
+        this.that = this;
+        this.setSize = 0;
+        this.isContent = function(k) {
+            return this.hasOwnProperty(k) && typeof this[k] !== "function" && k !== "that" && k !== "setSize";
+        };
+        this.add = function(k) {
+            var contained = typeof this[k] !== "undefined";
+            this[k] = k;
+            if (contained !== (typeof this[k] !== "undefined")) {
+                this.setSize++;
+            }
+        };
+        this.addAll = function(other) {
+            var k = null, value;
+            for (k in other) {
+                if (other.hasOwnProperty(k)) {
+                    value = other[k];
+                    if (typeof value !== "function") {
+                        add(value);
+                    }
+                }
+            }
+        };
+        this.clear = function() {
+            for (var k in this) {
+                if (this.hasOwnProperty(k)) {
+                    delete this[k];
+                }
+            }
+            setSize = 0;
+        };
+        this.contains = function(k) {
+            return typeof this[k] !== "undefined";
+        };
+        this.containsAll = function(keys) {
+            var keySet = keys, k = null;
+            if (typeof keys === "Array" || Object.prototype.toString.call(keys) === "[object Array]") {
+                keySet = ThSet.prototype.fromArray(keys);
+            }
+            for (k in keySet) {
+                if (keySet.hasOwnProperty(k)) {
+                    if (typeof this[k] === "undefined") {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        };
+        this.isEmpty = function() {
+            return this.setSize === 0;
+        };
+        this.size = function() {
+            return this.setSize;
+        };
+        this.remove = function(k) {
+            var contained = typeof this[k] !== "undefined";
+            delete this[k];
+            if (contained !== (typeof this[k] !== "undefined")) {
+                this.setSize--;
+            }
+        };
+        this.toArray = function() {
+            return getArray(this);
+        };
+        this.toString = function() {
+            var array = getArray();
+            return array.toString();
+        };
+        function getArray(obj) {
+            var array = [], k = null, value;
+            for (k in obj) {
+                if (obj.hasOwnProperty(k) && k !== "that" && k !== "setSize") {
+                    value = obj[k];
+                    if (typeof value !== "function") {
+                        array.push(value);
+                    }
+                }
+            }
+            return array;
+        }
+    }
+    ThSet.prototype.fromArray = function(array) {
+        var set = new thymol.ThSet(), i, iLimit;
+        for (i = 0, iLimit = array.length; i < iLimit; i++) {
+            set.add(array[i]);
+        }
+        return set;
+    };
+    function ThMap() {
+        ThSet.apply(this);
+        this.containsKey = function(k) {
+            return this.contains(k);
+        };
+        this.containsValue = function(target) {
+            var k = null, value;
+            for (k in this.that) {
+                if (this.that.hasOwnProperty(k) && k !== "that") {
+                    value = this.that[k];
+                    if (value === target) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        };
+        this.entrySet = function() {
+            return this.that;
+        };
+        this.get = function(k) {
+            return this.that[k];
+        };
+        this.keySet = function() {
+            return this.that;
+        };
+        this.put = function(k, v) {
+            var contained = typeof this[k] !== "undefined";
+            this.that[k] = v;
+            if (contained !== (typeof this[k] !== "undefined")) {
+                this.setSize++;
+            }
+        };
+        this.putAll = function(t) {
+            for (var k in t) {
+                put(k, t[k]);
+            }
+        };
+        this.values = function() {
+            return this.that;
+        };
+    }
+    ThMap.prototype = new ThSet();
+    ThMap.prototype.constructor = ThMap;
+    function ThObject(dolly) {
+        for (prop in dolly) {
+            if (dolly.hasOwnProperty(prop)) {
+                if (prop) {
+                    if (!this[prop]) {
+                        this[prop] = dolly[prop];
+                    }
+                }
+            }
+        }
+        this["class"] = new thymol.ThClass("Thymol.ThObject");
+        this.toNonThObject = function() {
+            var plain = {};
+            for (prop in this) {
+                if (this.hasOwnProperty(prop)) {
+                    if (prop) {
+                        if (!plain[prop]) {
+                            if (prop !== "toNonThObject") {
+                                if (prop !== "class" || prop === "class" && this[prop] !== null && this[prop].name !== "Thymol.ThObject") {
+                                    plain[prop] = this[prop];
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            return plain;
+        };
+    }
+    function ThVarsAccessor(storeArg, storeNameArg) {
+        this.store = storeArg;
+        this.arrayName = storeNameArg;
+        this.length = function() {
+            return this.store.length;
+        };
+        this.get = function(name) {
+            return this.store[name];
+        };
+        this.set = function(name, value) {
+            this.store[name] = value;
+        };
+    }
+    function ThClass(nValue) {
+        this.name = nValue;
+    }
+    return {
+        Thymol: Thymol,
+        ThError: ThError,
+        ThParam: ThParam,
+        ThAttr: ThAttr,
+        ThElement: ThElement,
+        ThSet: ThSet,
+        ThMap: ThMap,
+        ThObject: ThObject,
+        ThVarsAccessor: ThVarsAccessor,
+        ThClass: ThClass,
+        thDomParser: thymol.thDomParser,
+        thDocument: thymol.thDocument,
+        thWindow: thymol.thWindow,
+        thTop: thymol.thTop,
+        thRequest: thymol.thRequest,
+        thVersion: thymol.thVersion,
+        thReleaseDate: thymol.thReleaseDate,
+        thURL: thymol.thURL,
+        thAltURL: thymol.thAltURL,
+        thInclude: thymol.thInclude,
+        thReplace: thymol.thReplace,
+        thSubstituteby: thymol.thSubstituteby,
+        thFragment: thymol.thFragment,
+        thRemove: thymol.thRemove,
+        thBlock: thymol.thBlock,
+        thScriptName: thymol.thScriptName,
+        thDefaultPrefix: thymol.thDefaultPrefix,
+        thDefaultDataPrefix: thymol.thDefaultDataPrefix,
+        thDefaultPrecision: thymol.thDefaultPrecision,
+        thDefaultProtocol: thymol.thDefaultProtocol,
+        thDefaultLocale: thymol.thDefaultLocale,
+        thDefaultPrecedence: thymol.thDefaultPrecedence,
+        thDefaultMessagePath: thymol.thDefaultMessagePath,
+        thDefaultResourcePath: thymol.thDefaultResourcePath,
+        thDefaultMessagesBaseName: thymol.thDefaultMessagesBaseName,
+        thDefaultRelativeRootPath: thymol.thDefaultRelativeRootPath,
+        thDefaultExtendedMapping: thymol.thDefaultExtendedMapping,
+        thDefaultLocalMessages: thymol.thDefaultLocalMessages,
+        thDefaultDisableMessages: thymol.thDefaultDisableMessages,
+        thDefaultTemplateSuffix: thymol.thDefaultTemplateSuffix,
+        thThymeleafPrefixList: thymol.thThymeleafPrefixList,
+        thThymeleafElementsList: thymol.thThymeleafElementsList,
+        thLocation: thymol.thLocation,
+        messagePath: thymol.messagePath,
+        resourcePath: thymol.resourcePath,
+        relativeRootPath: thymol.relativeRootPath,
+        messagesBaseName: thymol.messagesBaseName,
+        extendedMapping: thymol.extendedMapping,
+        scriptPath: thymol.scriptPath,
+        absolutePath: thymol.absolutePath,
+        useAbsolutePath: thymol.useAbsolutePath,
+        useFullURLPath: thymol.useFullURLPath,
+        localMessages: thymol.localMessages,
+        indexFile: thymol.indexFile,
+        disableMessages: thymol.disableMessages,
+        templateSuffix: thymol.templateSuffix,
+        prefix: thymol.prefix,
+        dataPrefix: thymol.dataPrefix,
+        templateName: thymol.templateName,
+        templatePath: thymol.templatePath,
+        objects: thymol.objects,
+        jqSetup: jqSetup,
+        isClientSide: isClientSide,
+        execute: execute,
+        updatePrefix: updatePrefix,
+        init: init,
+        ready: ready,
+        addDialect: addDialect,
+        isFragmentChild: isFragmentChild,
+        preProcess: preProcess,
+        substitute: substitute,
+        substituteParam: substituteParam,
+        configureModule: configureModule,
+        configureAttributeProcessor: configureAttributeProcessor,
+        configureElementProcessor: configureElementProcessor,
+        configurePreExecution: configurePreExecution,
+        configurePostExecution: configurePostExecution,
+        getStandardURL: getStandardURL,
+        getMessage: getMessage,
+        getExpression: getExpression,
+        getWith: getWith,
+        getParsedExpr: getParsedExpr,
+        getLocale: getLocale,
+        getMapped: getMapped,
+        getBooleanValue: getBooleanValue,
+        setLocale: setLocale
+    };
+}();
+
+thymol.makeContext = function(contextNameParam, varAccessorParam) {
+    var jsonDeclSpec = "(?:\\W*([\\'][A-Za-z]+(?:\\w|[$])*[\\'])\\s*[:])?\\s*([#][A-Za-z]+(?:\\w|[$])*)(?:\\W|[^$])*", jsonDeclExpr = new RegExp(jsonDeclSpec), context = new Array();
+    context.contextName = contextNameParam;
+    context.varAccessor = varAccessorParam;
+    context.varStore = [];
+    context.varNamePrefix = "";
+    if (typeof varAccessorParam === "undefined") {
+        context.varAccessor = new thymol.ThVarsAccessor(context.varStore, "varStore");
+    }
+    context.varNamePrefix = context.varAccessor.arrayName + "[";
+    context.getJSONView = function(param, rootVal) {
+        var pType = typeof param, view = "", objType;
+        if (pType === "string") {
+            view = view + "'" + param + "'";
+        } else if (pType === "number" || pType === "boolean") {
+            view = view + param;
+        } else if (pType === "object") {
+            if (param instanceof Object) {
+                objType = Object.prototype.toString.call(param);
+                if ("[object Array]" === objType) {
+                    view = this.getJSONViewArray(param, false);
+                } else if ("[object Object]" === objType) {
+                    view = this.getJSONViewObject(param, false);
+                }
+                view = "#" + view;
+            }
+        }
+        return view;
+    };
+    context.init = function() {
+        var persisted = thymol.thTop.name, paramRow, paramName, params, i, iLimit, paramValue;
+        if (persisted && persisted !== "") {
+            params = this.javascriptify(persisted);
+            if (params && params.length > 0) {
+                for (i = 0, iLimit = params.length; i < iLimit; i++) {
+                    paramRow = params[i];
+                    if (paramRow) {
+                        paramName = paramRow[0];
+                        if (paramName) {
+                            paramValue = paramRow[1];
+                            this.createVariable(paramName, paramValue);
+                        }
+                    }
+                }
+            }
+        }
+    };
+    context.getJSONViewObject = function(param, rootVal) {
+        var isRoot = true, key = null, view = "{", value, identifier, definition, suffix, instanceNamePrefix, isTaken, i, iLimit, instanceValue;
+        if (typeof rootVal === "boolean") {
+            isRoot = rootVal;
+        }
+        for (key in param) {
+            if (key) {
+                value = param[key];
+                if (typeof value !== "function") {
+                    if (view != "{") {
+                        view = view + ",";
+                    }
+                    identifier = this.getJSONView(key, false);
+                    definition = this.getJSONView(value, false);
+                    view = view + identifier + ":";
+                    if (!isRoot && typeof value === "object") {
+                        suffix = 1;
+                        instanceNamePrefix = key + "$";
+                        instanceName = null;
+                        isTaken = false;
+                        do {
+                            instanceName = instanceNamePrefix + suffix++;
+                            instanceValue = context[instanceName];
+                            if (instanceValue === null || typeof instanceValue === "undefined") {
+                                isTaken = false;
+                                for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
+                                    if (instanceName === varStore[i][0]) {
+                                        isTaken = true;
+                                        break;
+                                    }
+                                }
+                                if (!isTaken) {
+                                    this.addAttribute(instanceName, definition);
+                                }
+                            }
+                        } while (isTaken);
+                        if (instanceName !== null) {
+                            view = view + "#" + instanceName;
+                        }
+                    } else {
+                        view = view + definition;
+                    }
+                }
+            }
+        }
+        view = view + "}";
+        return view;
+    };
+    context.getJSONViewArray = function(param, rootVal) {
+        var view = "[", i;
+        for (i = 0; i < param.length; i++) {
+            view = view + this.getJSONView(param[i], false);
+            if (i < param.length - 1) {
+                view = view + ",";
+            }
+        }
+        view = view + "]";
+        return view;
+    };
+    context.getAttribute = function(name) {
+        return context[name];
+    };
+    context.addAttribute = function(name, value) {
+        var entry = [];
+        entry[0] = name;
+        entry[1] = value;
+        varStore.push(entry);
+    };
+    context.serialise = function() {
+        varStore = [];
+        var serialised = "[", key = null, value, cn, view, name, i, iLimit;
+        for (key in context) {
+            if (key) {
+                value = context[key];
+                if (value != null && typeof value === "object") {
+                    cn = Object.prototype.toString.call(value);
+                    if ("[object Array]" !== cn && !(value instanceof thymol.ThClass) && !(value instanceof thymol.ThVarsAccessor)) {
+                        if (serialised !== "[") {
+                            serialised = serialised + ",";
+                        }
+                        view = this.getJSONView(value, true);
+                        serialised = serialised + "[";
+                        serialised = serialised + '"' + key + '"';
+                        serialised = serialised + ",";
+                        serialised = serialised + '"' + view + '"';
+                        serialised = serialised + "]";
+                    }
+                }
+            }
+        }
+        for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
+            name = varStore[i][0];
+            view = varStore[i][1];
+            serialised = serialised + ",[";
+            serialised = serialised + '"' + name + '"';
+            serialised = serialised + ",";
+            serialised = serialised + '"' + view + '"';
+            serialised = serialised + "]";
+        }
+        serialised = serialised + "]";
+        return serialised;
+    };
+    context.javascriptify = function(fn) {
+        try {
+            return new Function("return " + fn)();
+        } catch (err) {
+            return undefined;
+        }
+    };
+    context.createVariable = function(name, valParam, isReq) {
+        var value = valParam, param, tt, literalBoolean, strValue, initial, existing, newArray;
+        param = value;
+        if (!(value instanceof thymol.ThParam)) {
+            tt = typeof valParam;
+            if (tt !== "function" && tt !== "object") {
+                if (tt === "string") {
+                    try {
+                        value = isReq ? decodeURIComponent(value) : decodeURI(value);
+                    } catch (err) {}
+                }
+                if (tt === "boolean" || tt === "number") {
+                    param = new thymol.ThParam(value);
+                } else if (value || value === "") {
+                    literalBoolean = thymol.ThUtils.testLiteralFalse(value);
+                    if (literalBoolean) {
+                        param = false;
+                    } else {
+                        strValue = new String(value);
+                        initial = strValue.trim();
+                        if (initial.charAt(0) === "#") {
+                            initial = initial.substring(1);
+                            try {
+                                param = this.createJSONVariable(initial);
+                            } catch (err) {
+                                if (err instanceof ReferenceError) {}
+                                if (err instanceof EvalError) {}
+                                if (param == null || isReq) {
+                                    param = new thymol.ThParam(value);
+                                }
+                            }
+                        } else {
+                            param = new thymol.ThParam(strValue.toString());
+                        }
+                    }
+                }
+            }
+        }
+        if (isReq) {
+            existing = context[name];
+            if (typeof existing !== "undefined" && existing !== null) {
+                if (Object.prototype.toString.call(existing) === "[object Array]") {
+                    existing.push(param);
+                } else {
+                    if (thymol.debug) {
+                        thymol.thWindow.alert('request parameters should be of type string array "' + name + '"');
+                    }
+                }
+            } else {
+                newArray = new Array();
+                newArray["class"] = {};
+                newArray["class"]["name"] = "[Thymol.ThParam]";
+                newArray.push(param);
+                context[name] = newArray;
+            }
+        } else {
+            context[name] = param;
+        }
+        return param;
+    };
+    context.createJSONVariable = function(initial) {
+        var current = initial.trim(), parts = " ", substIndex, token, re, vName, obj, result;
+        substIndex = this.varAccessor.length() + 1;
+        while (parts) {
+            parts = current.match(jsonDeclExpr);
+            if (parts && parts.length > 2) {
+                token = parts[2];
+                token = token.replace(/[\']/g, "[']").replace(/[$]/g, "[$]");
+                re = new RegExp(token);
+                vName = this.varNamePrefix + substIndex + "]";
+                obj = new Object();
+                obj.name = parts[2].substring(1);
+                this.varAccessor.set(substIndex, obj);
+                substIndex = substIndex + 1;
+                current = current.replace(re, "'" + vName + "'", "g");
+            }
+        }
+        current = current.replace(/[\']/g, '"');
+        result = $.parseJSON(current);
+        if ("[object Array]" !== Object.prototype.toString.call(result)) {
+            result = new thymol.ThObject(result);
+        }
+        return result;
+    };
+    context.resolveJSONReferences = function() {
+        var key = null, param, prop = null, val, ref, subst, isReq = "request" === this.contextName;
+        for (key in context) {
+            if (key) {
+                param = context[key];
+                if (param != null && typeof param === "object") {
+                    if (!(param instanceof thymol.ThVarsAccessor) && !(param instanceof thymol.ThClass)) {
+                        if (!(param instanceof thymol.ThParam)) {
+                            if (isReq && Object.prototype.toString.call(param) === "[object Array]") {
+                                for (var i = 0, iLimit = param.length; i < iLimit; i++) {
+                                    var pi = param[i];
+                                    if (!!pi && typeof pi.value === "string" && pi.value.charAt(0) == "#") {
+                                        var pv = thymol.ThUtils.getParameter(pi.value.substring(1));
+                                        param[i] = pv;
+                                    }
+                                }
+                            } else {
+                                for (prop in param) {
+                                    if (prop) {
+                                        val = param[prop];
+                                        if (typeof val === "string") {
+                                            if (val.indexOf(this.varNamePrefix) == 0) {
+                                                subst = null;
+                                                if (prop.match(/\d*/)) {
+                                                    ref = val.substring(this.varNamePrefix.length, val.length - 1);
+                                                    ref = this.varAccessor.get(ref);
+                                                    subst = context[ref.name];
+                                                } else {
+                                                    subst = context[prop];
+                                                }
+                                                param[prop] = subst;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        } else if (typeof param.value === "string" && param.value.charAt(0) == "#") {
+                            subst = context[param.value.substring(1)];
+                            context[key] = subst;
+                        }
+                    }
+                }
+            }
+        }
+    };
+    return context;
+};
+
+thymol.ThUtils = function() {
+    function mergeVars(thiz, other) {
+        var current = thiz, prop = null;
+        if (!current) {
+            current = {};
+        }
+        for (prop in other) {
+            if (other.hasOwnProperty(prop)) {
+                if (prop) {
+                    if (!current[prop]) {
+                        current[prop] = other[prop];
+                    }
+                }
+            }
+        }
+        return current;
+    }
+    function processElement(func, element, arg, obj) {
+        var result = null, parent = element.parentElement;
+        if (!thymol.isFragmentChild(element)) {
+            if (!element.thObjectVar) {
+                parent = element.parentElement;
+                while (parent) {
+                    if (parent.thObjectVar) {
+                        element.thObjectVar = parent.thObjectVar;
+                        break;
+                    }
+                    parent = parent.parentElement;
+                }
+            }
+            parent = element.parentElement;
+            while (parent) {
+                if (parent.thLocalVars) {
+                    element.thLocalVars = mergeVars(element.thLocalVars, parent.thLocalVars);
+                    break;
+                }
+                parent = parent.parentElement;
+            }
+            result = func(element, arg, obj);
+        }
+        return result;
+    }
+    function unQuote(param) {
+        var par = param, pared;
+        if (par) {
+            if (typeof par === "string") {
+                par = par.trim();
+                if (par.charAt(0) == '"') {
+                    if (par.charAt(par.length - 1) == '"') {
+                        pared = par.substring(1, par.length - 1);
+                        if (pairParity(pared, '"', '"') == 0) {
+                            par = pared;
+                        }
+                    }
+                } else if (par.charAt(0) == "'") {
+                    if (par.charAt(par.length - 1) == "'") {
+                        pared = par.substring(1, par.length - 1);
+                        if (pairParity(pared, "'", "'") == 0) {
+                            par = pared;
+                        }
+                    }
+                }
+            }
+        }
+        return par;
+    }
+    function unParenthesise(param) {
+        var par = param, pared;
+        if (par) {
+            if (typeof par === "string") {
+                par = par.trim();
+                if (par.charAt(0) == "(") {
+                    if (par.charAt(par.length - 1) == ")") {
+                        pared = par.substring(1, par.length - 1).trim();
+                        if (pairParity(pared, "(", ")") == 0) {
+                            par = pared;
+                        }
+                    }
+                }
+            }
+        }
+        return par;
+    }
+    function pairParity(str, left, right) {
+        var i, ch, strLength = str.length, parity = 0;
+        for (i = 0; i < strLength; i++) {
+            ch = str.charAt(i);
+            if (ch == left) {
+                parity++;
+            } else if (ch == right) {
+                parity--;
+                if (parity < 0) {
+                    break;
+                }
+            }
+        }
+        return parity;
+    }
+    function unBracket(param) {
+        var par = param, pared;
+        if (typeof par === "string") {
+            par = par.trim();
+        }
+        if (par) {
+            if (par.charAt(0) == "[") {
+                if (par.charAt(par.length - 1) == "]") {
+                    pared = par.substring(1, par.length - 1);
+                    if (pairParity(pared, "[", "]") == 0) {
+                        par = pared;
+                    }
+                }
+            }
+        }
+        return par;
+    }
+    function getToPrecision(n, p) {
+        if (typeof p === "undefined") {
+            return n;
+        }
+        var up = thymol.thDefaultPrecision, ndp = 0, s, sl, dp, v;
+        if (p > up) {
+            up = p;
+        } else {
+            s = n.toString();
+            sl = s.length;
+            dp = s.indexOf(".");
+            if (dp >= 0) {
+                ndp = sl - 1 - dp;
+            }
+            if (ndp > up) {
+                v = n.toPrecision(ndp + 1);
+                v = truncateDecimals(v);
+                s = v.toString();
+                sl = s.length;
+                if (dp >= 0) {
+                    ndp = sl - 1 - dp;
+                }
+            }
+            if (p > ndp) {
+                up = p;
+            } else if (ndp < up) {
+                up = ndp;
+            }
+        }
+        v = parseFloat(n);
+        v = v.toFixed(up);
+        if (p === 0) {
+            v = Number(v);
+        }
+        return v;
+    }
+    function truncateDecimals(valp) {
+        var val = valp, iLimit = valp.length - 1, i;
+        for (i = iLimit; i >= 0; i--) {
+            if (val.charAt(i) === "0") {
+                val = val.substr(0, i);
+            } else {
+                break;
+            }
+        }
+        return val;
+    }
+    function getDecimalDigits(val) {
+        var digits = 0, s, dp;
+        s = val.toString();
+        dp = s.indexOf(".") + 1;
+        if (dp > 0) {
+            digits = s.length - dp;
+        }
+        return digits;
+    }
+    function testLiteralFalse(initial) {
+        var result = false, val;
+        if (typeof initial === "string") {
+            val = initial.toLowerCase();
+            result = val == "false" || val == "off" || val == "no";
+        } else if (typeof initial === "boolean") {
+            result = !initial;
+        }
+        return result;
+    }
+    function renderMessage(msg, values) {
+        var result = msg, i, iLimit;
+        if (Object.prototype.toString.call(values) == "[object Array]") {
+            for (i = 0, iLimit = values.length; i < iLimit; i++) {
+                result = renderMessageArg(result, i, values[i]);
+            }
+        } else {
+            result = renderMessageArg(msg, 0, values);
+        }
+        return result;
+    }
+    function renderMessageArg(msg, index, value) {
+        var result = msg, splits, i, iLimit, iUpper;
+        splits = msg.split("{" + index + "}");
+        if (splits.length > 0) {
+            result = "";
+            for (i = 0, iLimit = splits.length, iUpper = iLimit - 1; i < iLimit; i++) {
+                result += splits[i];
+                if (i < iUpper) {
+                    result += value;
+                }
+            }
+        }
+        return result;
+    }
+    function getParameter(name) {
+        var result, tor;
+        result = thymol.requestContext[name];
+        tor = typeof result;
+        if (tor === "undefined") {
+            result = thymol.sessionContext[name];
+            if (typeof result === "undefined") {
+                result = thymol.applicationContext[name];
+            }
+        } else if (tor === "object") {
+            if (Object.prototype.toString.call(result) === "[object Array]") {
+                if (result.length === 1) {
+                    result = result[0];
+                }
+            }
+        }
+        return result;
+    }
+    function charOcurrences(str, chr) {
+        var count = 0, i = 0, iLimit = str.length;
+        for (;i < iLimit; i++) {
+            if (str.charAt(i) === chr) {
+                count++;
+            }
+        }
+        return count;
+    }
+    function isLiteral(val) {
+        var first, last;
+        if (typeof val === "string") {
+            first = val.charAt(0);
+            last = val.charAt(val.length - 1);
+            if (first == "'" && last == "'") {
+                return true;
+            }
+            if (first == '"' && last == '"') {
+                return true;
+            }
+        }
+        return false;
+    }
+    function isLiteralSubst(param) {
+        var result = false, par = param;
+        if (typeof par === "string") {
+            par = par.trim();
+        }
+        if (par) {
+            if (par.charAt(0) == "|") {
+                if (par.charAt(par.length - 1) == "|") {
+                    result = true;
+                }
+            }
+        }
+        return result;
+    }
+    function loadScript(file) {
+        var script = thymol.Thymol.prototype.getFilePath(file);
+        var status = "";
+        var jqxhr = $.ajax({
+            type: "GET",
+            url: script,
+            dataType: "script",
+            cache: true,
+            async: false
+        }).done(function() {
+            status = "success";
+        }).fail(function() {
+            status = "error";
+        });
+    }
+    function unescape(text) {
+        var result = text, i, iLimit, iUpper, c, cc;
+        if (text !== null && typeof text !== "undefined") {
+            result = "";
+            iLimit = text.length;
+            iUpper = iLimit - 3;
+            for (i = 0; i < iLimit; i++) {
+                c = text.charAt(i);
+                if (i < iUpper) {
+                    if (c === "&") {
+                        cc = text.charAt(i + 1).toLowerCase();
+                        if ((cc === "g" || cc === "l") && text.charAt(i + 2).toLowerCase() === "t" && text.charAt(i + 3) === ";") {
+                            i += 3;
+                            if (cc === "g") {
+                                c = ">";
+                            } else {
+                                c = "<";
+                            }
+                        } else if (i < iUpper - 1 && cc === "a" && text.charAt(i + 2).toLowerCase() === "m" && text.charAt(i + 3).toLowerCase() === "p" && text.charAt(i + 4) === ";") {
+                            i += 4;
+                        } else if (i < iUpper - 2) {
+                            if (cc === "q" && text.charAt(i + 2).toLowerCase() === "u" && text.charAt(i + 3).toLowerCase() === "o" && text.charAt(i + 4).toLowerCase() === "t" && text.charAt(i + 5) === ";") {
+                                i += 5;
+                                c = '"';
+                            } else if (cc === "a" && text.charAt(i + 2).toLowerCase() === "p" && text.charAt(i + 3).toLowerCase() === "o" && text.charAt(i + 4).toLowerCase() === "s" && text.charAt(i + 5) === ";") {
+                                i += 5;
+                                c = "'";
+                            }
+                        }
+                    }
+                }
+                result += c;
+            }
+        }
+        return result;
+    }
+    function unicodeUnescape(initial) {
+        var result = initial.replace(/\\u([\da-f]{4})/gi, function(match, grp) {
+            return String.fromCharCode(parseInt(grp, 16));
+        });
+        result = unescape(result);
+        return result;
+    }
+    function removeTag(element) {
+        var parent = element.parentNode, i, iLimit, savedObject = element.thObjectVar, savedLocals = element.thLocalVars;
+        if (!!parent) {
+            for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
+                var newNode = element.childNodes[i].cloneNode(true);
+                if (newNode.nodeType === 1) {
+                    if (!!savedObject) {
+                        newNode.thObjectVar = savedObject;
+                    }
+                    if (!!savedLocals) {
+                        newNode.thLocalVars = savedLocals;
+                    }
+                }
+                parent.insertBefore(newNode, element);
+            }
+            parent.removeChild(element);
+        }
+    }
+    function getRequestEncoded(initial) {
+        var result = initial;
+        result = encodeURIComponent(result);
+        result = result.replace(/%20/g, "+");
+        result = result.replace(/%26/g, "&");
+        result = result.replace(/%3A/g, ":");
+        result = result.replace(/!/g, "%21");
+        result = result.replace(/'/g, "%27");
+        result = result.replace(/\(/g, "%28");
+        result = result.replace(/\)/g, "%29");
+        result = result.replace(/\*/g, "%2A");
+        result = result.replace(/~/g, "%7E");
+        return result;
+    }
+    return {
+        getParameter: getParameter,
+        processElement: processElement,
+        unQuote: unQuote,
+        unParenthesise: unParenthesise,
+        unBracket: unBracket,
+        getToPrecision: getToPrecision,
+        getDecimalDigits: getDecimalDigits,
+        testLiteralFalse: testLiteralFalse,
+        renderMessage: renderMessage,
+        charOcurrences: charOcurrences,
+        isLiteral: isLiteral,
+        isLiteralSubst: isLiteralSubst,
+        loadScript: loadScript,
+        unescape: unescape,
+        unicodeUnescape: unicodeUnescape,
+        removeTag: removeTag,
+        getRequestEncoded: getRequestEncoded
+    };
+}();
+
+thymol.ThParser = function(scope) {
+    function object(o) {
+        function F() {}
+        F.prototype = o;
+        return new F();
+    }
+    function NullReturn(varName) {
+        this.varName = varName;
+    }
+    var TNUMBER = 0;
+    var TOP1 = 1;
+    var TOP2 = 2;
+    var TVAR = 3;
+    var TFUNCALL = 4;
+    var MSGSUBST = 5;
+    var ARGLIST = 6;
+    function Token(type_p, index_p, prio_p, number_p, mode_p, meta_p) {
+        this.type_ = type_p;
+        this.index_ = index_p || 0;
+        this.prio_ = prio_p || 0;
+        this.number_ = number_p !== undefined && number_p !== null ? number_p : 0;
+        this.mode_ = mode_p !== undefined && mode_p !== null ? mode_p : 0;
+        this.meta_ = meta_p;
+        this.toString = function() {
+            switch (this.type_) {
+              case TNUMBER:
+                return this.number_;
+
+              case TOP1:
+              case TOP2:
+              case TVAR:
+                return this.index_;
+
+              case TFUNCALL:
+              case MSGSUBST:
+              case ARGLIST:
+                return "CALL";
+
+              default:
+                return "Invalid Token";
+            }
+        };
+    }
+    function Expression(tokens, ops1, ops2, functions, precision, position) {
+        this.tokens = tokens;
+        this.ops1 = ops1;
+        this.ops2 = ops2;
+        this.functions = functions;
+        this.precision = precision;
+        this.position = position;
+    }
+    Expression.prototype = {
+        simplify: function(valuesParam) {
+            var values = valuesParam || {};
+            var nstack = [];
+            var newexpression = [];
+            var n1;
+            var n2;
+            var f;
+            var L = this.tokens.length;
+            var item;
+            var i = 0;
+            for (i = 0; i < L; i++) {
+                item = this.tokens[i];
+                var type_ = item.type_;
+                if (type_ === TNUMBER) {
+                    nstack.push(item);
+                } else if (type_ === TVAR && !(item.index_ in new Object()) && item.index_ in values) {
+                    item = new Token(TNUMBER, 0, 0, values[item.index_]);
+                    nstack.push(item);
+                } else if (type_ === TOP2 && nstack.length > 1) {
+                    f = this.ops2[item.index_];
+                    if (!!f) {
+                        n2 = nstack.pop();
+                        n1 = nstack.pop();
+                        item = new Token(TNUMBER, 0, 0, f(n1.number_, n2.number_));
+                    }
+                    nstack.push(item);
+                } else if (type_ === TOP1 && nstack.length > 0) {
+                    if ("{" == item.index_) {
+                        if (item.mode_ == 2) {
+                            nstack.push(item);
+                        }
+                    } else {
+                        n1 = nstack.pop();
+                        f = this.ops1[item.index_];
+                        item = new Token(TNUMBER, 0, 0, f(n1.number_));
+                        nstack.push(item);
+                    }
+                } else {
+                    while (nstack.length > 0) {
+                        newexpression.push(nstack.shift());
+                    }
+                    newexpression.push(item);
+                }
+            }
+            while (nstack.length > 0) {
+                newexpression.push(nstack.shift());
+            }
+            var res = new Expression(newexpression, object(this.ops1), object(this.ops2), object(this.functions), this.precision);
+            return res;
+        },
+        evaluate: function(element) {
+            var nstack = [];
+            var n1;
+            var n2;
+            var f;
+            var res = null;
+            var L = this.tokens.length;
+            var item;
+            var i = 0;
+            var result;
+            for (i = 0; i < L; i++) {
+                item = this.tokens[i];
+                if (i === 0 && thymol.disableMessages && item.mode_ === 4) {
+                    var nullReturn = new thymol.ThClass();
+                    nullReturn.abort = true;
+                    return nullReturn;
+                }
+                var type_ = item.type_;
+                if (type_ === TNUMBER) {
+                    nstack.push(item.number_);
+                    if (i == L - 1) {
+                        break;
+                    }
+                } else if (type_ === TOP2) {
+                    n2 = nstack.pop();
+                    if (typeof n2 === "undefined" || n2 instanceof NullReturn) {
+                        n2 = null;
+                    }
+                    n1 = nstack.pop();
+                    if (typeof n1 === "undefined" || n1 instanceof NullReturn) {
+                        n1 = null;
+                    }
+                    f = this.ops2[item.index_];
+                    var pathMatch = false;
+                    try {
+                        if (item.mode_ === 6) {
+                            if (f === dot) {
+                                res = n1 + "[" + n2 + "]";
+                            } else if (f === append) {
+                                if (!!item.meta_) {
+                                    if (!!item.meta_.paths) {
+                                        var values = item.meta_.paths[n1];
+                                        if (!!values) {
+                                            values.push(n2);
+                                            pathMatch = true;
+                                            res = null;
+                                        }
+                                    }
+                                }
+                                if (!pathMatch) {
+                                    if (!item.meta_) {
+                                        item.meta_ = {};
+                                    }
+                                    if (!item.meta_.params) {
+                                        item.meta_.params = [];
+                                    }
+                                    var values = item.meta_.params[n1];
+                                    if (!values) {
+                                        values = [];
+                                        item.meta_.params[n1] = values;
+                                    }
+                                    values.push(n2);
+                                    pathMatch = true;
+                                }
+                            } else {
+                                res = n2;
+                                nstack.push(n1);
+                            }
+                        } else {
+                            if (f === dot && "class" === n2 && !!n1 && !n1["class"]) {
+                                var tn2 = typeof n2;
+                                if (tn2 === "object" && n2 instanceof thymol.ThParam) {
+                                    res = f(n1, n2);
+                                } else {
+                                    res = new thymol.ThClass("JavaScript:" + tn2);
+                                }
+                            } else {
+                                res = f(n1, n2);
+                                if (typeof res === "function") {
+                                    if (L - 1 > i) {
+                                        next = this.tokens[i + 1];
+                                        if (next.type_ === TNUMBER && Object.prototype.toString.call(next.number_) == "[object Array]" && next.number_.length == 0) {
+                                            i += 1;
+                                            nstack.push(res);
+                                            n1.isDirect = true;
+                                            res = n1;
+                                        }
+                                    }
+                                }
+                            }
+                            if (f !== append) {
+                                if (Object.prototype.toString.call(res) == "[object Array]") {
+                                    res.arrayResult = true;
+                                }
+                            }
+                        }
+                    } catch (err) {
+                        if (!element.isBlockChild) {
+                            var aValue = n1 == null ? "null" : n1;
+                            var bValue = n2 == null ? "null" : n2;
+                            var message = "while evaluating expression: " + this.tokens[i - 2].index_ + ": " + aValue + ", " + this.tokens[i - 1].index_ + ": " + bValue;
+                            throw new thymol.ThError(message, element, err);
+                        }
+                    }
+                    if (!pathMatch) {
+                        nstack.push(res);
+                    }
+                } else if (type_ === TVAR) {
+                    var next = null, pushed = nstack.length;
+                    if (item.index_ != null) {
+                        if (L - 1 > i) {
+                            next = this.tokens[i + 1];
+                            if (next.type_ === TOP2 && next.index_ === ".") {
+                                nstack.push(item.index_);
+                            }
+                        }
+                        if (pushed === nstack.length) {
+                            var val = thymol.substituteParam(item.index_, item.mode_, element);
+                            if (Object.prototype.toString.call(val) == "[object Array]") {
+                                val.arrayResult = true;
+                            }
+                            this.updatePrecision(val);
+                            if (val === null) {
+                                val = new NullReturn(item.index_);
+                            }
+                            nstack.push(val);
+                        }
+                    } else if (pushed === nstack.length && item.index_ in this.functions) {
+                        nstack.push(this.functions[item.index_]);
+                    } else {
+                        if (!element.isBlockChild) {
+                            throw new thymol.ThError("Exception undefined variable: " + item.index_, element);
+                        }
+                    }
+                } else if (type_ === TOP1) {
+                    n1 = nstack.pop();
+                    if (typeof n1 === "undefined" || n1 instanceof NullReturn) {
+                        if (item.mode_ === 2) {
+                            n1 = "";
+                        } else {
+                            n1 = null;
+                        }
+                    }
+                    res = n1;
+                    if ("{" === item.index_) {
+                        var prev = this.tokens[i - 1];
+                        if (prev.mode_ == 7) {
+                            if (thymol.conversionService) {
+                                n1 = thymol.conversionService(n1);
+                                res = n1;
+                            }
+                        }
+                        if (typeof n1 === "string") {
+                            if (item.mode_ === 2) {
+                                res = thymol.getStandardURL(n1);
+                            } else {
+                                var subst = thymol.substituteParam(n1, item.mode_, element);
+                                if (subst != null) {
+                                    this.updatePrecision(subst);
+                                    res = subst;
+                                }
+                            }
+                        }
+                    } else {
+                        f = this.ops1[item.index_];
+                        try {
+                            res = f(n1);
+                        } catch (err) {
+                            if (!element.isBlockChild) {
+                                var aValue = n1 == null ? "null" : n1;
+                                var message = "while evaluating expression: " + this.tokens[i - 2].index_ + ": " + aValue;
+                                throw new thymol.ThError(message, element, err);
+                            }
+                        }
+                    }
+                    if (Object.prototype.toString.call(res) == "[object Array]") {
+                        res.arrayResult = true;
+                    }
+                    nstack.push(res);
+                } else if (type_ === TFUNCALL || type_ === MSGSUBST || type_ === ARGLIST) {
+                    n1 = nstack.pop();
+                    f = nstack.pop();
+                    if (type_ === MSGSUBST) {
+                        if (f instanceof NullReturn) {
+                            res = "??" + f.varName + "_" + thymol.locale.value + "??";
+                        } else {
+                            res = thymol.ThUtils.renderMessage(f, n1);
+                        }
+                        nstack.push(res);
+                    } else if (type_ === ARGLIST) {
+                        var pathMatch = false;
+                        n2 = nstack.pop();
+                        if (typeof n2 === "undefined") {
+                            n2 = f;
+                            f = n1;
+                            n1 = "";
+                        }
+                        if (!!item.meta_) {
+                            if (!!item.meta_.paths) {
+                                var values = item.meta_.paths[f];
+                                if (!!values) {
+                                    values.push(n1);
+                                    pathMatch = true;
+                                }
+                                for (var j in item.meta_.paths) {
+                                    if (item.meta_.paths.hasOwnProperty(j)) {
+                                        var values = item.meta_.paths[j];
+                                        var isReq = n2.indexOf("?") >= 0;
+                                        if (!!values && values.length > 0) {
+                                            var pathVar = "{" + j + "}";
+                                            var repReg = new RegExp(pathVar, "g");
+                                            var rep = "";
+                                            values.reverse();
+                                            for (var k = 0, kLimit = values.length; k < kLimit; k++) {
+                                                if (rep.length > 0) {
+                                                    rep = rep + ",";
+                                                }
+                                                if (isReq) {
+                                                    rep = rep + thymol.ThUtils.getRequestEncoded(values[k]);
+                                                } else {
+                                                    rep = rep + encodeURIComponent(values[k]);
+                                                }
+                                            }
+                                            n2 = n2.replace(repReg, rep);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (pathMatch) {
+                            res = n2;
+                        } else {
+                            if (typeof f === "undefined" || f instanceof NullReturn) {
+                                f = "";
+                            } else {
+                                f = f.toString();
+                            }
+                            f = thymol.ThUtils.getRequestEncoded(f);
+                            f = "?" + f;
+                            n1 = n1.toString();
+                            if (f != "?" && n1 != "") {
+                                f = f + "=";
+                            }
+                            if (n1 != "") {
+                                n1 = thymol.ThUtils.getRequestEncoded(n1);
+                                f = f + n1;
+                            }
+                            if (typeof n2 === "undefined" || n2 instanceof NullReturn) {
+                                n2 = "";
+                            } else {
+                                n2 = n2.toString();
+                            }
+                            res = n2 + f;
+                        }
+                        if (!!item.meta_) {
+                            var separator = res.indexOf("?") >= 0 ? "&" : "?";
+                            for (var j in item.meta_.params) {
+                                if (item.meta_.params.hasOwnProperty(j)) {
+                                    var values = item.meta_.params[j];
+                                    if (!!values && values.length > 0) {
+                                        for (var k = 0, kLimit = values.length; k < kLimit; k++) {
+                                            res = res + separator + thymol.ThUtils.getRequestEncoded(j) + "=" + thymol.ThUtils.getRequestEncoded(values[k]);
+                                            if (k == 0) {
+                                                separator = "&";
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                            if (!!item.meta_.urlFragment) {
+                                res = res + item.meta_.urlFragment;
+                            }
+                        }
+                        nstack.push(res);
+                    } else if (f.apply && f.call) {
+                        if (!!n1 && !!n1.isDirect) {
+                            res = f.call(n1);
+                        } else {
+                            if (n1 instanceof NullReturn) {
+                                n1 = null;
+                            }
+                            if (n1 != null && (n1.arrayResult || Object.prototype.toString.call(n1) !== "[object Array]")) {
+                                res = f.call(element, n1);
+                            } else {
+                                res = f.apply(element, n1);
+                            }
+                        }
+                        if (res instanceof String) {
+                            if (res.precision) {
+                                if (typeof this.precision === "undefined" || res.precision > this.precision) {
+                                    this.precision = res.precision;
+                                }
+                            }
+                            res = res.toString();
+                        } else if (Object.prototype.toString.call(res) == "[object Array]") {
+                            res.arrayResult = true;
+                        }
+                        nstack.push(res);
+                    } else {
+                        if (!element.isBlockChild) {
+                            throw new thymol.ThError(f + " is not a function", element);
+                        }
+                    }
+                } else {
+                    if (!element.isBlockChild) {
+                        throw new thymol.ThError("invalid expression item type: " + type_, element);
+                    }
+                }
+            }
+            if (nstack.length > 1) {
+                if (!element.isBlockChild) {
+                    throw new thymol.ThError("invalid Expression (parity)", element);
+                }
+            }
+            result = nstack[0];
+            return result;
+        },
+        updatePrecision: function(val) {
+            if (typeof val === "number") {
+                var p = thymol.ThUtils.getDecimalDigits(val);
+                if (typeof this.precision === "undefined" || p > this.precision) {
+                    this.precision = p;
+                }
+            }
+        }
+    };
+    function add(a, b) {
+        return a + b;
+    }
+    function assign(a) {
+        return a;
+    }
+    function sub(a, b) {
+        return a - b;
+    }
+    function mul(a, b) {
+        return a * b;
+    }
+    function div(a, b) {
+        return a / b;
+    }
+    function mod(a, b) {
+        return a % b;
+    }
+    function concat(a, b) {
+        return "" + a + b;
+    }
+    function neg(a) {
+        return -a;
+    }
+    function not(a) {
+        var v = thymol.getBooleanValue(a);
+        return !v;
+    }
+    function random(a) {
+        return Math.random() * (a || 1);
+    }
+    function fac(a) {
+        var aa = Math.floor(a);
+        var b = aa;
+        while (aa > 1) {
+            b = b * --aa;
+        }
+        return b;
+    }
+    function append(a, b) {
+        if (a != null) {
+            if (a.arrayResult === true || Object.prototype.toString.call(a) != "[object Array]") {
+                return [ a, b ];
+            }
+        } else {
+            if (b != null) {
+                if (b.arrayResult === true || Object.prototype.toString.call(b) != "[object Array]") {
+                    return [ a, b ];
+                }
+                return b;
+            }
+            return null;
+        }
+        var aa = a.slice();
+        aa.push(b);
+        return aa;
+    }
+    function equal(a, b) {
+        return a == b;
+    }
+    function notEqual(a, b) {
+        return a != b;
+    }
+    function gt(a, b) {
+        return a > b;
+    }
+    function ge(a, b) {
+        return a >= b;
+    }
+    function lt(a, b) {
+        return a < b;
+    }
+    function le(a, b) {
+        return a <= b;
+    }
+    function and(a, b) {
+        return a && b;
+    }
+    function or(a, b) {
+        return a || b;
+    }
+    function dot(a, b) {
+        return a[b];
+    }
+    function binary(a, b) {
+        return a ? b : null;
+    }
+    function elvis(a, b) {
+        return a != null ? a : b;
+    }
+    function getStr(pos, expression, mode, partial, preprocessed) {
+        var localMode = mode;
+        var s = "";
+        var c = expression.charAt(pos);
+        var start = pos + 1;
+        var end = expression.length;
+        var stopChar = c;
+        if (localMode === 4 || c === "#") {
+            stopChar = "}";
+            localMode = 4;
+        }
+        var i = start;
+        var inCurly = false;
+        var curlyPos = null;
+        var urlFragPos = -1;
+        var meta = null;
+        if (localMode !== 4 && c !== "'" && c !== '"') {
+            for (;i <= end; i++) {
+                if (c.toUpperCase() === c.toLowerCase()) {
+                    if (c === "{") {
+                        inCurly = true;
+                        curlyPos = i;
+                        if (meta === null) {
+                            meta = {};
+                            meta.paths = [];
+                        }
+                    } else if (mode === 2 && c === "#") {
+                        urlFragPos = i;
+                    }
+                    if (i === pos || !inCurly && c === "}" || c !== "_" && c !== "?" && c !== ":" && (c < "0" || c > "9")) {
+                        if (!(partial && c == "-") && !((mode === 2 || mode === 6) && (c === "/" || c === "." || c === "~" || c === "?" || c === "=" || c === ":" || c === "-" || c === "_" || c === "[" || c === "]" || c === "#" || inCurly && c === "{" || inCurly && c === "}")) || mode === 6 && c === "=") {
+                            i = i - 1;
+                            break;
+                        }
+                    }
+                    if (inCurly && c === "}") {
+                        inCurly = false;
+                        if (meta === null) {
+                            var message = 'bad path variable definition in expression: "' + expression + '" near column ' + pos;
+                            throw new thymol.ThError(message, element);
+                        }
+                        var curlyVar = expression.substring(curlyPos, i - 1);
+                        var values = [];
+                        meta.paths[curlyVar] = values;
+                    }
+                }
+                s += c;
+                c = expression.charAt(i);
+            }
+            if (urlFragPos >= 0) {
+                var urlFrag = expression.substring(urlFragPos - 1, i);
+                s = s.substring(0, s.length - urlFrag.length);
+                if (meta === null) {
+                    meta = {};
+                    meta.urlFragment = urlFrag;
+                }
+            }
+        } else {
+            var quoted = false;
+            var preprocessing = false;
+            if (c === "'" || c === '"') {
+                quoted = true;
+                stopChar = c;
+            }
+            while (i <= end) {
+                if (c === stopChar && i > start && !preprocessing) {
+                    if (localMode !== 4 || quoted) {
+                        s += c;
+                    } else {
+                        i = i - 1;
+                    }
+                    break;
+                }
+                var nc = expression.charAt(i);
+                if (c === "_" && nc === "_" && !preprocessed) {
+                    preprocessing = !preprocessing;
+                }
+                if (c === "\\") {
+                    if (nc === "'" && s.charAt(s.length - 1) !== "\\") {
+                        c = "&#39;";
+                        if (i + 1 > end) {
+                            break;
+                        }
+                        i = i + 1;
+                        nc = expression.charAt(i);
+                    }
+                }
+                if (!quoted) {
+                    if (c === ".") {
+                        var exp = thymol.thExpressionObjects[s];
+                        if (typeof exp !== "undefined" && exp !== null) {
+                            i -= 1;
+                            break;
+                        }
+                    }
+                    if (c === "(") {
+                        i -= 1;
+                        break;
+                    }
+                }
+                s += c;
+                if (i + 1 > end) {
+                    break;
+                }
+                i = i + 1;
+                c = nc;
+            }
+        }
+        var str = new Object();
+        str.str = s;
+        str.pos = i;
+        if (meta !== null) {
+            str.meta = meta;
+        }
+        return str;
+    }
+    function ThParser() {
+        this.precision;
+        this.success = false;
+        this.errormsg = "";
+        this.expression = "";
+        this.pos = 0;
+        this.tokennumber = 0;
+        this.tokenprio = 0;
+        this.tokenindex = 0;
+        this.tmpprio = 0;
+        this.ops1 = {
+            sin: Math.sin,
+            cos: Math.cos,
+            tan: Math.tan,
+            asin: Math.asin,
+            acos: Math.acos,
+            atan: Math.atan,
+            sqrt: Math.sqrt,
+            log: Math.log,
+            abs: Math.abs,
+            ceil: Math.ceil,
+            floor: Math.floor,
+            round: Math.round,
+            "-": neg,
+            "!": not,
+            not: not,
+            exp: Math.exp,
+            "=": assign
+        };
+        this.ops2 = {
+            "?": binary,
+            ":": elvis,
+            "?:": elvis,
+            "+": add,
+            "-": sub,
+            "*": mul,
+            "/": div,
+            "%": mod,
+            "^": Math.pow,
+            ",": append,
+            "||": concat,
+            "==": equal,
+            eq: equal,
+            "!=": notEqual,
+            ne: notEqual,
+            neq: notEqual,
+            div: div,
+            mod: mod,
+            and: and,
+            or: or,
+            ">": gt,
+            gt: gt,
+            ">=": ge,
+            "=>": ge,
+            ge: ge,
+            "<": lt,
+            lt: lt,
+            "<=": le,
+            "=<": le,
+            le: le,
+            ".": dot,
+            "[": dot
+        };
+        this.functions = {
+            random: random,
+            fac: fac,
+            min: Math.min,
+            max: Math.max,
+            pow: Math.pow
+        };
+        this.consts = {
+            E: Math.E,
+            PI: Math.PI
+        };
+    }
+    ThParser.parse = function(expr, partial, preprocessed) {
+        return new thymol.ThParser().parse(expr, partial, preprocessed);
+    };
+    ThParser.evaluate = function(expr, partial, element) {
+        return thymol.ThParser.parse(expr, partial, false).evaluate(element);
+    };
+    ThParser.Expression = Expression;
+    ThParser.values = {
+        sin: Math.sin,
+        cos: Math.cos,
+        tan: Math.tan,
+        asin: Math.asin,
+        acos: Math.acos,
+        atan: Math.atan,
+        sqrt: Math.sqrt,
+        log: Math.log,
+        abs: Math.abs,
+        ceil: Math.ceil,
+        floor: Math.floor,
+        round: Math.round,
+        random: random,
+        fac: fac,
+        exp: Math.exp,
+        min: Math.min,
+        max: Math.max,
+        pow: Math.pow,
+        E: Math.E,
+        PI: Math.PI
+    };
+    var PRIMARY = 1 << 0;
+    var OPERATOR = 1 << 1;
+    var FUNCTION = 1 << 2;
+    var LPAREN = 1 << 3;
+    var RPAREN = 1 << 4;
+    var COMMA = 1 << 5;
+    var SIGN = 1 << 6;
+    var CALL = 1 << 7;
+    var NULLARY_CALL = 1 << 8;
+    var LBRACK = 1 << 9;
+    var RBRACK = 1 << 10;
+    var LVARBRK = 1 << 11;
+    var RVARBRK = 1 << 11;
+    var OPTION = 1 << 12;
+    var ASSIGN = 1 << 13;
+    ThParser.prototype = {
+        parse: function(expr, partial, preprocessed) {
+            this.errormsg = "";
+            this.success = true;
+            var operstack = [];
+            var tokenstack = [];
+            var modestack = [];
+            this.tmpprio = 0;
+            var expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | OPERATOR | SIGN | OPTION;
+            var noperators = 0;
+            this.expression = expr;
+            this.pos = 0;
+            this.mode = 0;
+            while (this.pos < this.expression.length) {
+                if (this.isWhite()) {} else if (this.isOperator()) {
+                    if (this.isSign() && expected & SIGN) {
+                        if (this.isNegativeSign()) {
+                            this.tokenprio = 6;
+                            this.tokenindex = "-";
+                            noperators++;
+                            this.addfunc(tokenstack, operstack, TOP1);
+                        }
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                    } else if (this.isAssign() && expected & ASSIGN) {
+                        noperators++;
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                    } else if (this.isComment()) {} else {
+                        if (this.tokenindex == "!") {
+                            if ((expected & SIGN) === 0) {
+                                this.error_parsing(this.pos, "unexpected sign");
+                            }
+                            noperators += 1;
+                            this.addfunc(tokenstack, operstack, TOP1);
+                        } else {
+                            if ((expected & OPERATOR) === 0) {
+                                this.error_parsing(this.pos, "unexpected operator");
+                            }
+                            noperators += 2;
+                            this.addfunc(tokenstack, operstack, TOP2);
+                        }
+                        if (this.expression.charAt(this.pos - 1) === "[") {
+                            this.tmpprio += 20;
+                        }
+                        expected = PRIMARY | OPERATOR | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                    }
+                } else if (this.isNumber()) {
+                    if ((expected & PRIMARY) === 0) {
+                        this.error_parsing(this.pos, "unexpected number");
+                    }
+                    var token = new Token(TNUMBER, 0, 0, this.tokennumber);
+                    tokenstack.push(token);
+                    expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA;
+                } else if (this.isLeftParenth()) {
+                    if ((expected & LPAREN) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "("');
+                    }
+                    modestack.push(this.mode);
+                    if (expected & CALL) {
+                        noperators += 2;
+                        this.tokenprio = -2;
+                        this.tokenindex = -1;
+                        this.tmpprio += 2;
+                        var ft = TFUNCALL;
+                        if (this.mode === 4) {
+                            ft = MSGSUBST;
+                            this.mode = 5;
+                        } else if (this.mode === 2) {
+                            ft = ARGLIST;
+                            this.mode = 6;
+                            var url = tokenstack[tokenstack.length - 1];
+                            if (!url.meta_) {
+                                url.meta_ = {};
+                            }
+                            this.meta = url.meta_;
+                        } else {
+                            this.mode = 5;
+                        }
+                        this.addfunc(tokenstack, operstack, ft);
+                        this.tmpprio -= 2;
+                    }
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio += 10;
+                    }
+                    expected = PRIMARY | OPERATOR | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION | NULLARY_CALL;
+                } else if (this.isRightParenth()) {
+                    if (expected & NULLARY_CALL) {
+                        var token = new Token(TNUMBER, 0, 0, []);
+                        tokenstack.push(token);
+                    } else if ((expected & RPAREN) === 0) {
+                        this.error_parsing(this.pos, 'unexpected ")"');
+                    }
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio -= 10;
+                    }
+                    this.mode = modestack.pop();
+                    expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
+                } else if (this.isRightBracket()) {
+                    if ((expected & RBRACK) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "]"');
+                    }
+                    expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
+                } else if (this.isLeftVarBrk(modestack)) {
+                    if ((expected & LVARBRK) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "{"');
+                    }
+                    noperators += 1;
+                    this.addfunc(tokenstack, operstack, TOP1);
+                    expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                } else if (this.isRightVarBrk()) {
+                    if ((expected & RVARBRK) === 0) {
+                        this.error_parsing(this.pos, 'unexpected "}"');
+                    }
+                    this.mode = modestack.pop();
+                    expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
+                } else if (this.isLeftCurly()) {
+                    if (this.mode == 1 || this.mode == 2 || this.mode == 3 || this.mode == 4) {
+                        modestack.push(this.mode);
+                        this.mode = 7;
+                    } else {
+                        this.error_parsing(this.pos, 'unexpected "{"');
+                    }
+                } else if (this.isRightCurly()) {
+                    if (this.mode == 7) {
+                        this.mode = modestack.pop();
+                    } else {
+                        this.error_parsing(this.pos, 'unexpected "}"');
+                    }
+                } else if (this.isComma()) {
+                    if ((expected & COMMA) === 0) {
+                        this.error_parsing(this.pos, 'unexpected ","');
+                    }
+                    if (!!partial) {
+                        break;
+                    }
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio -= 10;
+                    }
+                    this.tmpprio += 2;
+                    this.addfunc(tokenstack, operstack, TOP2);
+                    this.tmpprio -= 2;
+                    if (this.mode === 5 || this.mode === 6) {
+                        this.tmpprio += 10;
+                    }
+                    noperators += 2;
+                    expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
+                } else if (this.isConst()) {
+                    if ((expected & PRIMARY) === 0) {
+                        this.error_parsing(this.pos, "unexpected constant");
+                    }
+                    var consttoken = new Token(TNUMBER, 0, 0, this.tokennumber);
+                    tokenstack.push(consttoken);
+                    expected = OPERATOR | RPAREN | RVARBRK | RBRACK | COMMA;
+                } else {
+                    var str = getStr(this.pos, this.expression, this.mode, partial, preprocessed);
+                    if (this.isOpX(str, this.ops2) && (this.mode !== 2 && "/" !== str)) {
+                        if ("and" === str.str || "or" === str.str) {
+                            this.tokenprio = 3;
+                        }
+                        if ((expected & OPERATOR) === 0) {
+                            this.error_parsing(this.pos, "unexpected binary operator");
+                        }
+                        this.addfunc(tokenstack, operstack, TOP2);
+                        noperators += 2;
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | OPERATOR | SIGN | OPTION;
+                    } else if (this.isOpX(str, this.ops1)) {
+                        if ((expected & OPERATOR) === 0) {
+                            this.error_parsing(this.pos, "unexpected unary operator");
+                        }
+                        this.addfunc(tokenstack, operstack, TOP1);
+                        noperators++;
+                        expected = PRIMARY | LPAREN | LVARBRK | FUNCTION;
+                    } else if (this.isLiteralValue(str)) {
+                        if ((expected & PRIMARY) === 0) {
+                            this.error_parsing(this.pos, "unexpected literal value");
+                        }
+                        var token = new Token(TNUMBER, 0, 0, this.tokennumber);
+                        tokenstack.push(token);
+                        expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | RVARBRK | LBRACK | CALL | OPTION;
+                        if (this.mode === 6) {
+                            expected = expected | ASSIGN;
+                        }
+                    } else if (this.isVar(str)) {
+                        if ((expected & PRIMARY) === 0) {
+                            this.error_parsing(this.pos, "unexpected variable");
+                        }
+                        var vartoken = new Token(TVAR, this.tokenindex, 0, 0, this.mode, str.meta);
+                        tokenstack.push(vartoken);
+                        expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | RVARBRK | LBRACK | CALL | OPTION | ASSIGN;
+                    } else {
+                        if (this.errormsg === "") {
+                            this.error_parsing(this.pos, "unknown character");
+                        } else {
+                            this.error_parsing(this.pos, this.errormsg);
+                        }
+                    }
+                }
+            }
+            if (this.tmpprio < 0 || this.tmpprio >= 10) {
+                this.error_parsing(this.pos, 'unmatched "() or []"');
+            }
+            while (operstack.length > 0) {
+                var tmp = operstack.pop();
+                tokenstack.push(tmp);
+            }
+            if (noperators + 1 !== tokenstack.length) {
+                this.error_parsing(this.pos, "parity");
+            }
+            var res = new Expression(tokenstack, object(this.ops1), object(this.ops2), object(this.functions), this.precision, this.pos);
+            return res;
+        },
+        evaluate: function(expr, element) {
+            return this.parse(expr).evaluate(element);
+        },
+        error_parsing: function(column, msg) {
+            this.success = false;
+            this.errormsg = "parse error [column " + column + "]: " + msg;
+            throw new Error(this.errormsg);
+        },
+        addfunc: function(tokenstack, operstack, type_) {
+            var operator = new Token(type_, this.tokenindex, this.tokenprio + this.tmpprio, 0, this.mode, this.meta);
+            while (operstack.length > 0) {
+                if (operator.prio_ <= operstack[operstack.length - 1].prio_) {
+                    tokenstack.push(operstack.pop());
+                } else {
+                    break;
+                }
+            }
+            operstack.push(operator);
+        },
+        isNumber: function() {
+            var r = false;
+            var str = "";
+            var prec = -1;
+            while (this.pos < this.expression.length) {
+                var code = this.expression.charCodeAt(this.pos);
+                if (code >= 48 && code <= 57 || code === 46) {
+                    str += this.expression.charAt(this.pos);
+                    if (prec >= 0 || code === 46) {
+                        prec++;
+                    }
+                    this.pos++;
+                    r = true;
+                } else {
+                    break;
+                }
+            }
+            if (r) {
+                if (prec >= 0 && (typeof this.precision === "undefined" || prec > this.precision)) {
+                    this.precision = prec;
+                }
+                this.tokennumber = parseFloat(str);
+            }
+            return r;
+        },
+        isConst: function() {
+            var str;
+            for (var i in this.consts) {
+                if (true) {
+                    var L = i.length;
+                    str = this.expression.substr(this.pos, L);
+                    if (i === str) {
+                        this.tokennumber = this.consts[i];
+                        this.pos += L;
+                        return true;
+                    }
+                }
+            }
+            return false;
+        },
+        isOperator: function() {
+            var ch = this.expression.charAt(this.pos);
+            if (ch === "+") {
+                this.tokenprio = 0;
+                this.tokenindex = "+";
+            } else if (ch === "-") {
+                this.tokenprio = 0;
+                this.tokenindex = "-";
+            } else if (ch === "|") {
+                if (this.expression.charAt(this.pos + 1) === "|") {
+                    this.pos++;
+                    this.tokenprio = 0;
+                    this.tokenindex = "||";
+                } else {
+                    return false;
+                }
+            } else if (ch === "*") {
+                if (this.expression.charAt(this.pos + 1) === "{") {
+                    return false;
+                }
+                this.tokenprio = 1;
+                this.tokenindex = "*";
+            } else if (ch === "/" && this.mode != 2 && this.pos > 0) {
+                this.tokenprio = 2;
+                this.tokenindex = "/";
+            } else if (ch === "%") {
+                this.tokenprio = 2;
+                this.tokenindex = "%";
+            } else if (ch === "^") {
+                this.tokenprio = 3;
+                this.tokenindex = "^";
+            } else if (ch === "=" || ch === "!") {
+                if (this.expression.charAt(this.pos + 1) === "=") {
+                    if (ch === "=") {
+                        this.tokenindex = "==";
+                    } else if (ch === "!") {
+                        this.tokenindex = "!=";
+                    } else {
+                        return false;
+                    }
+                    this.pos++;
+                    this.tokenprio = 6;
+                } else if (ch === "!") {
+                    this.tokenprio = 7;
+                    this.tokenindex = "!";
+                } else if (ch === "=") {
+                    this.tokenindex = "=";
+                } else {
+                    return false;
+                }
+            } else if (ch === "<") {
+                if (this.expression.charAt(this.pos + 1) === "=") {
+                    this.tokenindex = "<=";
+                    this.pos++;
+                } else {
+                    this.tokenindex = "<";
+                }
+                this.tokenprio = 4;
+            } else if (ch === ">") {
+                if (this.expression.charAt(this.pos + 1) === "=") {
+                    this.tokenindex = ">=";
+                    this.pos++;
+                } else {
+                    this.tokenindex = ">";
+                }
+                this.tokenprio = 4;
+            } else if (ch === "." || ch === "[") {
+                this.tokenprio = 10;
+                this.tokenindex = ".";
+            } else {
+                return false;
+            }
+            this.pos++;
+            return true;
+        },
+        isRightBracket: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 93) {
+                this.pos++;
+                this.tmpprio -= 20;
+                return true;
+            }
+            return false;
+        },
+        isSign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 45 || code === 43) {
+                return true;
+            }
+            return false;
+        },
+        isAssign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 61) {
+                var cha = this.expression.charAt(this.pos - 2);
+                if (cha === "!" || cha === ">" || cha === "<" || cha === "=") {
+                    return false;
+                }
+                cha = this.expression.charAt(this.pos);
+                if (cha === ">" || cha === "<" || cha === "=") {
+                    return false;
+                }
+                return true;
+            }
+            return false;
+        },
+        isPositiveSign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 43) {
+                return true;
+            }
+            return false;
+        },
+        isNegativeSign: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 45) {
+                return true;
+            }
+            return false;
+        },
+        isLeftParenth: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 40) {
+                this.pos++;
+                this.tmpprio += 10;
+                return true;
+            }
+            return false;
+        },
+        isRightParenth: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 41) {
+                this.pos++;
+                this.tmpprio -= 10;
+                return true;
+            }
+            return false;
+        },
+        isLeftCurly: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 123) {
+                this.pos++;
+                this.tmpprio += 10;
+                return true;
+            }
+            return false;
+        },
+        isRightCurly: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 125) {
+                this.pos++;
+                this.tmpprio -= 10;
+                return true;
+            }
+            return false;
+        },
+        isComma: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 44) {
+                this.pos++;
+                this.tokenprio = -1;
+                this.tokenindex = ",";
+                return true;
+            }
+            return false;
+        },
+        isWhite: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 32 || code === 9 || code === 10 || code === 13) {
+                this.pos++;
+                return true;
+            }
+            return false;
+        },
+        isLeftVarBrk: function(modestack) {
+            var pp = this.pos, ch = this.expression.charAt(pp);
+            if (ch === "$" || ch === "@" || ch === "*" || ch === "#") {
+                pp++;
+                var ch2 = this.expression.charAt(pp);
+                if (ch2 === "{") {
+                    pp++;
+                    this.tmpprio += 10;
+                    this.tokenprio = -4;
+                    var oldMode = this.mode;
+                    modestack.push(oldMode);
+                    if (ch === "$") {
+                        this.mode = 1;
+                    } else if (ch === "@") {
+                        this.mode = 2;
+                    } else if (ch === "*") {
+                        this.mode = 3;
+                    } else if (ch === "#") {
+                        this.mode = 4;
+                    }
+                    this.tokenindex = "{";
+                    this.pos = pp;
+                    return true;
+                }
+            }
+            return false;
+        },
+        isRightVarBrk: function() {
+            var code = this.expression.charCodeAt(this.pos);
+            if (code === 125) {
+                this.pos++;
+                this.tmpprio -= 10;
+                return true;
+            }
+            return false;
+        },
+        isOpX: function(str, group) {
+            if (str.str.length > 0) {
+                if (str.str in new Object()) {
+                    return false;
+                }
+                if (str.str in group) {
+                    this.tokenindex = str.str;
+                    this.tokenprio = 5;
+                    this.pos = str.pos;
+                    return true;
+                }
+            }
+            return false;
+        },
+        isLiteralValue: function(str) {
+            if (typeof str.str === "string") {
+                var first = str.str.charAt(0);
+                var last = str.str.charAt(str.str.length - 1);
+                if (first == "'" && last == "'" || first == '"' && last == '"') {
+                    this.tokennumber = str.str.substring(1, str.str.length - 1);
+                    this.pos = str.pos;
+                    return true;
+                }
+            }
+            return false;
+        },
+        isVar: function(str) {
+            if (str.str.length > 0) {
+                this.tokenindex = str.str;
+                this.tokenprio = 4;
+                this.pos = str.pos;
+                return true;
+            }
+            return false;
+        },
+        isComment: function() {
+            var code = this.expression.charCodeAt(this.pos - 1);
+            if (code === 47 && this.expression.charCodeAt(this.pos) === 42) {
+                this.pos = this.expression.indexOf("*/", this.pos) + 2;
+                if (this.pos === 1) {
+                    this.pos = this.expression.length;
+                }
+                return true;
+            }
+            return false;
+        }
+    };
+    return ThParser;
+}();
+
+(function() {
+    var specAttrModList = [ "abbr", "accept", "accept-charset", "accesskey", "action", "align", "alt", "archive", "audio", "autocomplete", "axis", "background", "bgcolor", "border", "cellpadding", "cellspacing", "challenge", "charset", "cite", "class", "classid", "codebase", "codetype", "cols", "colspan", "compact", "content", "contenteditable", "contextmenu", "data", "datetime", "dir", "draggable", "dropzone", "enctype", "for", "form", "formaction", "formenctype", "formmethod", "formtarget", "frame", "frameborder", "headers", "height", "high", "href", "hreflang", "hspace", "http-equiv", "icon", "id", "keytype", "kind", "label", "lang", "list", "longdesc", "low", "manifest", "marginheight", "marginwidth", "max", "maxlength", "media", "method", "min", "name", "optimum", "pattern", "placeholder", "poster", "preload", "radiogroup", "rel", "rev", "rows", "rowspan", "rules", "sandbox", "scheme", "scope", "scrolling", "size", "sizes", "span", "spellcheck", "src", "srclang", "standby", "start", "step", "style", "summary", "tabindex", "target", "title", "type", "usemap", "value", "valuetype", "vspace", "width", "wrap", "xmlbase", "xmllang", "xmlspace" ];
+    var fixedValBoolAttrList = [ "async", "autofocus", "autoplay", "checked", "controls", "declare", "default", "defer", "disabled", "formnovalidate", "hidden", "ismap", "loop", "multiple", "novalidate", "nowrap", "open", "pubdate", "readonly", "required", "reversed", "scoped", "seamless", "selected" ];
+    var eventAttrList = [ "onabort", "onafterprint", "onbeforeprint", "onbeforeunload", "onblur", "oncanplay", "oncanplaythrough", "onchange", "onclick", "oncontextmenu", "ondblclick", "ondrag", "ondragend", "ondragenter", "ondragleave", "ondragover", "ondragstart", "ondrop", "ondurationchanged", "onemptied", "onended", "onerror", "onfocus", "onformchange", "onforminput", "onhashchange", "oninput", "oninvalid", "onkeydown", "onkeypress", "onkeyup", "onload", "onloadeddata", "onloadedmetadata", "onloadstart", "onmessage", "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onmousewheel", "onoffline", "ononline", "onpause", "onplay", "onplaying", "onpopstate", "onprogress", "onratechange", "onreadystatechange", "onredo", "onreset", "onresize", "onscroll", "onseeked", "onseeking", "onselect", "onshow", "onstalled", "onstorage", "onsubmit", "onsuspend", "ontimeupdate", "onundo", "onunload", "onvolumechange", "onwaiting" ];
+    var literalTokenExpr = /^[a-zA-Z0-9\[\]\.\-_]*$/;
+    var numericExpr = /^[+\-]?[0-9]*?[.]?[0-9]*?$/;
+    var nonURLExpr = /[\$\*#]{1}\{(?:!?[^}]*)\}/;
+    var varExpr = /[\$\*#@]{1}\{(!?[^}]*)\}/;
+    var textInlineCommentExpr = /\[\[(.*)\]\]/;
+    var javascriptInlineCommentExpr = /\/\*\[\[(.*)\]\]\*\//;
+    var javascriptInlineRemainderExpr = /\s*(?:['][^']*['])*(?:["][^"]*["])*(?:[\(][^\(\)]*[\)])*(?:[\{][^\{\}]*[\}])*(?:[\[][^\[\]]*[\]])*((?:[;,\(\)\[\]:\{\}](?=(?:\s*\/\/.*?(?:\n|$)))(?:\s*\/\/.*?(?:\n|$)))|(?:\s*\/\/.*?(?:\n|$))|(?:[;,\(\)\[\]:\{\}](?=(?:\s*(?:\n|$)))(?:\s*(?:\n|$)))|(?:\s*(?:\n|$)))/;
+    var thCase;
+    thymol.getThAttribute = function(part, element) {
+        var result = thymol.ThUtils.unParenthesise(part);
+        result = thymol.doExpression(result, element);
+        if (Object.prototype.toString.call(result) === "[object Array]") {
+            if (result.length === 1) {
+                result = result[0];
+            }
+        }
+        if (result instanceof thymol.ThParam) {
+            result = result.value;
+        }
+        return result;
+    };
+    thymol.doExpression = function(part, element) {
+        var result = thymol.ThUtils.unParenthesise(part), expr, unq, token, mapped;
+        expr = null;
+        unq = thymol.ThUtils.unQuote(result);
+        if (unq != result) {
+            result = thymol.preProcess(unq, element);
+        } else {
+            if (literalTokenExpr.test(result)) {
+                token = thymol.booleanAndNullTokens[result];
+                if (!(typeof token === "undefined")) {
+                    result = token;
+                } else {
+                    if (result.match(numericExpr)) {
+                        result = thymol.ThUtils.getToPrecision(result, thymol.ThUtils.getDecimalDigits(result));
+                    } else {
+                        expr = thymol.getExpression(result, element);
+                        if (expr !== undefined && expr !== null && !(expr != expr)) {
+                            result = expr;
+                        }
+                    }
+                }
+            } else {
+                expr = thymol.getExpression(result, element);
+                if (expr !== null && !(expr != expr)) {
+                    result = expr;
+                } else {
+                    result = null;
+                }
+            }
+        }
+        return result;
+    };
+    thymol.processText = function(element, thUrlAttr, thAttr) {
+        var url = thymol.getThAttribute(thUrlAttr.value, element), updated = false, text, newTextNode, i, iLimit, iUpper;
+        if (url == null) {
+            if (!thymol.allowNullText) {
+                if (thymol.debug) {
+                    thymol.thWindow.alert("thymol.processText cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
+                }
+                return updated;
+            }
+            url = "";
+        } else {
+            if (url instanceof thymol.ThParam || url instanceof thymol.ThObject) {
+                if (url.value) {
+                    url = url.value;
+                }
+            } else if (url instanceof thymol.ThClass && url.abort) {
+                element.removeAttribute(thUrlAttr.name);
+                return true;
+            }
+        }
+        try {
+            while (element.firstChild != null) {
+                element.removeChild(element.firstChild);
+                updated = true;
+                if (element.firstChild == null) {
+                    break;
+                }
+            }
+            if ("text" == thAttr.suffix) {
+                if (Object.prototype.toString.call(url) === "[object Array]") {
+                    text = "[";
+                    for (i = 0, iLimit = url.length, iUpper = url.length - 1; i < iLimit; i++) {
+                        text += url[i].toString();
+                        if (i < iUpper) {
+                            text += ", ";
+                        }
+                    }
+                    text += "]";
+                } else {
+                    text = url.toString();
+                }
+                text = thymol.ThUtils.unescape(text);
+                newTextNode = element.ownerDocument.createTextNode(text);
+                element.appendChild(newTextNode);
+                updated = true;
+            }
+            if ("utext" == thAttr.suffix) {
+                element.innerHTML = url;
+            }
+            element.removeAttribute(thUrlAttr.name);
+        } catch (err) {
+            if (thymol.debug) {
+                thymol.thWindow.alert("text replace error");
+            }
+        }
+        return updated;
+    };
+    thymol.processSpecAttrMod = function(element, thUrlAttr, thAttrObj) {
+        var url = thymol.getThAttribute(thUrlAttr.value, element);
+        if (!url || !(url instanceof thymol.ThClass) || !url.abort) {
+            element.setAttribute(thAttrObj.suffix, url);
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processAttr = function(element, thUrlAttr, thAttrObj) {
+        var argValue = thUrlAttr.value.trim(), argsExpr, expr, identifier, attrName = null, ep, lp, url, tt;
+        if (argValue) {
+            do {
+                argsExpr = thymol.ThParser.parse(argValue, true, false);
+                identifier = argsExpr.tokens.shift();
+                if (identifier.type_ === 3) {
+                    attrName = identifier.index_;
+                    if (!!attrName) {
+                        ep = argValue.indexOf("=");
+                        if (ep >= 0) {
+                            lp = argsExpr.position - 1;
+                            if (argsExpr.position === argValue.length) {
+                                lp = argValue.position;
+                            }
+                            expr = argValue.substring(ep + 1, lp).trim();
+                            if (fixedValBoolAttrList.indexOf(attrName) >= 0) {
+                                thymol.doFixedValBoolAttr(expr, element, attrName);
+                            } else {
+                                url = thymol.getThAttribute(expr, element);
+                                tt = typeof url;
+                                if (thAttrObj.suffix == "attrappend" || thAttrObj.suffix == "attrprepend") {
+                                    if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                                        existing = element.getAttribute(attrName);
+                                        if (existing) {
+                                            if (thAttrObj.suffix == "attrappend") {
+                                                url = existing + url;
+                                            } else if (thAttrObj.suffix == "attrprepend") {
+                                                url = url + existing;
+                                            }
+                                        }
+                                    }
+                                }
+                                if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                                    element.setAttribute(attrName, url);
+                                }
+                            }
+                        }
+                    }
+                    argValue = argValue.substring(argsExpr.position);
+                } else {
+                    break;
+                }
+            } while (argValue.length > 0);
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processCSSAttr = function(element, thUrlAttr, thAttrObj) {
+        var parts = thUrlAttr.value.split(","), i, iLimit, expr, attrName, url, tt, existing;
+        for (i = 0, iLimit = parts.length; i < iLimit; i++) {
+            expr = parts[i];
+            attrName = thAttrObj.suffix == "classappend" ? "class" : "style";
+            if (!!attrName) {
+                if (!!expr) {
+                    url = thymol.getThAttribute(expr, element);
+                    tt = typeof url;
+                    if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                        existing = element.getAttribute(attrName);
+                        if (existing) {
+                            url = existing + " " + url;
+                        }
+                    }
+                    if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
+                        element.setAttribute(attrName, url);
+                    }
+                }
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processFixedValBoolAttr = function(element, thUrlAttr, thAttrObj) {
+        var val = thymol.doFixedValBoolAttr(thUrlAttr.value, element, thAttrObj.suffix);
+        if (val != null) {
+            element.removeAttribute(thUrlAttr.name);
+        } else {
+            if (thymol.debug) {
+                thymol.thWindow.alert("thymol.processFixedValBoolAttr cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
+            }
+        }
+    };
+    thymol.doFixedValBoolAttr = function(valParam, element, attr) {
+        var val = thymol.getBoolean(valParam, element);
+        if (val) {
+            element.setAttribute(attr, attr);
+        }
+        return val;
+    };
+    thymol.processPairedAttr = function(element, thUrlAttr, thAttrObj) {
+        var url = thymol.getThAttribute(thUrlAttr.value, element);
+        if (url != "") {
+            if (thAttrObj.suffix === "alt-title") {
+                element.setAttribute("alt", url);
+                element.setAttribute("title", url);
+            }
+            if (thAttrObj.suffix === "lang-xmllang") {
+                element.setAttribute("lang", url);
+                element.setAttribute("xml:lang", url);
+            }
+            element.removeAttribute(thUrlAttr.name);
+        } else {
+            if (thymol.debug) {
+                thymol.thWindow.alert("thymol.processPairedAttr cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
+            }
+        }
+    };
+    thymol.processConditional = function(element, attr, thAttrObj) {
+        var removed = false;
+        if (attr.value) {
+            removed = thymol.doIfOrUnless(element, attr.value, thAttrObj.suffix === "if");
+        }
+        element.removeAttribute(attr.name);
+        return removed;
+    };
+    thymol.doIfOrUnless = function(element, value, isIf) {
+        var processed = false, flag;
+        if (value) {
+            flag = thymol.getBoolean(value, element);
+            processed = true;
+            if (!flag) {
+                if (isIf) {
+                    element.parentNode.removeChild(element);
+                    return true;
+                }
+            } else {
+                if (!isIf) {
+                    element.parentNode.removeChild(element);
+                    return true;
+                }
+            }
+        }
+        if (!processed && thymol.debug) {
+            thymol.thWindow.alert("thymol.processConditional cannot process conditional: " + value + "\n" + element.innerHTML);
+        }
+        return false;
+    };
+    thymol.processEach = function(element, thUrlAttr, junk) {
+        var elementsUpdated = false, initial = thUrlAttr.value.trim(), colonPos, varName, varNames, statVarName, expr, root, node, i, iLimit, tho, stat, count, newNode, next;
+        colonPos = initial.indexOf(":");
+        if (colonPos > 0) {
+            varName = initial.substring(0, colonPos);
+            if (varName) {
+                varName = varName.trim();
+                varNames = varName.split(",");
+                varName = varNames[0].trim();
+                if (varNames.length > 1) {
+                    statVarName = varNames[1].trim();
+                } else {
+                    statVarName = varName + "Stat";
+                }
+                expr = initial.substr(colonPos + 1);
+                if (expr) {
+                    expr = expr.trim();
+                    expr = thymol.getExpression(expr, element);
+                    if (expr instanceof thymol.ThSet) {
+                        expr = expr.toArray();
+                    }
+                    root = element.parentNode;
+                    if (expr && expr instanceof Object && expr.length > 0) {
+                        node = element;
+                        iLimit = expr.length;
+                        element.removeAttribute(thUrlAttr.name);
+                        for (i = 0; i < iLimit; i++) {
+                            tho = expr[i];
+                            stat = new Object();
+                            stat.current = tho;
+                            stat.size = expr.length;
+                            stat.index = i;
+                            count = i + 1;
+                            stat.count = count;
+                            if (i == 0) {
+                                stat.first = true;
+                            } else {
+                                stat.first = false;
+                            }
+                            if (i == expr.length - 1) {
+                                stat.last = true;
+                            } else {
+                                stat.last = false;
+                            }
+                            if (i % 2) {
+                                stat.odd = true;
+                                stat.even = false;
+                            } else {
+                                stat.odd = false;
+                                stat.even = true;
+                            }
+                            if (!node.thLocalVars) {
+                                node.thLocalVars = {};
+                            }
+                            node.thLocalVars[varName] = tho;
+                            node.thLocalVars[statVarName] = stat;
+                            if (count < expr.length) {
+                                newNode = element.cloneNode(true);
+                                if (node.nextElementSibling != null) {
+                                    next = root.insertBefore(newNode, node.nextElementSibling);
+                                } else {
+                                    next = root.appendChild(newNode);
+                                }
+                                node = next;
+                                elementsUpdated = true;
+                            }
+                        }
+                    } else {
+                        if (root !== null) {
+                            if (!element.thLocalVars) {
+                                element.thLocalVars = {};
+                            }
+                            if (!element.thLocalVars[varName]) {
+                                element.thLocalVars[varName] = new Object();
+                            }
+                            if (!element.thLocalVars[statVarName]) {
+                                element.thLocalVars[statVarName] = new Object();
+                            }
+                            root.removeChild(element);
+                            elementsUpdated = true;
+                        }
+                    }
+                }
+            }
+        }
+        return elementsUpdated;
+    };
+    thymol.processObject = function(element, thUrlAttr) {
+        var argValue = thUrlAttr.value.trim(), val;
+        if (argValue) {
+            val = thymol.getExpression(argValue, element);
+            if (val) {
+                element.thObjectVar = val;
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processInline = function(element, thUrlAttr, thAttrObj) {
+        var mode = thymol.getThAttribute(thUrlAttr.value, element);
+        if (mode == "text") {
+            thymol.doInlineText(element);
+        } else if (mode == "javascript" || mode == "dart") {
+            thymol.doInlineJavascript(element);
+        } else {
+            if (thymol.debug) {
+                thymol.thWindow.alert('thymol.processInline cannot process scripting mode: "' + mode + '" - it isn\'t supported by version "' + thymol.thVersion + '"\n');
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.doInlineText = function(element) {
+        var changed, value, i, iLimit, expr, term, result;
+        for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
+            do {
+                changed = false;
+                if (element.childNodes[i].nodeType == 1) {
+                    thymol.doInlineText(element.childNodes[i]);
+                } else if (element.childNodes[i].nodeType == 3) {
+                    value = element.childNodes[i].nodeValue;
+                    if (value) {
+                        expr = textInlineCommentExpr.exec(value);
+                        if (expr) {
+                            term = "";
+                            if (expr.length > 1) {
+                                term = "[[" + expr[1] + "]]";
+                            }
+                            if (expr.length > 1) {
+                                result = thymol.getThAttribute(expr[1], element);
+                                result = value.replace(term, result);
+                                element.childNodes[i].nodeValue = result;
+                                changed = true;
+                            }
+                            expr = null;
+                        }
+                    }
+                }
+            } while (changed);
+        }
+    };
+    thymol.doInlineJavascript = function(element) {
+        var changed, value, second, i, iLimit, expr, scraps, remainder, termIndx, term, secondIndx, result;
+        for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
+            do {
+                second = null;
+                changed = false;
+                value = element.childNodes[i].nodeValue;
+                if (value) {
+                    expr = javascriptInlineCommentExpr.exec(value);
+                    if (expr) {
+                        termIndx = expr.index;
+                        term = "";
+                        if (expr.length > 1) {
+                            term = "/*[[" + expr[1] + "]]*/";
+                        }
+                        termIndx = termIndx + term.length;
+                        remainder = value.substring(termIndx);
+                        scraps = javascriptInlineRemainderExpr.exec(remainder);
+                        if (scraps) {
+                            if (scraps.length > 1) {
+                                secondIndx = remainder.indexOf(scraps[1]);
+                                second = remainder.substring(secondIndx);
+                                value = value.substring(0, termIndx);
+                                value = value + second;
+                            }
+                        }
+                        if (expr.length > 1) {
+                            result = thymol.getExpression(expr[1], element);
+                            if (result instanceof thymol.ThObject) {
+                                result = result.toNonThObject();
+                            }
+                            if (!thymol.ThUtils.isLiteral(result)) {
+                                result = thymol.getStringView(result);
+                            }
+                            result = value.replace(term, result);
+                            element.childNodes[i].nodeValue = result;
+                            changed = true;
+                        }
+                        expr = null;
+                        scraps = null;
+                    }
+                }
+            } while (changed);
+        }
+    };
+    thymol.getStringView = function(param) {
+        var view = "", objType;
+        if (typeof param === "string") {
+            view = view + "'" + param + "'";
+        } else if (typeof param === "number" || typeof param === "boolean") {
+            view = view + param;
+        } else if (typeof param === "object") {
+            if (param instanceof Object) {
+                objType = Object.prototype.toString.call(param);
+                if ("[object Array]" == objType) {
+                    view = thymol.getStringViewArray(param);
+                } else if ("[object Object]" == objType) {
+                    view = thymol.getStringViewObject(param);
+                }
+            }
+        }
+        return view;
+    };
+    thymol.getStringViewArray = function(param) {
+        var view = "[", i, iLimit;
+        for (i = 0, iLimit = param.length; i < iLimit; i++) {
+            view = view + thymol.getStringView(param[i]);
+            if (i < param.length - 1) {
+                view = view + ",";
+            }
+        }
+        view = view + "]";
+        return view;
+    };
+    thymol.getStringViewObject = function(param) {
+        var view = "{", key = null;
+        for (key in param) {
+            if (key) {
+                if (view != "{") {
+                    view = view + ",";
+                }
+                view = view + thymol.getStringView(key) + ":";
+                view = view + thymol.getStringView(param[key]);
+            }
+        }
+        view = view + "}";
+        return view;
+    };
+    thymol.processRemove = function(element, thUrlAttr) {
+        var haveRemoved = false;
+        var locals = element.thLocalVars, savedLocals = element.thLocalVars, arg, nodes, first;
+        if (!locals) {
+            locals = {};
+        }
+        if (!locals["tag"]) {
+            locals["tag"] = "tag";
+        }
+        if (!locals["body"]) {
+            locals["body"] = "body";
+        }
+        if (!locals["none"]) {
+            locals["none"] = "none";
+        }
+        if (!locals["all"]) {
+            locals["all"] = "all";
+        }
+        if (!locals["all-but-first"]) {
+            locals["all-but-first"] = "all-but-first";
+        }
+        element.thLocalVars = locals;
+        arg = thymol.getThAttribute(thUrlAttr.value, element);
+        element.thLocalVars = savedLocals;
+        element.removeAttribute(thUrlAttr.name);
+        if ("all" == arg) {
+            if (element.parentNode != null) {
+                element.parentNode.removeChild(element);
+                haveRemoved = true;
+            }
+        } else if ("body" == arg) {
+            element.innerHTML = "";
+            haveRemoved = true;
+        } else if ("tag" == arg) {
+            thymol.ThUtils.removeTag(element);
+            haveRemoved = true;
+        } else if ("all-but-first" == arg) {
+            nodes = element.childNodes;
+            first = true;
+            $(nodes).each(function() {
+                if (this.nodeType == 1) {
+                    if (!first) {
+                        element.removeChild(this);
+                        haveRemoved = true;
+                    }
+                    first = false;
+                }
+            });
+        } else if ("none" == arg || null == arg) {}
+        return haveRemoved;
+    };
+    thymol.processSwitch = function(element, attr) {
+        var val = thymol.ThUtils.unParenthesise(attr.value), updated = false, args, matched = false, thCaseSpecs, caseClause, remove, ccAttr;
+        val = thymol.getThAttribute(val, element);
+        if (typeof val === "string") {
+            args = val.match(nonURLExpr);
+            if (args) {
+                val = args[1];
+            }
+        }
+        val = thymol.ThUtils.unQuote(val);
+        thCaseSpecs = $(thCase.escpName, element);
+        thCaseSpecs.each(function() {
+            caseClause = this;
+            remove = true;
+            $(caseClause.attributes).each(function() {
+                ccAttr = this;
+                if (thCase.name == ccAttr.name || thCase.synonym == ccAttr.name) {
+                    if (!matched) {
+                        matched = thymol.processCase(element, ccAttr, val);
+                        if (matched) {
+                            remove = false;
+                        }
+                    }
+                    caseClause.removeAttribute(ccAttr.name);
+                }
+            });
+            if (remove) {
+                element.removeChild(caseClause);
+                updated = true;
+            }
+        });
+        return updated;
+    };
+    thymol.processCase = function(element, attr, param) {
+        var val = thymol.substitute(attr.value, element);
+        val = thymol.ThUtils.unQuote(val);
+        if (val == "*" || param && param == val) {
+            return true;
+        }
+        return false;
+    };
+    thymol.processWith = function(element, thUrlAttr) {
+        thymol.getWith(element, thUrlAttr.value);
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processAssert = function(element, thUrlAttr) {
+        var argValue = thUrlAttr.value.trim(), result = true, term = "", terms, i, iLimit, expr, val, flag;
+        if (argValue) {
+            terms = argValue.split(",");
+            for (i = 0, iLimit = terms.length; i < iLimit; i++) {
+                term = terms[i];
+                expr = thymol.ThUtils.unParenthesise(term);
+                if (expr != null) {
+                    val = thymol.getExpression(expr, element);
+                    if (val) {
+                        flag = thymol.getBoolean(val, element);
+                        if (!flag) {
+                            result = false;
+                            break;
+                        }
+                    } else {
+                        result = false;
+                        break;
+                    }
+                } else {
+                    result = false;
+                    break;
+                }
+            }
+        }
+        if (!result) {
+            if (argValue != term) {
+                argValue = " list is: " + argValue;
+            } else {
+                argValue = "";
+            }
+            if (term != "") {
+                term = ' false term is: "' + term + '"';
+            }
+            if (thymol.debug) {
+                thymol.thWindow.alert("thymol.processAssert assertion failure -" + argValue + term + "\n");
+            }
+        }
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.processFragment = function(element, thUrlAttr, thAttrObj) {
+        element.removeAttribute(thUrlAttr.name);
+    };
+    thymol.getBoolean = function(param, element) {
+        if (param == null) {
+            return false;
+        }
+        if (typeof param === "boolean") {
+            return param;
+        } else if (typeof param === "number") {
+            return param != 0;
+        }
+        var initial = thymol.ThUtils.unParenthesise(param), negate = false, val, args, flag;
+        if (initial.charAt(0) == "!") {
+            negate = true;
+            initial = initial.substring(1, initial.length);
+            initial = thymol.ThUtils.unParenthesise(initial);
+        }
+        val = thymol.getThAttribute(initial, element);
+        if (val == null) {
+            args = initial.match(varExpr);
+            if (args) {
+                if (args[1].charAt(0) == "!") {
+                    negate = !negate;
+                }
+            }
+        }
+        flag = thymol.getBooleanValue(val);
+        if (negate) {
+            flag = !flag;
+        }
+        return flag;
+    };
+    thymol.appendToAttrList = function(func, prec, attrArray) {
+        var j, jLimit = attrArray.length, tha = null;
+        for (j = 0; j < jLimit; j++) {
+            tha = new thymol.ThAttr(attrArray[j], func, prec, thymol.thThymeleafPrefixList, thymol.prefix);
+        }
+        j = tha;
+    };
+    thymol.setupAttrList = function() {
+        thCase = new thymol.ThAttr("case", null, 275, thymol.thThymeleafPrefixList, thymol.prefix);
+        thymol.addDialect({
+            prefix: thymol.prefix,
+            attributeProcessors: [ {
+                name: "each",
+                processor: thymol.processEach,
+                precedence: 200
+            }, {
+                name: "switch",
+                processor: thymol.processSwitch,
+                precedence: 250
+            }, {
+                name: "if",
+                processor: thymol.processConditional,
+                precedence: 300
+            }, {
+                name: "unless",
+                processor: thymol.processConditional,
+                precedence: 400
+            }, {
+                name: "object",
+                processor: thymol.processObject,
+                precedence: 500
+            }, {
+                name: "with",
+                processor: thymol.processWith,
+                precedence: 600
+            }, {
+                name: "attr",
+                processor: thymol.processAttr,
+                precedence: 700
+            }, {
+                name: "attrprepend",
+                processor: thymol.processAttr,
+                precedence: 800
+            }, {
+                name: "attrappend",
+                processor: thymol.processAttr,
+                precedence: 900
+            }, {
+                name: "alt-title",
+                processor: thymol.processPairedAttr,
+                precedence: 990
+            }, {
+                name: "lang-xmllang",
+                processor: thymol.processPairedAttr,
+                precedence: 990
+            }, {
+                name: "inline",
+                processor: thymol.processInline,
+                precedence: 1e3
+            }, {
+                name: "classappend",
+                processor: thymol.processCSSAttr,
+                precedence: 1100
+            }, {
+                name: "styleappend",
+                processor: thymol.processCSSAttr,
+                precedence: 1100
+            }, {
+                name: "text",
+                processor: thymol.processText,
+                precedence: 1300
+            }, {
+                name: "utext",
+                processor: thymol.processText,
+                precedence: 1400
+            }, {
+                name: "fragment",
+                processor: thymol.processFragment,
+                precedence: 1500
+            }, {
+                name: "assert",
+                processor: thymol.processAssert,
+                precedence: 1550
+            }, {
+                name: "remove",
+                processor: thymol.processRemove,
+                precedence: 1600
+            } ]
+        });
+        thymol.appendToAttrList(thymol.processSpecAttrMod, 1e3, specAttrModList);
+        thymol.appendToAttrList(thymol.processSpecAttrMod, 1e3, eventAttrList);
+        thymol.appendToAttrList(thymol.processFixedValBoolAttr, 1e3, fixedValBoolAttrList);
+    };
+})();
+
+thymol.objects.thHttpSessionObject = function() {
+    var thExpressionObjectName = "#httpSession";
+    function getAttribute(name) {
+        var result = thymol.sessionContext[name];
+        return result;
+    }
+    function getParameter(name) {
+        var result = thymol.sessionContext[name];
+        return result;
+    }
+    function getServletContext() {
+        var result = thymol.applicationContext;
+        return result;
+    }
+    function getSessionContext() {
+        var result = thymol.sessionContext;
+        return result;
+    }
+    function getContextPath() {
+        var result = "";
+        return result;
+    }
+    function getRequestName() {
+        var result = "";
+        return result;
+    }
+    function getParameterValues(name) {
+        var result = thymol.sessionContext[name];
+        return result;
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        getAttribute: getAttribute,
+        getParameter: getParameter,
+        getServletContext: getServletContext,
+        getSessionContext: getSessionContext,
+        getContextPath: getContextPath,
+        getRequestName: getRequestName,
+        getParameterValues: getParameterValues
+    };
+}();
+
+thymol.objects.thHttpServletRequestObject = function() {
+    var thExpressionObjectName = "#httpServletRequest";
+    function getAttribute(name) {
+        var result = thymol.requestContext[name][0];
+        if (result instanceof thymol.ThParam) {
+            result = thymol.ThUtils.unQuote(result.value);
+        }
+        return result;
+    }
+    function getParameter(name) {
+        var result = thymol.requestContext[name];
+        return result;
+    }
+    function getContextPath() {
+        var result = "";
+        return result;
+    }
+    function getRequestName() {
+        var result = "";
+        return result;
+    }
+    function getParameterValues(name) {
+        var result = thymol.requestContext[name];
+        return result;
+    }
+    function getSession(create) {
+        return thymol.objects.thHttpSessionObject;
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        getAttribute: getAttribute,
+        getParameter: getParameter,
+        getContextPath: getContextPath,
+        getRequestName: getRequestName,
+        getParameterValues: getParameterValues,
+        getSession: getSession
+    };
+}();
+
+thymol.objects.thAggregatesObject = function() {
+    var thExpressionObjectName = "#aggregates";
+    function sum(target) {
+        return aggregate(target, false, "sum");
+    }
+    function avg(target) {
+        return aggregate(target, true, "avg");
+    }
+    function aggregate(target, doAvg, label) {
+        if (target !== null) {
+            var result = 0;
+            var count;
+            var tt = typeof target;
+            var ptc = Object.prototype.toString.call(target);
+            if (tt === "Array" || ptc === "[object Array]") {
+                count = target.length;
+                for (var i = 0; i < count; i++) {
+                    if (target[i] !== null) {
+                        result += target[i];
+                    } else {
+                        throw new thymol.ThError("#aggregates." + label + " Cannot aggregate on object containing nulls");
+                    }
+                }
+            } else {
+                count = 0;
+                for (var k in target) {
+                    var value = target[k];
+                    var process = false;
+                    if (value !== null) {
+                        if (target instanceof thymol.ThSet) {
+                            process = target.isContent(k);
+                        } else {
+                            process = target.hasOwnProperty(k) && typeof value !== "function";
+                        }
+                    } else {
+                        throw new thymol.ThError("#aggregates." + label + " Cannot aggregate on object containing nulls");
+                    }
+                    if (process) {
+                        result += value;
+                        count++;
+                    }
+                }
+            }
+            if (doAvg) {
+                if (count == 0) {
+                    throw new thymol.ThError("#aggregates." + label + " Cannot get size of object");
+                }
+                result = result / count;
+            }
+            return result;
+        }
+        throw new thymol.ThError("#aggregates." + label + " Cannot aggregate on null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        sum: sum,
+        avg: avg
+    };
+}();
+
+thymol.objects.thArraysObject = function() {
+    var thExpressionObjectName = "#arrays";
+    function toArray(target) {
+        if (target !== null) {
+            return toTypedArray(null, target);
+        }
+        throw new thymol.ThError("#arrays.toArray Cannot convert null to array");
+    }
+    function toStringArray(target) {
+        if (target !== null) {
+            return toTypedArray("string", target);
+        }
+        throw new thymol.ThError("#arrays.toStringArray Cannot convert null to array");
+    }
+    function toNumberArray(target) {
+        if (target !== null) {
+            return toTypedArray("number", target);
+        }
+        throw new thymol.ThError("#arrays.toNumberArray Cannot convert null to array");
+    }
+    function toBooleanArray(target) {
+        if (target !== null) {
+            return toTypedArray("boolean", target);
+        }
+        throw new thymol.ThError("#arrays.toBooleanArray Cannot convert null to array");
+    }
+    function toTypedArray(componentClass, target) {
+        if (target instanceof Array) {
+            if (componentClass === null || componentClass === "undefined") {
+                return target;
+            }
+            var result = new Array();
+            try {
+                for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                    if (target[i] !== null) {
+                        if (componentClass === "string") {
+                            result.push(new String(target[i]).valueOf());
+                        } else if (componentClass === "number") {
+                            result.push(new Number(target[i]).valueOf());
+                        } else if (componentClass === "boolean") {
+                            result.push(new Boolean(target[i]).valueOf());
+                        } else {
+                            result.push(target[i]);
+                        }
+                    }
+                }
+            } catch (err) {
+                throw new IllegalArgumentException('#arrays.toArray Cannot convert object of class "' + targetComponentClass.getName() + '[]" to an array' + " of " + componentClass.getClass().getSimpleName());
+            }
+            return result;
+        } else if (target instanceof Object) {
+            var result = new Array();
+            try {
+                for (var k in target) {
+                    var value = target[k];
+                    var process = false;
+                    if (value !== null) {
+                        if (target instanceof thymol.ThSet) {
+                            process = target.isContent(k);
+                        } else {
+                            process = target.hasOwnProperty(k) && typeof value !== "function";
+                        }
+                    }
+                    if (process) {
+                        if (componentClass === "string") {
+                            result.push(new String(value).valueOf());
+                        } else if (componentClass === "number") {
+                            result.push(new Number(value).valueOf());
+                        } else if (componentClass === "boolean") {
+                            result.push(new Boolean(value).valueOf());
+                        } else {
+                            result.push(value);
+                        }
+                    }
+                }
+            } catch (err) {
+                throw new IllegalArgumentException('#arrays.toArray Cannot convert object of class "' + targetComponentClass.getName() + '[]" to an array' + " of " + componentClass.getClass().getSimpleName());
+            }
+            return result;
+        } else {
+            throw new thymol.ThError('#arrays.toArray Cannot convert object of type "' + typeof target + '" to an array' + (componentClass == null ? "" : " of " + componentClass));
+        }
+    }
+    function length(target) {
+        if (target !== null) {
+            return target.length;
+        }
+        throw new thymol.ThError("#arrays.length Cannot get array length of null");
+    }
+    function isEmpty(target) {
+        return target === null || target.length <= 0;
+    }
+    function contains(target, element) {
+        if (target !== null) {
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] === null) {
+                    if (element === null) {
+                        return true;
+                    }
+                } else if (element !== null && target[i] === element) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        throw new thymol.ThError("#arrays.contains Cannot execute array contains: target is null");
+    }
+    function containsAll(target, elements) {
+        if (target !== null) {
+            if (elements !== null) {
+                var elementsArray;
+                if (elements instanceof Array) {
+                    elementsArray = [].concat(elements);
+                } else {
+                    if (elements instanceof thymol.ThSet) {
+                        elementsArray = elements.toArray();
+                    } else {
+                        elementsArray = [];
+                        for (var k in elements) {
+                            if (elements.hasOwnProperty(k) && typeof elements[k] !== "function") {
+                                elementsArray.push(elements[k]);
+                            }
+                        }
+                    }
+                }
+                for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                    for (var j = 0, jLimit = elementsArray.length; j < jLimit; j++) {
+                        if (target[i] === elementsArray[j]) {
+                            elementsArray.splice(j, 1);
+                        }
+                    }
+                }
+                return elementsArray.length === 0;
+            }
+            throw new thymol.ThError("#arrays.containsAll Cannot execute array containsAll: elements is null");
+        }
+        throw new thymol.ThError("#arrays.containsAll Cannot execute array containsAll: target is null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        toArray: toArray,
+        toStringArray: toStringArray,
+        toIntegerArray: toNumberArray,
+        toLongArray: toNumberArray,
+        toDoubleArray: toNumberArray,
+        toFloatArray: toNumberArray,
+        toBooleanArray: toBooleanArray,
+        length: length,
+        isEmpty: isEmpty,
+        contains: contains,
+        containsAll: containsAll
+    };
+}();
+
+thymol.objects.thBoolsObject = function() {
+    var thExpressionObjectName = "#bools";
+    function isTrue(target) {
+        var result = true;
+        var tc;
+        if (target == null || (tc = typeof target) === "undefined") {
+            result = false;
+        } else {
+            if (tc === "boolean") {
+                result = target;
+            } else if (tc === "number") {
+                result = target != 0;
+            } else if (tc === "string") {
+                if (target.length === 1) {
+                    result = target.charCodeAt(0) != 0;
+                } else if (thymol.ThUtils.testLiteralFalse(target)) {
+                    result = false;
+                }
+            }
+        }
+        return result;
+    }
+    function arrayIsTrue(target) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(isTrue(target[i]));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#bools.arrayIsTrue Target cannot be null");
+    }
+    function setIsTrue(target) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(isTrue(target[k]));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#bools.setIsTrue Target cannot be null");
+    }
+    function isFalse(target) {
+        return !isTrue(target);
+    }
+    function arrayIsFalse(target) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(!isTrue(target[i]));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#bools.arrayIsFalse Target cannot be null");
+    }
+    function setIsFalse(target) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(!isTrue(target[k]));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#bools.setIsFalse Target cannot be null");
+    }
+    function arrayAnd(target) {
+        if (target !== null) {
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (!isTrue(target[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        throw new thymol.ThError("#bools.arrayAnd Target cannot be null");
+    }
+    function setAnd(target) {
+        if (target !== null) {
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    if (!isTrue(target[k])) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        throw new thymol.ThError("#bools.setAnd Target cannot be null");
+    }
+    function arrayOr(target) {
+        if (target !== null) {
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (isTrue(target[i])) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        throw new thymol.ThError("#bools.arrayOr Target cannot be null");
+    }
+    function setOr(target) {
+        if (target !== null) {
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    if (isTrue(target[k])) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+        throw new thymol.ThError("#bools.setOr Target cannot be null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        isTrue: isTrue,
+        arrayIsTrue: arrayIsTrue,
+        listIsTrue: arrayIsTrue,
+        setIsTrue: setIsTrue,
+        isFalse: isFalse,
+        arrayIsFalse: arrayIsFalse,
+        listIsFalse: arrayIsFalse,
+        setIsFalse: setIsFalse,
+        arrayAnd: arrayAnd,
+        listAnd: arrayAnd,
+        setAnd: setAnd,
+        arrayOr: arrayOr,
+        listOr: arrayOr,
+        setOr: setOr
+    };
+}();
+
+thymol.objects.thDatesObject = function() {
+    var thExpressionObjectName = "#dates";
+    function createProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 6) {
+                return create(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
+            } else if (arguments.length > 5) {
+                return create(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], 0);
+            } else if (arguments.length > 4) {
+                return create(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], 0, 0);
+            }
+            return create(arguments[0], arguments[1], arguments[2], 0, 0, 0, 0);
+        }
+    }
+    function create(year, month, day, hour, minute, second, millisecond) {
+        var result = new Date();
+        result.setMilliseconds(millisecond);
+        result.setSeconds(second);
+        result.setMinutes(minute);
+        result.setHours(hour);
+        result.setDate(day);
+        result.setMonth(month - 1);
+        result.setFullYear(year);
+        return result;
+    }
+    function getDay(dateValue) {
+        var month = dateValue.getMonth() + 1;
+        var year = dateValue.getFullYear();
+        var day = dateValue.getDate();
+        var a = Math.floor((14 - month) / 12);
+        var y = year + 4800 - a;
+        var m = month + 12 * a - 3;
+        var jdn = day + Math.floor((153 * m + 2) / 5) + 365 * y + Math.floor(y / 4);
+        if (jdn < 2331254) {
+            jdn = jdn - 32083;
+        } else {
+            jdn = jdn - Math.floor(y / 100) + Math.floor(y / 400) - 32045;
+        }
+        var mjdn = (jdn + 1) % 7;
+        return mjdn;
+    }
+    function createNow() {
+        return new Date();
+    }
+    function createToday() {
+        var today = new Date();
+        today.setHours(0, 0, 0, 0);
+        return today;
+    }
+    function format(dateParam, patternParam, locale) {
+        var pattern = "";
+        var date;
+        if (arguments === null) {
+            date = new Date();
+        } else {
+            if (arguments.length > 1) {
+                pattern = patternParam;
+            }
+            date = dateParam;
+        }
+        return formatDate(date, pattern, locale);
+    }
+    function formatDate(target, patternParam, locale) {
+        var pattern = "";
+        if (arguments.length > 1) {
+            pattern = patternParam;
+        }
+        var result = dateFormat(target, pattern, false);
+        return result;
+    }
+    function arrayFormat(target, patternParam) {
+        var pattern = "";
+        if (arguments.length > 1) {
+            pattern = patternParam;
+        }
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(dateFormat(target[i], pattern, false));
+        }
+        return result;
+    }
+    function setFormat(target, patternParam) {
+        var pattern = "";
+        if (arguments.length > 1) {
+            pattern = patternParam;
+        }
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(dateFormat(target[k], pattern, false));
+            }
+        }
+        return result;
+    }
+    function day(target) {
+        return target.getDate();
+    }
+    function arrayDay(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getDate());
+        }
+        return result;
+    }
+    function setDay(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getDate());
+            }
+        }
+        return result;
+    }
+    function month(target) {
+        return target.getMonth() + 1;
+    }
+    function arrayMonth(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getMonth() + 1);
+        }
+        return result;
+    }
+    function setMonth(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getMonth() + 1);
+            }
+        }
+        return result;
+    }
+    function monthName(target) {
+        return dateFormat.i18n.monthNames[target.getMonth() + 12];
+    }
+    function arrayMonthName(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(dateFormat.i18n.monthNames[target[i].getMonth() + 12]);
+        }
+        return result;
+    }
+    function setMonthName(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(dateFormat.i18n.monthNames[target[k].getMonth() + 12]);
+            }
+        }
+        return result;
+    }
+    function monthNameShort(target) {
+        return dateFormat.i18n.monthNames[target.getMonth()];
+    }
+    function arrayMonthNameShort(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(dateFormat.i18n.monthNames[target[i].getMonth()]);
+        }
+        return result;
+    }
+    function setMonthNameShort(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(dateFormat.i18n.monthNames[target[k].getMonth()]);
+            }
+        }
+        return result;
+    }
+    function year(target) {
+        return target.getFullYear();
+    }
+    function arrayYear(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getFullYear());
+        }
+        return result;
+    }
+    function setYear(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getFullYear());
+            }
+        }
+        return result;
+    }
+    function dayOfWeek(target) {
+        return getDay(target) + 1;
+    }
+    function arrayDayOfWeek(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(getDay(target[i]) + 1);
+        }
+        return result;
+    }
+    function setDayOfWeek(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(getDay(target[k]) + 1);
+            }
+        }
+        return result;
+    }
+    function dayOfWeekName(target) {
+        return dateFormat.i18n.dayNames[getDay(target) + 7];
+    }
+    function arrayDayOfWeekName(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(dateFormat.i18n.dayNames[getDay(target[i]) + 7]);
+        }
+        return result;
+    }
+    function setDayOfWeekName(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(dateFormat.i18n.dayNames[getDay(target[k]) + 7]);
+            }
+        }
+        return result;
+    }
+    function dayOfWeekNameShort(target) {
+        return dateFormat.i18n.dayNames[getDay(target)];
+    }
+    function arrayDayOfWeekNameShort(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(dateFormat.i18n.dayNames[getDay(target[i])]);
+        }
+        return result;
+    }
+    function setDayOfWeekNameShort(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(dateFormat.i18n.dayNames[getDay(target[k])]);
+            }
+        }
+        return result;
+    }
+    function hour(target) {
+        return target.getHours();
+    }
+    function arrayHour(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getHours());
+        }
+        return result;
+    }
+    function setHour(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getHours());
+            }
+        }
+        return result;
+    }
+    function minute(target) {
+        return target.getMinutes();
+    }
+    function arrayMinute(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getMinutes());
+        }
+        return result;
+    }
+    function setMinute(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getMinutes());
+            }
+        }
+        return result;
+    }
+    function second(target) {
+        return target.getSeconds();
+    }
+    function arraySecond(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getSeconds());
+        }
+        return result;
+    }
+    function setSecond(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getSeconds());
+            }
+        }
+        return result;
+    }
+    function millisecond(target) {
+        return target.getMilliseconds();
+    }
+    function arrayMillisecond(target) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(target[i].getMilliseconds());
+        }
+        return result;
+    }
+    function setMillisecond(target) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.isContent(k)) {
+                result.add(target[k].getMilliseconds());
+            }
+        }
+        return result;
+    }
+    var timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, timezoneClip = /[^-+\dA-Z]/g;
+    function processTZ(target) {
+        var toStr = String(target);
+        var result = toStr;
+        result = (result.match(timezone) || [ "" ]).pop();
+        if ("" !== result) {
+            result = result.replace(timezoneClip, "");
+            var tail = toStr.match(/[\(]((?:[GL]M|BS)T[^\)]*?)[\)]/);
+            if (tail) {
+                if (target.getFullYear() > 1916 || target.getFullYear() === 1916 && target.getMonth() > 4 || target.getFullYear() === 1916 && target.getMonth() === 4 && target.getDate() > 20) {
+                    result = result.replace(/GMT\+\d{1,4}/, "BST");
+                } else {
+                    result = result.replace(/GMT\+\d{1,4}/, "GMT");
+                }
+            }
+        }
+        return result;
+    }
+    var dateFormat = function() {
+        var token = /d{1,4}|M{1,4}|yy(?:yy)?|([HhmsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, pad = function(valp, lenp) {
+            var val = String(valp), len = lenp || 2;
+            while (val.length < len) val = "0" + val;
+            return val;
+        };
+        return function(datep, maskp, utcp) {
+            var dF = dateFormat, mask = maskp, date = datep, utc = utcp;
+            if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
+                mask = date;
+                date = undefined;
+            }
+            date = date ? new Date(date) : new Date();
+            if (isNaN(date)) throw SyntaxError("invalid date");
+            mask = String(dF.masks[mask] || mask || dF.masks["default"]);
+            if (mask.slice(0, 4) == "UTC:") {
+                mask = mask.slice(4);
+                utc = true;
+            }
+            var _ = utc ? "getUTC" : "get", d = date[_ + "Date"](), D = getDay(date), M = date[_ + "Month"](), y = date[_ + "FullYear"](), H = date[_ + "Hours"](), m = date[_ + "Minutes"](), s = date[_ + "Seconds"](), L = date[_ + "Milliseconds"](), o = utc ? 0 : date.getTimezoneOffset(), flags = {
+                d: d,
+                dd: pad(d),
+                ddd: dF.i18n.dayNames[D],
+                dddd: dF.i18n.dayNames[D + 7],
+                M: M + 1,
+                MM: pad(M + 1),
+                MMM: dF.i18n.monthNames[M],
+                MMMM: dF.i18n.monthNames[M + 12],
+                yy: String(y).slice(2),
+                yyyy: y,
+                h: H % 12 || 12,
+                hh: pad(H % 12 || 12),
+                H: H,
+                HH: pad(H),
+                m: m,
+                mm: pad(m),
+                s: s,
+                ss: pad(s),
+                l: pad(L, 3),
+                L: pad(L > 99 ? Math.round(L / 10) : L),
+                t: H < 12 ? "a" : "p",
+                tt: H < 12 ? "am" : "pm",
+                T: H < 12 ? "A" : "P",
+                TT: H < 12 ? "AM" : "PM",
+                Z: utc ? "UTC" : processTZ(date),
+                o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
+                S: [ "th", "st", "nd", "rd" ][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
+            };
+            return mask.replace(token, function($0) {
+                return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
+            });
+        };
+    }();
+    dateFormat.masks = {
+        "default": "dd MMMM yyyy HH:mm:ss Z",
+        shortDate: "M/d/yy",
+        mediumDate: "MMM d, yyyy",
+        longDate: "d MMMM yyyy",
+        fullDate: "dddd, MMMM d, yyyy",
+        shortTime: "h:mm TT",
+        mediumTime: "h:mm:ss TT",
+        longTime: "h:mm:ss TT Z",
+        isoDate: "yyyy-MM-dd",
+        isoTime: "HH:mm:ss",
+        isoDateTime: "yyyy-MM-dd'T'HH:mm:ss",
+        isoUtcDateTime: "UTC:yyyy-MM-dd'T'HH:mm:ss'Z'"
+    };
+    dateFormat.i18n = {
+        dayNames: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
+        monthNames: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]
+    };
+    Date.prototype.format = function(mask, utc) {
+        return dateFormat(this, mask, utc);
+    };
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        create: createProxy,
+        createNow: createNow,
+        createNowForTimeZone: createNow,
+        createToday: createToday,
+        createTodayForTimeZone: createToday,
+        format: format,
+        dateFormat: dateFormat,
+        arrayFormat: arrayFormat,
+        listFormat: arrayFormat,
+        setFormat: setFormat,
+        day: day,
+        arrayDay: arrayDay,
+        listDay: arrayDay,
+        setDay: setDay,
+        month: month,
+        arrayMonth: arrayMonth,
+        listMonth: arrayMonth,
+        setMonth: setMonth,
+        monthName: monthName,
+        arrayMonthName: arrayMonthName,
+        listMonthName: arrayMonthName,
+        setMonthName: setMonthName,
+        monthNameShort: monthNameShort,
+        arrayMonthNameShort: arrayMonthNameShort,
+        listMonthNameShort: arrayMonthNameShort,
+        setMonthNameShort: setMonthNameShort,
+        year: year,
+        arrayYear: arrayYear,
+        listYear: arrayYear,
+        setYear: setYear,
+        dayOfWeek: dayOfWeek,
+        arrayDayOfWeek: arrayDayOfWeek,
+        listDayOfWeek: arrayDayOfWeek,
+        setDayOfWeek: setDayOfWeek,
+        dayOfWeekName: dayOfWeekName,
+        arrayDayOfWeekName: arrayDayOfWeekName,
+        listDayOfWeekName: arrayDayOfWeekName,
+        setDayOfWeekName: setDayOfWeekName,
+        dayOfWeekNameShort: dayOfWeekNameShort,
+        arrayDayOfWeekNameShort: arrayDayOfWeekNameShort,
+        listDayOfWeekNameShort: arrayDayOfWeekNameShort,
+        setDayOfWeekNameShort: setDayOfWeekNameShort,
+        hour: hour,
+        arrayHour: arrayHour,
+        listHour: arrayHour,
+        setHour: setHour,
+        minute: minute,
+        arrayMinute: arrayMinute,
+        listMinute: arrayMinute,
+        setMinute: setMinute,
+        second: second,
+        arraySecond: arraySecond,
+        listSecond: arraySecond,
+        setSecond: setSecond,
+        millisecond: millisecond,
+        arrayMillisecond: arrayMillisecond,
+        listMillisecond: arrayMillisecond,
+        setMillisecond: setMillisecond
+    };
+}();
+
+thymol.objects.thCalendarsObject = function() {
+    var thExpressionObjectName = "#calendars";
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        create: thymol.objects.thDatesObject.create,
+        createNow: thymol.objects.thDatesObject.createNow,
+        createNowForTimeZone: thymol.objects.thDatesObject.createNow,
+        createToday: thymol.objects.thDatesObject.createToday,
+        createTodayForTimeZone: thymol.objects.thDatesObject.createToday,
+        format: thymol.objects.thDatesObject.format,
+        dateFormat: thymol.objects.thDatesObject.dateFormat,
+        arrayFormat: thymol.objects.thDatesObject.arrayFormat,
+        listFormat: thymol.objects.thDatesObject.arrayFormat,
+        setFormat: thymol.objects.thDatesObject.setFormat,
+        day: thymol.objects.thDatesObject.day,
+        arrayDay: thymol.objects.thDatesObject.arrayDay,
+        listDay: thymol.objects.thDatesObject.arrayDay,
+        setDay: thymol.objects.thDatesObject.setDay,
+        month: thymol.objects.thDatesObject.month,
+        arrayMonth: thymol.objects.thDatesObject.arrayMonth,
+        listMonth: thymol.objects.thDatesObject.arrayMonth,
+        setMonth: thymol.objects.thDatesObject.setMonth,
+        monthName: thymol.objects.thDatesObject.monthName,
+        arrayMonthName: thymol.objects.thDatesObject.arrayMonthName,
+        listMonthName: thymol.objects.thDatesObject.arrayMonthName,
+        setMonthName: thymol.objects.thDatesObject.setMonthName,
+        monthNameShort: thymol.objects.thDatesObject.monthNameShort,
+        arrayMonthNameShort: thymol.objects.thDatesObject.arrayMonthNameShort,
+        listMonthNameShort: thymol.objects.thDatesObject.arrayMonthNameShort,
+        setMonthNameShort: thymol.objects.thDatesObject.setMonthNameShort,
+        year: thymol.objects.thDatesObject.year,
+        arrayYear: thymol.objects.thDatesObject.arrayYear,
+        listYear: thymol.objects.thDatesObject.arrayYear,
+        setYear: thymol.objects.thDatesObject.setYear,
+        dayOfWeek: thymol.objects.thDatesObject.dayOfWeek,
+        arrayDayOfWeek: thymol.objects.thDatesObject.arrayDayOfWeek,
+        listDayOfWeek: thymol.objects.thDatesObject.arrayDayOfWeek,
+        setDayOfWeek: thymol.objects.thDatesObject.setDayOfWeek,
+        dayOfWeekName: thymol.objects.thDatesObject.dayOfWeekName,
+        arrayDayOfWeekName: thymol.objects.thDatesObject.arrayDayOfWeekName,
+        listDayOfWeekName: thymol.objects.thDatesObject.arrayDayOfWeekName,
+        setDayOfWeekName: thymol.objects.thDatesObject.setDayOfWeekName,
+        dayOfWeekNameShort: thymol.objects.thDatesObject.dayOfWeekNameShort,
+        arrayDayOfWeekNameShort: thymol.objects.thDatesObject.arrayDayOfWeekNameShort,
+        listDayOfWeekNameShort: thymol.objects.thDatesObject.arrayDayOfWeekNameShort,
+        setDayOfWeekNameShort: thymol.objects.thDatesObject.setDayOfWeekNameShort,
+        hour: thymol.objects.thDatesObject.hour,
+        arrayHour: thymol.objects.thDatesObject.arrayHour,
+        listHour: thymol.objects.thDatesObject.arrayHour,
+        setHour: thymol.objects.thDatesObject.setHour,
+        minute: thymol.objects.thDatesObject.minute,
+        arrayMinute: thymol.objects.thDatesObject.arrayMinute,
+        listMinute: thymol.objects.thDatesObject.arrayMinute,
+        setMinute: thymol.objects.thDatesObject.setMinute,
+        second: thymol.objects.thDatesObject.second,
+        arraySecond: thymol.objects.thDatesObject.arraySecond,
+        listSecond: thymol.objects.thDatesObject.arraySecond,
+        setSecond: thymol.objects.thDatesObject.setSecond,
+        millisecond: thymol.objects.thDatesObject.millisecond,
+        arrayMillisecond: thymol.objects.thDatesObject.arrayMillisecond,
+        listMillisecond: thymol.objects.thDatesObject.arrayMillisecond,
+        setMillisecond: thymol.objects.thDatesObject.setMillisecond
+    };
+}();
+
+thymol.objects.thIdsObject = function() {
+    var thExpressionObjectName = "#ids";
+    function seq(id) {
+        if (id !== null) {
+            var str = id.toString();
+            var idCount = getLocal(str);
+            var result = str + idCount;
+            idCount++;
+            setLocal(str, idCount);
+            return result;
+        }
+        throw new thymol.ThError("#ids.seq ID Cannot be null");
+    }
+    function next(id) {
+        if (id !== null) {
+            var str = id.toString();
+            var idCount = getLocal(str);
+            return str + idCount;
+        }
+        throw new thymol.ThError("#ids.next ID Cannot be null");
+    }
+    function prev(id) {
+        if (id !== null) {
+            var str = id.toString();
+            var idCount = getLocal(str);
+            return str + (idCount - 1);
+        }
+        throw new thymol.ThError("#ids.prev ID Cannot be null");
+    }
+    function setLocal(str, idCount) {
+        if (!thymol.objects.thIdsObject.thLocalVars) {
+            thymol.objects.thIdsObject.thLocalVars = [];
+        }
+        if (!thymol.objects.thIdsObject.thLocalVars["thIdCounts"]) {
+            thymol.objects.thIdsObject.thLocalVars["thIdCounts"] = [];
+        }
+        thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str] = idCount;
+    }
+    function getLocal(str) {
+        if (!thymol.objects.thIdsObject.thLocalVars) {
+            thymol.objects.thIdsObject.thLocalVars = [];
+        }
+        if (!thymol.objects.thIdsObject.thLocalVars["thIdCounts"]) {
+            thymol.objects.thIdsObject.thLocalVars["thIdCounts"] = [];
+        }
+        if (!thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str]) {
+            thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str] = 1;
+        }
+        return thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str];
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        seq: seq,
+        next: next,
+        prev: prev
+    };
+}();
+
+thymol.objects.thListsObject = function() {
+    var thExpressionObjectName = "#lists";
+    function sort(list, comparator) {
+        if (list !== null) {
+            if (arguments.length > 1) {
+                if (comparator !== null) {
+                    if (typeof comparator === "function") {
+                        return list.sort(comparator);
+                    }
+                    throw new thymol.ThError("#lists.sort Cannot execute list sort: comparator is not a function");
+                }
+                throw new thymol.ThError("#lists.sort Cannot execute list sort: comparator is null");
+            }
+            return list.sort();
+        }
+        throw new thymol.ThError("#lists.sort Cannot execute list sort: list is null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        toList: thymol.objects.thArraysObject.toArray,
+        size: thymol.objects.thArraysObject.length,
+        isEmpty: thymol.objects.thArraysObject.isEmpty,
+        contains: thymol.objects.thArraysObject.contains,
+        containsAll: thymol.objects.thArraysObject.containsAll,
+        sort: sort
+    };
+}();
+
+thymol.objects.thMapsObject = function() {
+    var thExpressionObjectName = "#maps";
+    function size(target) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                return target.size();
+            }
+            throw new thymol.ThError('#maps.size Cannot get size of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.size Cannot get size of null");
+    }
+    function isEmpty(target) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                return target.isEmpty();
+            }
+            throw new thymol.ThError('#maps.size Cannot get isEmpty of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.size Cannot get isEmpty of null");
+    }
+    function containsKey(target, key) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                return target.containsKey(key);
+            }
+            throw new thymol.ThError('#maps.size Cannot get containsKey of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.containsKey Cannot execute map containsKey: target is null");
+    }
+    function containsValue(target, value) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                return target.containsValue(value);
+            }
+            throw new thymol.ThError('#maps.size Cannot get containsValue of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.containsKey Cannot execute map containsValue: target is null");
+    }
+    function containsAllKeys(target, keys) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                var ptc = Object.prototype.toString.call(keys);
+                if (keys instanceof thymol.ThSet || keys instanceof Array || ptc === "[object Array]") {
+                    return target.containsAll(keys);
+                }
+                throw new thymol.ThError('#maps.size Cannot get containsAllKeys with non-collection type "' + ptc + '"');
+            }
+            throw new thymol.ThError('#maps.size Cannot get containsAllKeys of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.containsKey Cannot execute map containsAllKeys: target is null");
+    }
+    function containsAllValues(target, values) {
+        if (target !== null) {
+            if (target instanceof thymol.ThMap) {
+                var ptc = Object.prototype.toString.call(values);
+                if (values instanceof thymol.ThSet || values instanceof Array || ptc === "[object Array]") {
+                    var vArray = values;
+                    if (values instanceof thymol.ThSet) {
+                        vArray = values.toArray();
+                    }
+                    for (var i = 0, iLimit = vArray.length; i < iLimit; i++) {
+                        var found = false;
+                        for (var k in target) {
+                            if (target.hasOwnProperty(k)) {
+                                var value = target[k];
+                                if (value === vArray[i]) {
+                                    found = true;
+                                    break;
+                                }
+                            }
+                        }
+                        if (!found) {
+                            return false;
+                        }
+                    }
+                    return true;
+                }
+                throw new thymol.ThError('#maps.size Cannot get containsAllValues with non-collection type "' + ptc + '"');
+            }
+            throw new thymol.ThError('#maps.size Cannot get containsAllValues of non-map type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#maps.containsKey Cannot execute map containsAllValues: target is null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        size: size,
+        isEmpty: isEmpty,
+        containsKey: containsKey,
+        containsValue: containsValue,
+        containsAllKeys: containsAllKeys,
+        containsAllValues: containsAllValues
+    };
+}();
+
+thymol.objects.thMessagesObject = function() {
+    var thExpressionObjectName = "#messages";
+    function msg() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return msgWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.msg Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.msg Target cannot be null");
+    }
+    function msgWithParams(target, params) {
+        if (target !== null) {
+            return thymol.getMessage(target, params, true);
+        }
+        throw new thymol.ThError("#messages.msgWithParams Target cannot be null");
+    }
+    function msgOrNull() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return msgOrNullWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.msgOrNull Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.msgOrNull Target cannot be null");
+    }
+    function msgOrNullWithParams(target, params) {
+        if (target !== null) {
+            return thymol.getMessage(target, params, false);
+        }
+        throw new thymol.ThError("#messages.msgOrNullWithParams Target cannot be null");
+    }
+    function arrayMsg() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return arrayMsgWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.arrayMsg Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.arrayMsg Target cannot be null");
+    }
+    function arrayMsgWithParams(target, params) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(msgWithParams(target[i], params));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#messages.arrayMsgWithParams Target cannot be null");
+    }
+    function setMsg() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return setMsgWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.setMsg Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.setMsg Target cannot be null");
+    }
+    function setMsgWithParams(target, params) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(msgWithParams(target[k], params));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#messages.setMsgWithParams Target cannot be null");
+    }
+    function arrayMsgOrNull() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return arrayMsgOrNullWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.arrayMsgOrNull Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.arrayMsgOrNull Target cannot be null");
+    }
+    function arrayMsgOrNullWithParams(target, params) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(msgOrNullWithParams(target[i], params));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#messages.arrayMsgOrNullWithParams Target cannot be null");
+    }
+    function setMsgOrNull() {
+        if (arguments !== null) {
+            if (arguments.length > 0) {
+                return setMsgOrNullWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
+            }
+            throw new thymol.ThError("#messages.setMsgOrNull Invoked with no arguments!");
+        }
+        throw new thymol.ThError("#messages.setMsgOrNull Target cannot be null");
+    }
+    function setMsgOrNullWithParams(target, params) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(msgOrNullWithParams(target[k], params));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#messages.setMsgOrNullWithParams Target cannot be null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        msg: msg,
+        msgWithParams: msgWithParams,
+        msgOrNull: msgOrNull,
+        msgOrNullWithParams: msgOrNullWithParams,
+        arrayMsg: arrayMsg,
+        listMsg: arrayMsg,
+        setMsg: setMsg,
+        arrayMsgWithParams: arrayMsgWithParams,
+        listMsgWithParams: arrayMsgWithParams,
+        setMsgWithParams: setMsgWithParams,
+        arrayMsgOrNull: arrayMsgOrNull,
+        listMsgOrNull: arrayMsgOrNull,
+        setMsgOrNull: setMsgOrNull,
+        arrayMsgOrNullWithParams: arrayMsgOrNullWithParams,
+        listMsgOrNullWithParams: arrayMsgOrNullWithParams,
+        setMsgOrNullWithParams: setMsgOrNullWithParams
+    };
+}();
+
+thymol.objects.thNumbersObject = function() {
+    var thExpressionObjectName = "#numbers";
+    var DEFAULT_THOU_PT = ",";
+    var DEFAULT_DECI_PT = ".";
+    var DEFAULT_NONE_PT = "?";
+    function formatDecimalProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 4) {
+                return formatDecimal5(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
+            } else if (arguments.length > 3) {
+                return formatDecimal4(arguments[0], arguments[1], arguments[2], arguments[3]);
+            }
+            return formatDecimal3(arguments[0], arguments[1], arguments[2]);
+        }
+    }
+    function formatIntegerProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 4) {
+                return formatDecimal5(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
+            } else if (arguments.length > 3) {
+                return formatDecimal5(arguments[0], arguments[1], "NONE", arguments[2], arguments[3]);
+            } else if (arguments.length > 2) {
+                if (typeof arguments[2] === "string") {
+                    return formatDecimal5(arguments[0], arguments[1], arguments[2], 0, "POINT");
+                }
+                return formatDecimal5(arguments[0], arguments[1], "NONE", arguments[2], "POINT");
+            } else {
+                return formatDecimal5(arguments[0], arguments[1], "NONE", 0, "POINT");
+            }
+        }
+    }
+    function arrayFormatIntegerProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 2) {
+                return arrayFormatDecimal(arguments[0], arguments[1], arguments[2], 0, "POINT");
+            }
+            return arrayFormatDecimal(arguments[0], arguments[1], "NONE", 0, "POINT");
+        }
+    }
+    function setFormatIntegerProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 2) {
+                return setFormatDecimal(arguments[0], arguments[1], arguments[2], 0, "POINT");
+            }
+            return setFormatDecimal(arguments[0], arguments[1], "NONE", 0, "POINT");
+        }
+    }
+    function arrayFormatDecimalProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 4) {
+                return arrayFormatDecimal(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
+            } else if (arguments.length > 3) {
+                return arrayFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], arguments[3]);
+            }
+            return arrayFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], "POINT");
+        }
+    }
+    function setFormatDecimalProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 4) {
+                return setFormatDecimal(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
+            } else if (arguments.length > 3) {
+                return setFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], arguments[3]);
+            }
+            return setFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], "POINT");
+        }
+    }
+    function sequenceProxy() {
+        if (arguments !== null) {
+            if (arguments.length > 2) {
+                return sequence(arguments[0], arguments[1], arguments[2]);
+            }
+            return sequence(arguments[0], arguments[1], 1);
+        }
+    }
+    function getIntegerDigits(val) {
+        var s = val.toString();
+        var digits = s.length;
+        var dp = s.indexOf(".");
+        if (dp > 0) {
+            digits = dp;
+        }
+        return digits;
+    }
+    function formatDecimal3(target, minIntegerDigits, decimalDigits) {
+        var result = target.toString();
+        var value = new Number(target);
+        value = value.toFixed(decimalDigits);
+        if (minIntegerDigits > 0) {
+            result = value;
+            value = new Number(value);
+            var a = Math.abs(value);
+            if (a < Math.pow(10, minIntegerDigits)) {
+                if (target < 0) {
+                    result = result.substring(1);
+                }
+                var p = getIntegerDigits(a);
+                var x = minIntegerDigits - p;
+                if (x > 0) {
+                    for (var i = 0; i < x; i++) {
+                        result = "0" + result;
+                    }
+                }
+                if (target < 0) {
+                    result = "-" + result;
+                }
+            }
+        } else {
+            result = value.toString();
+        }
+        result = new String(result);
+        result.precision = decimalDigits;
+        return result;
+    }
+    function formatDecimal4(target, minIntegerDigits, decimalDigits, decimalPointType) {
+        var result = formatDecimal3(target, minIntegerDigits, decimalDigits);
+        var decimalPoint;
+        if ("DEFAULT" === decimalPointType) {
+            decimalPoint = DEFAULT_DECI_PT;
+        } else if ("NONE" === decimalPointType) {
+            decimalPoint = DEFAULT_NONE_PT;
+        } else {
+            decimalPoint = getPointType(decimalPointType);
+        }
+        if ("." !== decimalPoint) {
+            result = result.replace(".", decimalPoint, "g");
+        }
+        return result;
+    }
+    function formatDecimal5(target, minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType) {
+        var result = target.toString();
+        var decimalPoint;
+        if ("DEFAULT" === decimalPointType) {
+            decimalPoint = DEFAULT_DECI_PT;
+        } else if ("NONE" === decimalPointType) {
+            decimalPoint = DEFAULT_NONE_PT;
+        } else {
+            decimalPoint = getPointType(decimalPointType);
+        }
+        if ("" !== decimalPoint) {
+            result = formatDecimal4(target, minIntegerDigits, decimalDigits, decimalPointType);
+        } else {
+            result = formatDecimal3(target, minIntegerDigits, decimalDigits);
+        }
+        var thousandsPoint;
+        if ("DEFAULT" === thousandsPointType) {
+            thousandsPoint = DEFAULT_THOU_PT;
+        } else {
+            thousandsPoint = getPointType(thousandsPointType);
+        }
+        if ("" !== thousandsPoint) {
+            result = addThousandsPointType(result.toString(), decimalPoint, thousandsPoint);
+        }
+        return result;
+    }
+    function getPointType(type) {
+        var result = ".";
+        if ("COMMA" === type) {
+            result = ",";
+        } else if ("WHITESPACE" === type) {
+            result = " ";
+        } else if ("NONE" === type) {
+            result = "";
+        }
+        return result;
+    }
+    function arrayFormatDecimal(target, minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType) {
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(formatDecimal5(target[i], minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType));
+        }
+        return result;
+    }
+    function setFormatDecimal(target, minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType) {
+        var result = new thymol.ThSet();
+        for (var k in target) {
+            if (target.hasOwnProperty(k) && typeof target[k] !== "function") {
+                result.add(formatDecimal5(target[k], minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType));
+            }
+        }
+        return result;
+    }
+    function addThousandsPointType(nStr, dpt, tpt) {
+        var x = nStr.split(dpt);
+        var x1 = x[0];
+        var x2 = x.length > 1 ? dpt + x[1] : "";
+        var rgx = /(\d+)(\d{3})/;
+        while (rgx.test(x1)) {
+            x1 = x1.replace(rgx, "$1" + tpt + "$2");
+        }
+        return x1 + x2;
+    }
+    function sequence(start, stop, step) {
+        var result = [];
+        if (step > 0) {
+            var value = start;
+            if (start <= stop) {
+                do {
+                    result.push(value);
+                    value += step;
+                } while (value <= stop);
+            } else {
+                do {
+                    result.push(value);
+                    value -= step;
+                } while (value >= stop);
+            }
+        }
+        return result;
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        formatDecimal: formatDecimalProxy,
+        formatInteger: formatIntegerProxy,
+        arrayFormatInteger: arrayFormatIntegerProxy,
+        arrayFormatDecimal: arrayFormatDecimalProxy,
+        listFormatInteger: arrayFormatIntegerProxy,
+        listFormatDecimal: arrayFormatDecimalProxy,
+        setFormatInteger: setFormatIntegerProxy,
+        setFormatDecimal: setFormatDecimalProxy,
+        sequence: sequenceProxy
+    };
+}();
+
+thymol.objects.thObjectsObject = function() {
+    var thExpressionObjectName = "#objects";
+    function nullSafe(target, defaultValue) {
+        return target != null ? target : defaultValue;
+    }
+    function arrayNullSafe(target, defaultValue) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(nullSafe(target[i], defaultValue));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#objects.arrayNullSafe Target cannot be null");
+    }
+    function setNullSafe(target, defaultValue) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(nullSafe(target[k], defaultValue));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#objects.setNullSafe Target cannot be null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        nullSafe: nullSafe,
+        arrayNullSafe: arrayNullSafe,
+        listNullSafe: arrayNullSafe,
+        setNullSafe: setNullSafe
+    };
+}();
+
+thymol.objects.thSetsObject = function() {
+    var thExpressionObjectName = "#sets";
+    function toSet(target) {
+        if (target !== null) {
+            var tt = typeof target;
+            var ptc = Object.prototype.toString.call(target);
+            var result;
+            if (tt === "thymol.ThSet") {
+                result = target;
+            }
+            if (tt === "Array" || ptc === "[object Array]") {
+                result = thymol.ThSet.prototype.fromArray(target);
+            } else if (tt === "object") {
+                result = new thymol.ThSet();
+                for (var k in target) {
+                    var value = target[k];
+                    var process = false;
+                    if (value !== null) {
+                        if (target instanceof thymol.ThSet) {
+                            process = target.isContent(k);
+                        } else {
+                            process = target.hasOwnProperty(k) && typeof value !== "function";
+                        }
+                    }
+                    if (process) {
+                        result.add(value);
+                    }
+                }
+            } else {
+                throw new thymol.ThError('#sets.toSet Cannot convert object of type "' + tt + '" to a set');
+            }
+            return result;
+        }
+        throw new thymol.ThError("#sets.toSet Cannot convert null to set");
+    }
+    function size(target) {
+        if (target !== null) {
+            if (target instanceof thymol.ThSet) {
+                return target.size();
+            }
+            throw new thymol.ThError('#sets.size Cannot get size of non-set type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#sets.size Cannot get size of null");
+    }
+    function isEmpty(target) {
+        if (target !== null) {
+            if (target instanceof thymol.ThSet) {
+                return target.isEmpty();
+            }
+            throw new thymol.ThError('#sets.size Cannot get isEmpty of non-set type "' + typeof target + '"');
+        }
+        throw new thymol.ThError("#sets.size Cannot get isEmpty of null");
+    }
+    function contains(target, element) {
+        if (target !== null) {
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    if (target[k] === null) {
+                        if (element === null) {
+                            return true;
+                        }
+                    } else if (element !== null && target[k] === element) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+        throw new thymol.ThError("#sets.contains Cannot execute sets contains: target is null");
+    }
+    function containsAll(target, elements) {
+        if (target !== null) {
+            if (elements !== null) {
+                var elementsArray;
+                if (elements instanceof Array) {
+                    elementsArray = [].concat(elements);
+                } else {
+                    if (elements instanceof thymol.ThSet) {
+                        elementsArray = elements.toArray();
+                    } else {
+                        elementsArray = [];
+                        for (var k in elements) {
+                            if (elements.hasOwnProperty(k) && typeof elements[k] !== "function") {
+                                elementsArray.push(elements[k]);
+                            }
+                        }
+                    }
+                }
+                for (var k in target) {
+                    if (target.isContent(k)) {
+                        for (var j = 0, jLimit = elementsArray.length; j < jLimit; j++) {
+                            if (target[k] === elementsArray[j]) {
+                                elementsArray.splice(j, 1);
+                            }
+                        }
+                    }
+                }
+                return elementsArray.length === 0;
+            }
+            throw new thymol.ThError("#sets.containsAll Cannot execute sets containsAll: elements is null");
+        }
+        throw new thymol.ThError("#sets.containsAll Cannot execute sets containsAll: target is null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        toSet: toSet,
+        size: size,
+        isEmpty: isEmpty,
+        contains: contains,
+        containsAll: containsAll
+    };
+}();
+
+thymol.objects.thStringsObject = function() {
+    var thExpressionObjectName = "#strings";
+    function toString(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString();
+        }
+        return result;
+    }
+    function arrayToString(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(target[i].toString());
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setToString(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(toString(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    function abbreviate(target, maxSize, source) {
+        if (maxSize >= 3) {
+            var result = null;
+            if (target !== null && typeof target !== "undefined") {
+                result = target.toString();
+                if (result.length > maxSize) {
+                    result = result.substring(0, maxSize - 3) + "...";
+                }
+            }
+            return result;
+        }
+        throwAbbreviateException("abbreviate", maxSize);
+    }
+    function arrayAbbreviate(target, maxSize) {
+        if (maxSize >= 3) {
+            var result = null;
+            if (target !== null && typeof target !== "undefined") {
+                result = [];
+                for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                    result.push(abbreviate(target[i], maxSize));
+                }
+            }
+            return result;
+        }
+        throwAbbreviateException("arrayAbbreviate", maxSize);
+    }
+    function setAbbreviate(target, maxSize) {
+        if (maxSize >= 3) {
+            var result = null;
+            if (target !== null && typeof target !== "undefined") {
+                result = new thymol.ThSet();
+                for (var k in target) {
+                    if (target.isContent(k)) {
+                        result.add(abbreviate(target[k], maxSize));
+                    }
+                }
+            }
+            return result;
+        }
+        throwAbbreviateException("setAbbreviate", maxSize);
+    }
+    function throwAbbreviateException(source, maxSize) {
+        throw new thymol.ThError("#strings." + source + ' Maximum size must be greater than or equal to 3 but was: "' + maxSize + '"');
+    }
+    function equals(o1, o2) {
+        if (o1 === null) {
+            return o2 === null;
+        } else if (o2 !== null) {
+            return o1.toString() === o2.toString();
+        }
+        return false;
+    }
+    function equalsIgnoreCase(o1, o2) {
+        if (o1 === null) {
+            return o2 === null;
+        } else if (o2 !== null) {
+            return o1.toString().toLowerCase() === o2.toString().toLowerCase();
+        }
+        return false;
+    }
+    function contains(target, fragment) {
+        if (target !== null) {
+            if (fragment !== null) {
+                return target.toString().indexOf(fragment) >= 0;
+            }
+            throw new thymol.ThError("#strings.contains Fragment cannot be null");
+        }
+        throw new thymol.ThError("#strings.contains Cannot apply contains on null");
+    }
+    function arrayContains(target, fragment) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(contains(target[i], fragment));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayContains Cannot apply arrayContains on null");
+    }
+    function setContains(target, fragment) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(contains(target[k], fragment));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setContains Cannot apply setContains on null");
+    }
+    function containsIgnoreCase(target, fragment) {
+        if (target !== null) {
+            if (fragment !== null) {
+                return target.toString().toLowerCase().indexOf(fragment.toLowerCase()) >= 0;
+            }
+            throw new thymol.ThError("#strings.containsIgnoreCase Fragment cannot be null");
+        }
+        throw new thymol.ThError("#strings.containsIgnoreCase Cannot apply containsIgnoreCase on null");
+    }
+    function arrayContainsIgnoreCase(target, fragment) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(containsIgnoreCase(target[i], fragment));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayContainsIgnoreCase Cannot apply arrayContainsIgnoreCase on null");
+    }
+    function setContainsIgnoreCase(target, fragment) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(containsIgnoreCase(target[k], fragment));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setContainsIgnoreCase Cannot apply setContainsIgnoreCase on null");
+    }
+    function startsWith(target, prefix) {
+        if (target !== null) {
+            if (prefix !== null) {
+                return target.toString().indexOf(prefix) === 0;
+            }
+            throw new thymol.ThError("#strings.startsWith Prefix cannot be null");
+        }
+        throw new thymol.ThError("#strings.startsWith Cannot apply startsWith on null");
+    }
+    function arrayStartsWith(target, prefix) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(startsWith(target[i], prefix));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayStartsWith Target cannot be null");
+    }
+    function setStartsWith(target, prefix) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(startsWith(target[k], prefix));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setStartsWith Target cannot be null");
+    }
+    function endsWith(target, suffix) {
+        if (target !== null) {
+            if (suffix !== null) {
+                var str = target.toString();
+                return str.indexOf(suffix) === str.length - suffix.length;
+            }
+            throw new thymol.ThError("#strings.startsWith Suffix cannot be null");
+        }
+        throw new thymol.ThError("#strings.endsWith Cannot apply endsWith on null");
+    }
+    function arrayEndsWith(target, suffix) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(endsWith(target[i], suffix));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayEndsWith Target cannot be null");
+    }
+    function setEndsWith(target, suffix) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(endsWith(target[k], suffix));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setEndsWith Target cannot be null");
+    }
+    function substring(target, start, end) {
+        if (target !== null) {
+            return target.toString().substring(start, end);
+        }
+        throw new thymol.ThError("#strings.substring Target cannot be null");
+    }
+    function arraySubstring(target, start, end) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(substring(target[i], start, end));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arraySubstring Target cannot be null");
+    }
+    function setSubstring(target, start, end) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(substring(target[k], start, end));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setSubstring Target cannot be null");
+    }
+    function substringAfter(target, substr) {
+        if (target !== null) {
+            if (substr !== null) {
+                var str = target.toString();
+                var indx = str.indexOf(substr);
+                if (indx < 0) {
+                    return null;
+                }
+                return str.substring(indx + substr.length);
+            }
+            throw new thymol.ThError("#strings.substringAfter Parameter substring cannot be null");
+        }
+        throw new thymol.ThError("#strings.substringAfter Cannot apply substringAfter on null");
+    }
+    function arraySubstringAfter(target, substr) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(substringAfter(target[i], substr));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arraySubstringAfter Cannot apply arraySubstringAfter on null");
+    }
+    function setSubstringAfter(target, substr) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(substringAfter(target[k], substr));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setSubstringAfter Cannot apply setSubstringAfter on null");
+    }
+    function substringBefore(target, substr) {
+        if (target !== null) {
+            if (substr !== null) {
+                var str = target.toString();
+                var indx = str.indexOf(substr);
+                if (indx < 0) {
+                    return null;
+                }
+                return str.substring(0, indx);
+            }
+            throw new thymol.ThError("#strings.substringBefore Parameter substring cannot be null");
+        }
+        throw new thymol.ThError("#strings.substringBefore Cannot apply substringBefore on null");
+    }
+    function arraySubstringBefore(target, substr) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(substringBefore(target[i], substr));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arraySubstringBefore Cannot apply arraySubstringBefore on null");
+    }
+    function setSubstringBefore(target, substr) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(substringBefore(target[k], substr));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setSubstringBefore Cannot apply setSubstringBefore on null");
+    }
+    function prepend(target, prefix) {
+        if (target !== null) {
+            if (prefix !== null) {
+                return prefix.toString() + target.toString();
+            }
+            throw new thymol.ThError("#strings.prepend Prefix cannot be null");
+        }
+        throw new thymol.ThError("#strings.prepend Cannot apply prepend on null");
+    }
+    function arrayPrepend(target, prefix) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(prepend(target[i], prefix));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayPrepend Cannot apply arrayPrepend on null");
+    }
+    function setPrepend(target, prefix) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(prepend(target[k], prefix));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setPrepend Cannot apply setPrepend on null");
+    }
+    function repeat(target, times) {
+        var result = "";
+        for (var i = 0; i < times; i++) {
+            result += target.toString();
+        }
+        return result;
+    }
+    function append(target, suffix) {
+        if (target !== null) {
+            if (suffix !== null) {
+                return target.toString() + suffix.toString();
+            }
+            throw new thymol.ThError("#strings.append Suffix cannot be null");
+        }
+        throw new thymol.ThError("#strings.append Cannot apply append on null");
+    }
+    function concat() {
+        var result = "";
+        for (var i = 0, iLimit = arguments.length; i < iLimit; i++) {
+            if (arguments[i] !== null) {
+                result += arguments[i];
+            }
+        }
+        return result;
+    }
+    function concatReplaceNulls() {
+        var result = "";
+        for (var i = 1, iLimit = arguments.length; i < iLimit; i++) {
+            if (arguments[i] === null) {
+                result += arguments[0];
+            } else {
+                result += arguments[i];
+            }
+        }
+        return result;
+    }
+    function arrayAppend(target, suffix) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(append(target[i], suffix));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayAppend Target cannot be null");
+    }
+    function setAppend(target, suffix) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(append(target[k], suffix));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setAppend Target cannot be null");
+    }
+    function indexOf(target, fragment) {
+        if (target !== null) {
+            if (fragment !== null) {
+                var str = target.toString();
+                var indx = str.indexOf(fragment);
+                return indx;
+            }
+            throw new thymol.ThError("#strings.indexOf Fragment cannot be null");
+        }
+        throw new thymol.ThError("#strings.indexOf Cannot apply indexOf on null");
+    }
+    function arrayIndexOf(target, fragment) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(indexOf(target[i], fragment));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayIndexOf Cannot apply arrayIndexOf on null");
+    }
+    function setIndexOf(target, fragment) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(indexOf(target[k], fragment));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setIndexOf Cannot apply setIndexOf on null");
+    }
+    function isEmpty(target) {
+        if (target !== null) {
+            var str = target.toString();
+            if (str !== null) {
+                str = str.replace(/(?:[\\]t)/g, "      ").replace(/(?:[\\]n)/g, "\n").replace(/(?:[\\]v)/g, "\v").replace(/(?:[\\]f)/g, "\f").replace(/(?:[\\]r)/g, "\r");
+                str = str.trim();
+                if (str.length !== 0) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+    function arrayIsEmpty(target) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(isEmpty(target[i]));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayIsEmpty Target cannot be null");
+    }
+    function setIsEmpty(target) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(isEmpty(target[k]));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setIsEmpty Target cannot be null");
+    }
+    function arrayJoin(stringArray, separator) {
+        if (stringArray !== null) {
+            if (separator !== null) {
+                var sepStr = separator.toString();
+                var result = "";
+                for (var i = 0, iLimit = stringArray.length; i < iLimit; i++) {
+                    if ("" !== result) {
+                        result += sepStr;
+                    }
+                    result += stringArray[i];
+                }
+                return result;
+            }
+            throw new thymol.ThError("#strings.arrayJoin Separator cannot be null");
+        }
+        throw new thymol.ThError("#strings.arrayJoin Cannot apply join on null");
+    }
+    function setJoin(stringSet, separator) {
+        if (stringSet !== null) {
+            if (separator !== null) {
+                var sepStr = separator.toString();
+                var result = "";
+                for (var k in stringSet) {
+                    if (stringSet.isContent(k)) {
+                        if ("" !== result) {
+                            result += sepStr;
+                        }
+                        result += stringSet[k];
+                    }
+                }
+                return result;
+            }
+            throw new thymol.ThError("#strings.setJoin Separator cannot be null");
+        }
+        throw new thymol.ThError("#strings.setJoin Cannot apply join on null");
+    }
+    function doRegExpify(target, flags) {
+        var result = target.toString();
+        result = result.replace(/[\\]/g, "\\").replace(/[\^]/g, "^").replace(/[\[]/g, "[").replace(/[\]]/g, "]").replace(/[\(]/g, "(").replace(/[\)]/g, ")");
+        result = "[" + result + "]";
+        return new RegExp(result, flags);
+    }
+    function doSplit(target, separator) {
+        var re = doRegExpify(separator);
+        var splits = target.split(re);
+        var result = [];
+        for (var i = 0, iLimit = splits.length; i < iLimit; i++) {
+            if (splits[i]) {
+                result.push(splits[i]);
+            }
+        }
+        return result;
+    }
+    function arraySplit(target, separator) {
+        if (target !== null) {
+            if (separator !== null) {
+                return doSplit(target, separator);
+            }
+            throw new thymol.ThError("#strings.arraySplit Separator cannot be null");
+        }
+        throw new thymol.ThError("#strings.arraySplit Cannot apply split on null");
+    }
+    function setSplit(target, separator) {
+        if (target !== null) {
+            if (separator !== null) {
+                var result = new thymol.ThSet();
+                var splits = doSplit(target, separator);
+                for (var i = 0, iLimit = splits.length; i < iLimit; i++) {
+                    result.add(splits[i]);
+                }
+                return result;
+            }
+            throw new thymol.ThError("#strings.setSplit Separator cannot be null");
+        }
+        throw new thymol.ThError("#strings.setSplit Cannot apply split on null");
+    }
+    function length(target) {
+        if (target !== null) {
+            return target.toString().length;
+        }
+        throw new thymol.ThError("#strings.length Cannot apply length on null");
+    }
+    function arrayLength(target) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(length(target[i]));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayLength Target cannot be null");
+    }
+    function setLength(target) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(length(target[k]));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setLength Target cannot be null");
+    }
+    function getReplacer(target) {
+        var bfr = target.replace(/[$]/g, "[$]").replace(/[*]/g, "[*]").replace(/[\']/g, "[']").replace(/[+]/g, "[+]").replace(/[\(]/g, "[(]").replace(/[\)]/g, "[)]");
+        return new RegExp(bfr, "g");
+    }
+    function replace(target, before, after) {
+        if (target !== null) {
+            if (before !== null) {
+                var bfr = unescapeXml(before);
+                if (after !== null) {
+                    var re = getReplacer(bfr);
+                    var aft = unescapeXml(after);
+                    return target.replace(re, aft);
+                }
+                throw new thymol.ThError("#strings.replace After cannot be null");
+            }
+            throw new thymol.ThError("#strings.replace Before cannot be null");
+        }
+        throw new thymol.ThError("#strings.replace Cannot apply replace on null");
+    }
+    function arrayReplace(target, before, after) {
+        if (target !== null) {
+            if (before !== null) {
+                var bfr = unescapeXml(before);
+                if (after !== null) {
+                    var re = getReplacer(bfr);
+                    var aft = unescapeXml(after);
+                    var result = [];
+                    for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                        result.push(target[i].toString().replace(re, aft));
+                    }
+                    return result;
+                }
+                throw new thymol.ThError("#strings.arrayReplace After cannot be null");
+            }
+            throw new thymol.ThError("#strings.arrayReplace Before cannot be null");
+        }
+        throw new thymol.ThError("#strings.arrayReplace Cannot apply replace on null");
+    }
+    function setReplace(target, before, after) {
+        if (target !== null) {
+            if (before !== null) {
+                var bfr = unescapeXml(before);
+                if (after !== null) {
+                    var re = getReplacer(bfr);
+                    var aft = unescapeXml(after);
+                    var result = new thymol.ThSet();
+                    for (var k in target) {
+                        if (target.isContent(k)) {
+                            result.add(target[k].toString().replace(re, aft));
+                        }
+                    }
+                    return result;
+                }
+                throw new thymol.ThError("#strings.setReplace Array of 'after' values cannot be null");
+            }
+            throw new thymol.ThError("#strings.setReplace Array of 'before' values cannot be null");
+        }
+        throw new thymol.ThError("#strings.setReplace Cannot apply replace on null");
+    }
+    function multipleReplace(target, before, after) {
+        if (target !== null) {
+            if (before !== null) {
+                if (Object.prototype.toString.call(before) == "[object Array]") {
+                    if (after !== null) {
+                        if (Object.prototype.toString.call(after) == "[object Array]") {
+                            if (before.length === after.length) {
+                                var result = target;
+                                var bfr, aft;
+                                for (var i = 0, iLimit = before.length; i < iLimit; i++) {
+                                    bfr = unescapeXml(before[i]);
+                                    var re = getReplacer(bfr);
+                                    aft = unescapeXml(after[i]);
+                                    result = result.replace(re, aft);
+                                }
+                                return result;
+                            }
+                            throw new thymol.ThError("#strings.multipleReplace Arrays of 'before' and 'after' values must have the same length");
+                        }
+                        throw new thymol.ThError("#strings.multipleReplace After must be an array type");
+                    }
+                    throw new thymol.ThError("#strings.multipleReplace After cannot be null");
+                }
+                throw new thymol.ThError("#strings.multipleReplace Before must be an array type");
+            }
+            throw new thymol.ThError("#strings.multipleReplace Before cannot be null");
+        }
+        throw new thymol.ThError("#strings.multipleReplace Target cannot be null");
+    }
+    function arrayMultipleReplace(target, before, after) {
+        if (target !== null) {
+            var result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                result.push(multipleReplace(target[i].toString(), before, after));
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.arrayMultipleReplace Target cannot be null");
+    }
+    function setMultipleReplace(target, before, after) {
+        if (target !== null) {
+            var result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(multipleReplace(target[k].toString(), before, after));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setMultipleReplace Target cannot be null");
+    }
+    function toUpperCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString().toUpperCase();
+        }
+        return result;
+    }
+    function arrayToUpperCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(target[i].toString().toUpperCase());
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setToUpperCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(target[k].toString().toUpperCase());
+                }
+            }
+        }
+        return result;
+    }
+    function toLowerCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString().toLowerCase();
+        }
+        return result;
+    }
+    function arrayToLowerCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(target[i].toString().toLowerCase());
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setToLowerCase(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(target[k].toString().toLowerCase());
+                }
+            }
+        }
+        return result;
+    }
+    function trim(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString().trim();
+        }
+        return result;
+    }
+    function arrayTrim(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(target[i].toString().trim());
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setTrim(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(target[k].toString().trim());
+                }
+            }
+        }
+        return result;
+    }
+    function capitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString();
+            if (result.length > 0) {
+                result = result.charAt(0).toUpperCase() + result.substr(1);
+            }
+        }
+        return result;
+    }
+    function arrayCapitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(capitalize(target[i]));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setCapitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(capitalize(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    function unCapitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = target.toString();
+            if (result.length > 0) {
+                result = result.charAt(0).toLowerCase() + result.substr(1);
+            }
+        }
+        return result;
+    }
+    function arrayUnCapitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(unCapitalize(target[i]));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setUnCapitalize(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(unCapitalize(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    function capitalizeWords(target, delimiters) {
+        var splitter;
+        if (typeof delimiters === "undefined") {
+            splitter = new RegExp("[^  \r\n\f\v]\\w*", "g");
+        } else {
+            var spec = "[^ " + delimiters + "]\\w*";
+            splitter = new RegExp(spec, "g");
+        }
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            var str = target.toString();
+            if (str.length > 0) {
+                result = "";
+                var matched;
+                var indx = 0;
+                while ((matched = splitter.exec(str)) !== null) {
+                    result += str.substring(indx, matched.index);
+                    result += matched[0].charAt(0).toUpperCase() + matched[0].substr(1);
+                    indx = splitter.lastIndex;
+                }
+                result += str.substring(indx);
+            }
+        }
+        return result;
+    }
+    function arrayCapitalizeWords(target, delimiters) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(capitalizeWords(target[i], delimiters));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setCapitalizeWords(target, delimiters) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(capitalizeWords(target[k], delimiters));
+                }
+            }
+        }
+        return result;
+    }
+    function escapeXml(target, escapeQuotesParam) {
+        var result = target;
+        if (target !== null && typeof target !== "undefined") {
+            var escapeQuotes = escapeQuotesParam !== null && typeof escapeQuotesParam !== "undefined" && escapeQuotesParam;
+            if (escapeQuotes) {
+                result = escapeXmlTrue(target);
+            } else {
+                result = "";
+                for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                    var c = target.charAt(i);
+                    if (c === "&") {
+                        if (!isEntityStart(target, i)) {
+                            c = "&amp;";
+                        }
+                    } else if (c === "<") {
+                        c = "&amp;lt;";
+                    } else if (c === ">") {
+                        c = "&amp;gt;";
+                    } else if (c === '"') {
+                        c = "&amp;quot;";
+                    } else if (c === "'") {
+                        c = "&amp;#39;";
+                    }
+                    result += c;
+                }
+            }
+        }
+        return result;
+    }
+    function escapeXmlTrue(target) {
+        var result = "";
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            var c = target.charAt(i);
+            if (c === "&") {
+                if (!isEntityStart(target, i)) {
+                    c = "&amp;";
+                }
+            } else if (c === "<") {
+                c = "&lt;";
+            } else if (c === ">") {
+                c = "&gt;";
+            } else if (c === '"') {
+                c = "&quot;";
+            } else if (c === "'") {
+                c = "&#39;";
+            }
+            result += c;
+        }
+        return result;
+    }
+    function unescapeXml(target) {
+        var result = "";
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            var c = target.charAt(i);
+            if (c === "&") {
+                c = isEntity(target, i);
+                if (c !== "&") {
+                    i += c.length;
+                    if (c === "&lt;") {
+                        c = "<";
+                    } else if (c === "&gt;") {
+                        c = ">";
+                    } else if (c === "&amp;") {
+                        c = "&";
+                    } else if (c === "&quot;") {
+                        c = '"';
+                    } else if (c === "&#39;") {
+                        c = "'";
+                    }
+                } else {
+                    c = "&amp;";
+                }
+            }
+            result += c;
+        }
+        return result;
+    }
+    function isEntity(buffer, position) {
+        var entity = "&";
+        var i = position + 1;
+        while (i < buffer.length) {
+            var c = buffer[i];
+            if (!(c >= "A" && c <= "Z" || c >= "a" && c <= "z" || c >= "0" && c <= "9" || c == ";" || c == "#")) {
+                return "&";
+            }
+            entity += c;
+            if (c == ";") {
+                return entity;
+            }
+            i++;
+        }
+        return "&";
+    }
+    function isEntityStart(buffer, position) {
+        var i = position + 1;
+        while (i < buffer.length) {
+            var c = buffer[i];
+            if (!(c >= "A" && c <= "Z" || c >= "a" && c <= "z" || c >= "0" && c <= "9" || c == ";" || c == "#")) {
+                return false;
+            }
+            if (c == ";") {
+                return true;
+            }
+            i++;
+        }
+        return false;
+    }
+    function arrayEscapeXml(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(escapeXml(target[i], false));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setEscapeXml(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(escapeXml(target[k], false));
+                }
+            }
+        }
+        return result;
+    }
+    function escapeJavaScript(target) {
+        var result = target;
+        if (target !== null && typeof target !== "undefined") {
+            result = escapeJavaAny(target, true);
+        }
+        return result;
+    }
+    function escapeJavaAny(target, javaScript) {
+        var result = "";
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            var c = target.charAt(i);
+            var cc = target.charCodeAt(i);
+            if (cc >= 32 && cc <= 127) {
+                switch (c) {
+                  case "\\":
+                    c = "\\";
+                    break;
+
+                  case '"':
+                    c = '\\"';
+                    break;
+
+                  case "'":
+                    if (javaScript) {
+                        c = "\\'";
+                    }
+                    break;
+
+                  case "/":
+                    if (javaScript) {
+                        if (i > 0 && target.charAt(i - 1) == "<") {
+                            c = "\\/";
+                        }
+                    }
+                    break;
+
+                  case ">":
+                    if (javaScript && i > 1) {
+                        if (target.charAt(i - 1) == "]" && target.charAt(i - 2) == "]") {
+                            c = "\\>";
+                        }
+                    }
+                    break;
+
+                  default:
+                    break;
+                }
+            } else {
+                switch (c) {
+                  case "       ":
+                    c = "\\t";
+                    break;
+
+                  case "\n":
+                    c = "\\n";
+                    break;
+
+                  case "\b":
+                    c = "\\b";
+                    break;
+
+                  case "\f":
+                    c = "\\f";
+                    break;
+
+                  case "\r":
+                    c = "\\r";
+                    break;
+
+                  default:
+                    if (javaScript) {
+                        c = hexEscape(cc);
+                    } else {
+                        c = unicodeEscape(cc);
+                    }
+                    break;
+                }
+            }
+            result += c;
+        }
+        return result;
+    }
+    function unicodeEscape(c) {
+        var x = c + 65536;
+        x = x.toString(16);
+        x = x.slice(1);
+        var output = "\\u" + x.toUpperCase();
+        return output;
+    }
+    function hexEscape(c) {
+        var x = c + 256;
+        x = x.toString(16);
+        x = x.slice(1);
+        var output = "\\x" + x.toUpperCase();
+        return output;
+    }
+    function arrayEscapeJavaScript(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(escapeJavaScript(target[i]));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setEscapeJavaScript(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(escapeJavaScript(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    function unescapeJavaScript(target) {
+        var result = target;
+        if (target !== null && typeof target !== "undefined") {
+            result = unescapeJavaAny(target);
+        }
+        return result;
+    }
+    function unescapeJavaAny(target) {
+        var result = "";
+        var unicodeSpec = "";
+        var unicodeLen = -1;
+        var hexSpec = "";
+        var hexLen = -1;
+        var lastWasEscape = false;
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            var c = target.charAt(i);
+            if (unicodeLen >= 0) {
+                unicodeSpec += c;
+                if (c >= "0" && c <= "9" || c >= "A" && c <= "F" || c >= "a" && c <= "f") {
+                    unicodeLen++;
+                    if (unicodeLen > 3) {
+                        var cc = parseInt(unicodeSpec, 16);
+                        c = String.fromCharCode(cc);
+                        unicodeSpec = "";
+                        unicodeLen = -1;
+                        result += c;
+                        lastWasEscape = false;
+                    }
+                } else {
+                    return target;
+                }
+            } else if (hexLen >= 0) {
+                hexSpec += c;
+                if (c >= "0" && c <= "9" || c >= "A" && c <= "F" || c >= "a" && c <= "f") {
+                    hexLen++;
+                    if (hexLen > 1) {
+                        var cc = parseInt(hexSpec, 16);
+                        c = String.fromCharCode(cc);
+                        hexSpec = "";
+                        hexLen = -1;
+                        result += c;
+                        lastWasEscape = false;
+                    }
+                } else {
+                    return target;
+                }
+            } else if (lastWasEscape) {
+                if (c === "u") {
+                    unicodeLen = 0;
+                } else if (c === "x") {
+                    hexLen = 0;
+                } else {
+                    switch (c) {
+                      case "t":
+                        c = "  ";
+                        break;
+
+                      case "n":
+                        c = "\n";
+                        break;
+
+                      case "b":
+                        c = "\b";
+                        break;
+
+                      case "f":
+                        c = "\f";
+                        break;
+
+                      case "r":
+                        c = "\r";
+                        break;
+
+                      default:
+                        break;
+                    }
+                    result += c;
+                    lastWasEscape = false;
+                }
+            } else if (c == "\\") {
+                lastWasEscape = true;
+            } else {
+                result += c;
+                lastWasEscape = false;
+            }
+        }
+        if (unicodeLen >= 0) {
+            result += "\\u" + unicodeSpec;
+        } else if (hexLen >= 0) {
+            result += "\\x" + hexSpec;
+        } else if (lastWasEscape) {
+            result += "\\";
+        }
+        return result;
+    }
+    function arrayUnescapeJavaScript(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(unescapeJavaScript(target[i]));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setUnescapeJavaScript(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(unescapeJavaScript(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    function escapeJava(target) {
+        var result = target;
+        if (target !== null && typeof target !== "undefined") {
+            result = escapeJavaAny(target, false);
+        }
+        return result;
+    }
+    function arrayEscapeJava(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = [];
+            for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+                if (target[i] !== null) {
+                    result.push(escapeJava(target[i]));
+                } else {
+                    result.push(null);
+                }
+            }
+        }
+        return result;
+    }
+    function setEscapeJava(target) {
+        var result = null;
+        if (target !== null && typeof target !== "undefined") {
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(escapeJava(target[k]));
+                }
+            }
+        }
+        return result;
+    }
+    var ALPHA_NUMERIC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    function randomAlphanumeric(count) {
+        var result = "";
+        for (var i = 0; i < count; i++) {
+            result += ALPHA_NUMERIC.charAt(Math.floor(Math.random() * ALPHA_NUMERIC.length));
+        }
+        return result;
+    }
+    function defaultString(target, defaultValue) {
+        if (defaultValue !== null && typeof defaultValue !== "undefined") {
+            if (target == null) {
+                return defaultValue.toString();
+            }
+            var targetString = target.toString();
+            if (isEmpty(targetString)) {
+                return defaultValue.toString();
+            }
+            return targetString;
+        }
+        throw new thymol.ThError("#strings.defaultString defaultValue cannot be null");
+    }
+    function doArrayDefaultString(target, defaultValue) {
+        if (target == null || typeof target === "undefined") {
+            return target;
+        }
+        var result = [];
+        for (var i = 0, iLimit = target.length; i < iLimit; i++) {
+            result.push(defaultString(target[i], defaultValue));
+        }
+        return result;
+    }
+    function arrayDefaultString(target, defaultValue) {
+        if (defaultValue !== null && typeof defaultValue !== "undefined") {
+            return doArrayDefaultString(target, defaultValue);
+        }
+        throw new thymol.ThError("#strings.arrayDefaultString defaultValue cannot be null");
+    }
+    function listDefaultString(target, defaultValue) {
+        if (defaultValue !== null && typeof defaultValue !== "undefined") {
+            return doArrayDefaultString(target, defaultValue);
+        }
+        throw new thymol.ThError("#strings.listDefaultString defaultValue cannot be null");
+    }
+    function setDefaultString(target, defaultValue) {
+        if (defaultValue !== null && typeof defaultValue !== "undefined") {
+            if (target == null || typeof target === "undefined") {
+                return target;
+            }
+            result = new thymol.ThSet();
+            for (var k in target) {
+                if (target.isContent(k)) {
+                    result.add(defaultString(target[k], defaultValue));
+                }
+            }
+            return result;
+        }
+        throw new thymol.ThError("#strings.setDefaultString defaultValue cannot be null");
+    }
+    return {
+        thExpressionObjectName: thExpressionObjectName,
+        toString: toString,
+        arrayToString: arrayToString,
+        listToString: arrayToString,
+        setToString: setToString,
+        abbreviate: abbreviate,
+        arrayAbbreviate: arrayAbbreviate,
+        listAbbreviate: arrayAbbreviate,
+        setAbbreviate: setAbbreviate,
+        equals: equals,
+        equalsIgnoreCase: equalsIgnoreCase,
+        contains: contains,
+        arrayContains: arrayContains,
+        listContains: arrayContains,
+        setContains: setContains,
+        containsIgnoreCase: containsIgnoreCase,
+        arrayContainsIgnoreCase: arrayContainsIgnoreCase,
+        listContainsIgnoreCase: arrayContainsIgnoreCase,
+        setContainsIgnoreCase: setContainsIgnoreCase,
+        startsWith: startsWith,
+        arrayStartsWith: arrayStartsWith,
+        listStartsWith: arrayStartsWith,
+        setStartsWith: setStartsWith,
+        endsWith: endsWith,
+        arrayEndsWith: arrayEndsWith,
+        listEndsWith: arrayEndsWith,
+        setEndsWith: setEndsWith,
+        substring: substring,
+        arraySubstring: arraySubstring,
+        listSubstring: arraySubstring,
+        setSubstring: setSubstring,
+        substringAfter: substringAfter,
+        arraySubstringAfter: arraySubstringAfter,
+        listSubstringAfter: arraySubstringAfter,
+        setSubstringAfter: setSubstringAfter,
+        substringBefore: substringBefore,
+        arraySubstringBefore: arraySubstringBefore,
+        listSubstringBefore: arraySubstringBefore,
+        setSubstringBefore: setSubstringBefore,
+        prepend: prepend,
+        arrayPrepend: arrayPrepend,
+        listPrepend: arrayPrepend,
+        setPrepend: setPrepend,
+        repeat: repeat,
+        append: append,
+        concat: concat,
+        concatReplaceNulls: concatReplaceNulls,
+        arrayAppend: arrayAppend,
+        listAppend: arrayAppend,
+        setAppend: setAppend,
+        indexOf: indexOf,
+        arrayIndexOf: arrayIndexOf,
+        listIndexOf: arrayIndexOf,
+        setIndexOf: setIndexOf,
+        isEmpty: isEmpty,
+        arrayIsEmpty: arrayIsEmpty,
+        listIsEmpty: arrayIsEmpty,
+        setIsEmpty: setIsEmpty,
+        arrayJoin: arrayJoin,
+        listJoin: arrayJoin,
+        setJoin: setJoin,
+        arraySplit: arraySplit,
+        listSplit: arraySplit,
+        setSplit: setSplit,
+        length: length,
+        arrayLength: arrayLength,
+        listLength: arrayLength,
+        setLength: setLength,
+        replace: replace,
+        arrayReplace: arrayReplace,
+        listReplace: arrayReplace,
+        setReplace: setReplace,
+        multipleReplace: multipleReplace,
+        arrayMultipleReplace: arrayMultipleReplace,
+        listMultipleReplace: arrayMultipleReplace,
+        setMultipleReplace: setMultipleReplace,
+        toUpperCase: toUpperCase,
+        arrayToUpperCase: arrayToUpperCase,
+        listToUpperCase: arrayToUpperCase,
+        setToUpperCase: setToUpperCase,
+        toLowerCase: toLowerCase,
+        arrayToLowerCase: arrayToLowerCase,
+        listToLowerCase: arrayToLowerCase,
+        setToLowerCase: setToLowerCase,
+        trim: trim,
+        arrayTrim: arrayTrim,
+        listTrim: arrayTrim,
+        setTrim: setTrim,
+        capitalize: capitalize,
+        arrayCapitalize: arrayCapitalize,
+        listCapitalize: arrayCapitalize,
+        setCapitalize: setCapitalize,
+        unCapitalize: unCapitalize,
+        arrayUnCapitalize: arrayUnCapitalize,
+        listUnCapitalize: arrayUnCapitalize,
+        setUnCapitalize: setUnCapitalize,
+        capitalizeWords: capitalizeWords,
+        arrayCapitalizeWords: arrayCapitalizeWords,
+        listCapitalizeWords: arrayCapitalizeWords,
+        setCapitalizeWords: setCapitalizeWords,
+        escapeXml: escapeXml,
+        arrayEscapeXml: arrayEscapeXml,
+        listEscapeXml: arrayEscapeXml,
+        setEscapeXml: setEscapeXml,
+        escapeJavaScript: escapeJavaScript,
+        arrayEscapeJavaScript: arrayEscapeJavaScript,
+        listEscapeJavaScript: arrayEscapeJavaScript,
+        setEscapeJavaScript: setEscapeJavaScript,
+        unescapeJavaScript: unescapeJavaScript,
+        arrayUnescapeJavaScript: arrayUnescapeJavaScript,
+        listUnescapeJavaScript: arrayUnescapeJavaScript,
+        setUnescapeJavaScript: setUnescapeJavaScript,
+        escapeJava: escapeJava,
+        arrayEscapeJava: arrayEscapeJava,
+        listEscapeJava: arrayEscapeJava,
+        setEscapeJava: setEscapeJava,
+        unescapeJava: unescapeJavaScript,
+        arrayUnescapeJava: arrayUnescapeJavaScript,
+        listUnescapeJava: arrayUnescapeJavaScript,
+        setUnescapeJava: setUnescapeJavaScript,
+        randomAlphanumeric: randomAlphanumeric,
+        defaultString: defaultString,
+        arrayDefaultString: arrayDefaultString,
+        listDefaultString: listDefaultString,
+        setDefaultString: setDefaultString
+    };
+}();
+
+thymol.thObjectsConfigureModules = function() {
+    thymol.addDialect({
+        objects: [ thymol.objects.thAggregatesObject, thymol.objects.thArraysObject, thymol.objects.thBoolsObject, thymol.objects.thDatesObject, thymol.objects.thCalendarsObject, thymol.objects.thIdsObject, thymol.objects.thListsObject, thymol.objects.thMapsObject, thymol.objects.thMessagesObject, thymol.objects.thNumbersObject, thymol.objects.thObjectsObject, thymol.objects.thSetsObject, thymol.objects.thStringsObject ]
+    });
+};
+
+thymol.isServerSide = function() {
+    return true;
+};
+
+exports.thymol = thymol;
\ No newline at end of file
diff --git a/dist/js/thymol-node.min.js b/dist/js/thymol-node.min.js
new file mode 100644 (file)
index 0000000..8991ead
--- /dev/null
@@ -0,0 +1,6 @@
+/* Thymol version 2.0.0 | Copyright (C) 2012-2015 James J. Benson | View license at http://www.apache.org/licenses/LICENSE-2.0 */thymol=function(){function a(){}function b(){return"undefined"!=typeof thymol.isServerSide&&thymol.isServerSide()?(thymol.isClientSide=function(){return!1},!1):(thymol.isClientSide=function(){return!0},!0)}function c(b){"undefined"==typeof thymol.protocol&&(thymol.protocol=""),"undefined"==typeof thymol.root&&(thymol.root=""),"undefined"==typeof thymol.path&&(thymol.path=""),thymol.thDocument=b;var c=thymol.thWindow;"undefined"==typeof thymol.thWindow&&("undefined"!=typeof b.defaultView?c=b.defaultView:"undefined"!=typeof b.parentWindow&&(c=b.parentWindow)),thymol.thWindow=c;var d=thymol.thTop;"undefined"==typeof thymol.thTop&&"undefined"!=typeof top&&(d=top),thymol.thTop=d,thymol.init();var e=new K(thymol.thDocument,!1,null,null,null,thymol.thDocument.nodeName,"::",!1,thymol.thDocument);return a.prototype.process(e),q(),thymol.thDocument}function d(a){a.fn.extend({getComments:function(){return this.filter(function(){return 8===this.nodeType})},getThDecorated:function(a){var b,c,d,e,f,g=[],h=null,i=!1;for(null!==a.escpName&&(g=this.filter(a.escpName)),null!==a.escpSynonym&&(g=g.add(this.filter(a.escpSynonym))),b=0,d=g.length;d>b;b++)if(g[b])for(e=0,f=g[b].attributes.length;f>e;e++)g[b].attributes[e]&&(c=g[b].attributes[e].name,!c||a.name!=c&&a.synonym!=c||(i=thymol.ThUtils.processElement(a.process,g[b],g[b].attributes[e],a),i&&(null===h&&(h=[]),h.push(g[b]))));return h}})}function e(a){("undefined"==typeof thymolDeferredFunctions||null===thymolDeferredFunctions)&&(thymolDeferredFunctions=[]),thymolDeferredFunctions.push(a)}function f(){thymol.prefix=a.prototype.getThParam("thPrefix",!1,!1,thymol.thDefaultPrefix),thymol.dataPrefix=a.prototype.getThParam("thDataPrefix",!1,!1,thymol.thDefaultDataPrefix),thymol.messagePath=a.prototype.getThParam("thMessagePath",!1,!0,thymol.thDefaultMessagePath),thymol.resourcePath=a.prototype.getThParam("thResourcePath",!1,!0,thymol.thDefaultResourcePath),thymol.messagesBaseName=a.prototype.getThParam("thMessagesBaseName",!1,!1,thymol.thDefaultMessagesBaseName),thymol.relativeRootPath=a.prototype.getThParam("thRelativeRootPath",!1,!0,thymol.thDefaultRelativeRootPath),thymol.extendedMapping=a.prototype.getThParam("thExtendedMapping",!0,!1,thymol.thDefaultExtendedMapping),thymol.localMessages=a.prototype.getThParam("thLocalMessages",!0,!1,thymol.thDefaultLocalMessages),thymol.disableMessages=a.prototype.getThParam("thDisableMessages",!0,!1,thymol.thDefaultDisableMessages),thymol.templateSuffix=a.prototype.getThParam("thTemplateSuffix",!1,!1,thymol.thDefaultTemplateSuffix),thymol.scriptPath="","undefined"!=typeof thymol.thScriptPath&&(thymol.scriptPath=a.prototype.getThParam("thScriptPath",!1,!0,thymol.thScriptPath)),thymol.absolutePath="","undefined"!=typeof thymol.thAbsolutePath&&(thymol.absolutePath=a.prototype.getThParam("thAbsolutePath",!1,!0,thymol.thAbsolutePath)),thymol.useAbsolutePath=!1,"undefined"!=typeof thymol.thUseAbsolutePath&&(thymol.useAbsolutePath=a.prototype.getThParam("thUseAbsolutePath",!0,!1,thymol.thUseAbsolutePath)),thymol.useFullURLPath=!0,"undefined"!=typeof thymol.thUseFullURLPath&&(thymol.useFullURLPath=a.prototype.getThParam("thUseFullURLPath",!0,!1,thymol.thUseFullURLPath)),thymol.indexFile=a.prototype.getThParam("thIndexFile",!1,!1,null),thymol.debug=a.prototype.getThParam("thDebug",!0,!1,!1),thymol.allowNullText=a.prototype.getThParam("thAllowNullText",!0,!1,!0),thymol.location=thymol.thLocation,""!==thymol.relativeRootPath?(thymol.root=thymol.location+thymol.relativeRootPath,thymol.messagePath=thymol.root+thymol.messagePath):("undefined"!=typeof thymol.thMessagePath&&(thymol.messagePath=a.prototype.getThParam("thMessagePath",!1,!0,thymol.thMessagePath)),"undefined"!=typeof thymol.thRoot&&(thymol.root=a.prototype.getThParam("thRoot",!1,!0,thymol.thRoot))),thymol.root=a.prototype.getThParam("thRoot",!1,!0,thymol.root),"undefined"!=typeof thymol.thPath&&(thymol.path=a.prototype.getThParam("thPath",!1,!0,thymol.thPath)),thymol.path=a.prototype.getThParam("thPath",!1,!0,thymol.path),thymol.protocol=thymol.thDocument.location.protocol,""==thymol.protocol?thymol.protocol=thymol.thDefaultProtocol:(thymol.protocol+="//",""==thymol.thDocument.location.host&&(thymol.protocol+="/")),thymol.protocol=a.prototype.getThParam("thProtocol",!1,!1,thymol.protocol),thymol.resourcePath=a.prototype.getThParam("thResourcePath",!1,!0,thymol.resourcePath)}function g(a){thymol.prefix=a,thymol.thThymeleafPrefixList=[],thymol.thThymeleafElementsList=[]}function h(){this.messages=null,this.mappings=null,this.debug=null,i(this),this.locale=new thymol.ThObject,D();var b,c,d,e,g=void 0;"undefined"!=typeof thVars&&(g=new thymol.ThVarsAccessor(thVars,"thVars")),this.applicationContext=thymol.makeContext("application",g),this.sessionContext=thymol.makeContext("session",void 0),this.sessionContext.persist=function(){var a=this.serialise();thymol.thTop.name=a},this.requestContext=thymol.makeContext("request",void 0),this.booleanAndNullTokens=new Array,this.booleanAndNullTokens["null"]=this.applicationContext.createVariable("null",null),this.booleanAndNullTokens["true"]=this.applicationContext.createVariable("true",!0),this.booleanAndNullTokens["false"]=this.applicationContext.createVariable("false",!1),this.allowNullText=null,f(),this.thCache={},this.thExpressionObjects,this.thDeferredFunctions,this.thPreExecutionFunctions,this.thPostExecutionFunctions,("undefined"==typeof this.thExpressionObjects||null===this.thExpressionObjects)&&(this.thExpressionObjects={}),this.thExpressionObjects["#object"]={},this.thExpressionObjects["#locale"]={},this.thExpressionObjects["#ctx"]=[],this.thExpressionObjects["#ctx"].variables={},thymol.configureModule(thymol.objects.thHttpServletRequestObject),thymol.configureModule(thymol.objects.thHttpSessionObject),"undefined"!=typeof thymol.thObjectsConfigureModules&&thymol.thObjectsConfigureModules();for(var h=thymol.thDocument.getElementsByTagName("script"),b=0,c=h.length;c>b;b++){var j=h[b].getAttribute("data-thymol-load");if(j)for(var k=j.split(","),d=0,e=k.length;e>d;d++)thymol.ThUtils.loadScript(k[d])}if(f(),("undefined"==typeof thymol.thPreExecutionFunctions||null===thymol.thPreExecutionFunctions)&&(thymol.thPreExecutionFunctions=[]),("undefined"==typeof thymol.thPostExecutionFunctions||null===thymol.thPostExecutionFunctions)&&(thymol.thPostExecutionFunctions=[]),$.ajaxSetup({async:!1,isLocal:!0,dataType:"text"}),"undefined"!=typeof thVars)for(b=0,c=thVars.length;c>b;b++)this.applicationContext.createVariable(thVars[b][0],thVars[b][1]);o(),function(){var a,b,c=$("html")[0].attributes,d=null;$([thymol.thURL,thymol.thAltURL]).each(function(){return a=this,$(c).each(function(){return this.value==a&&(b=this.localName.split(":"),b.length>0)?(d=b[b.length-1],!1):void 0}),d?(thymol.updatePrefix(d),!1):void 0})}();var l="";if(thymol.thRequest&&(thymol.thWindow.location.search=thymol.thRequest),function(a,b){var c,d,e,f=/\+/g,g=/([^&=]+)=?([^&]*)/g,h=function(a){return decodeURIComponent(a.replace(f," "))},i=thymol.thWindow.location.search.substring(1),j=l;for($("script").each(function(){return e=this.src,e.indexOf(thymol.thScriptName)>=0?(j=h(e),!1):void 0});c=g.exec(j);)switch(d=c[1].split("?"),d[1]){case"thPrefix":thymol.prefix=c[2];break;case"thDataPrefix":thymol.dataPrefix=c[2];break;case"thMessagePath":thymol.messagePath=c[2];break;case"thResourcePath":thymol.resourcePath=c[2];break;case"thMessagesBaseName":thymol.messagesBaseName=c[2];break;case"thRelativeRootPath":thymol.relativeRootPath=c[2];break;case"thExtendedMapping":thymol.extendedMapping=c[2];break;case"thTemplateSuffix":thymol.templateSuffix=c[2];break;case"thLocalMessages":thymol.localMessages=c[2];break;case"thDisableMessages":thymol.disableMessages=c[2];break;case"thIndexFile":thymol.indexFile=c[2];break;case"thProtocol":thymol.protocol=c[2];break;case"thDebug":thymol.debug=c[2];break;case"thRoot":thymol.root=c[2];break;case"thPath":thymol.path=c[2];break;case"thAllowNullText":thymol.allowNullText=c[2];break;case"thLocale":thymol.locale.value=c[2];break;case"thDefaultPrecision":thymol.thDefaultPrecision=c[2];break;case"thDefaultPrecedence":thymol.thDefaultPrecedence=c[2];break;default:a.createVariable(c[1],c[2])}for(;c=g.exec(i);)b.createVariable(h(c[1]),c[2],!0)}(this.applicationContext,this.requestContext),thymol.thInclude=new thymol.ThAttr("include",null,100,null,thymol.prefix),thymol.thReplace=new thymol.ThAttr("replace",null,100,null,thymol.prefix),thymol.thSubstituteby=new thymol.ThAttr("substituteby",null,100,null,thymol.prefix),thymol.thFragment=new thymol.ThAttr("fragment",null,2e4,null,thymol.prefix),thymol.thRemove=null,thymol.thBlock=new thymol.ThElement("block",function(a){var b,c=a.childNodes.length;for(b=0;c>b;b++)1===a.childNodes[b].nodeType&&(a.childNodes[b].isBlockChild=!0)},thymol.prefix),this.applicationContext.resolveJSONReferences(),thymol.setupAttrList(),p(this.applicationContext),this.thExpressionObjects["#vars"]=this.applicationContext,this.thExpressionObjects["#root"]=this.applicationContext,this.sessionContext.init(),this.sessionContext.resolveJSONReferences(),this.requestContext.resolveJSONReferences(),this.thExpressionObjects["#ctx"].variables=this.applicationContext,this.thExpressionObjects["#ctx"].requestParameters=this.requestContext,this.thExpressionObjects["#ctx"].servletContext=this.applicationContext,this.thExpressionObjects["#ctx"].httpServletRequest=this.thExpressionObjects["#httpServletRequest"],this.thExpressionObjects["#ctx"].httpSession=this.thExpressionObjects["#httpSession"],this.protocol=a.prototype.override("thProtocol",this.protocol),this.debug=a.prototype.override("thDebug",this.debug),this.root=a.prototype.override("thRoot",this.root),""!==this.relativeRootPath){var m=thymol.thDocument.location.href,n=m.indexOf("?");n>=0&&(m=m.substring(0,n));var q=m.lastIndexOf("/");q>=0&&(m=m.substring(0,q+1));var r=m+this.thLocation+this.relativeRootPath;this.thRoot=a.prototype.getThParam("thRoot",!1,!0,r)}if(this.path=a.prototype.override("thPath",this.path),this.allowNullText=a.prototype.override("thAllowNullText",this.allowNullText),this.locale.value=a.prototype.override("thLocale",this.locale.value),"undefined"!=typeof thMappings){for(this.mappings=[],d=0,e=thMappings.length;e>d;d++)this.mappings.push([thMappings[d][0],thMappings[d][1]]);this.mappings.sort(function(a,b){return a[0].length>b[0].length?-1:1})}if(this.messages={},E(),"undefined"!=typeof thMessages){for(this.messages[""]=[],d=0,e=thMessages.length;e>d;d++)this.messages[""][thMessages[d][0]]=thMessages[d][1];for(var s in thMessages)if(thMessages.hasOwnProperty(s)&&!s.match(da))for(this.messages[s]=[],d=0,e=thMessages[s].length;e>d;d++)this.messages[s][thMessages[s][d][0]]=thMessages[s][d][1]}if("undefined"!=typeof thDisable)for(d=0,e=thDisable.length;e>d;d++)a.prototype.doDisable(thDisable[d]);thymol.thRemove=a.prototype.getThAttrByName("remove")}function i(a){if(a.templateName="",a.templatePath="",thymol.thDocument.location.href){var b=templatePath=thymol.thDocument.location.href;a.templateName=b.substring(0,-1==b.indexOf(".")?b.length:b.lastIndexOf(".")),a.templatePath=templatePath.substring(0,-1==templatePath.indexOf("/")?0:templatePath.lastIndexOf("/")+1)}}function j(a){("undefined"==typeof thymol.thExpressionObjects||null===thymol.thExpressionObjects)&&(thymol.thExpressionObjects={}),thymol.thExpressionObjects[a.thExpressionObjectName]=a}function k(a,b,c,d,e){var f=a+":";null!==f?thymol.thThymeleafPrefixList.indexOf(f)<0&&thymol.thThymeleafPrefixList.push(f):thymol.thUsingNullPrefix=!0,f=new thymol.ThAttr(b,c,d,thymol.thThymeleafPrefixList,a,e)}function l(a,b,c){new thymol.ThElement(b,c,a)}function m(a){("undefined"==typeof thymol.thPreExecutionFunctions||null===thymol.thPreExecutionFunctions)&&(thymol.thPreExecutionFunctions=[]),thymol.thPreExecutionFunctions.push(a)}function n(a){("undefined"==typeof thymol.thPostExecutionFunctions||null===thymol.thPostExecutionFunctions)&&(thymol.thPostExecutionFunctions=[]),thymol.thPostExecutionFunctions.push(a)}function o(){if("undefined"!=typeof thymolDeferredFunctions&&null!==thymolDeferredFunctions)for(;thymolDeferredFunctions.length>0;){var a=thymolDeferredFunctions.pop();a()}}function p(a){for(;thymol.thPreExecutionFunctions.length>0;){var b=thymol.thPreExecutionFunctions.pop();b(),a.resolveJSONReferences()}}function q(){for(;thymol.thPostExecutionFunctions.length>0;){var a=thymol.thPostExecutionFunctions.pop();a()}}function r(a,b){var c,d,e=a;do if(c=e.indexOf("__"),c>=0){if(d=-1,e.length>4&&(d=e.lastIndexOf("__")),0>=d)throw new thymol.ThError("Mismatched pre-processing indicators",b);var f=e.substring(0,c),g=e.substring(c+2,d);g=this.getParsedExpr(g,b);var h=e.substring(d+2);e=f+g+h,c=e.indexOf("__")}while(c>=0);return e=e.replace(/\\_\\_/g,"__")}function s(a,b,c){var d,e,f=a,g=a,h=null;if(f){if(4===b)d=thymol.getMessage(g),d&&(h=d);else if(6===b)h=a;else{var i=thymol.booleanAndNullTokens[f];"undefined"!=typeof i?h=null===i?null:i.value:("#"===g.charAt(0)&&("#object"===g?c.thObjectVar&&(h=c.thObjectVar):(e=thymol.thExpressionObjects[g],"undefined"!=typeof e&&null!==e&&(h=e))),"undefined"!=typeof h&&null!=h||!c.thObjectVar||(h=c.thObjectVar[g]),"undefined"!=typeof h&&null!=h||!c.thLocalVars||(h=c.thLocalVars[g]),("undefined"==typeof h||null==h)&&(h=thymol.ThUtils.getParameter(g)),("undefined"==typeof h||null==h)&&("param"===g&&(h=thymol.requestContext),"session"===g&&(h=thymol.sessionContext),"application"===g&&(h=thymol.applicationContext)),2!==b||"undefined"!=typeof h&&null!=h||(h=a))}f=h,h instanceof thymol.ThParam&&(f=h.value)}return f}function t(a){var b,c,d=a.trim();return b=thymol.getMapped(d,thymol.extendedMapping),b&&(d=b),"/"===d&&thymol.indexFile&&(d+=thymol.indexFile),/.*:\/\/.*/.test(d)||/^~?\/.*$/.test(d)&&(/^~.*$/.test(d)&&(d=d.substring(1)),/^\/\/.*$/.test(d)||(thymol.useFullURLPath?(c=thymol.root+thymol.resourcePath,""!=c&&("/"!==c.charAt(c.length-1)&&(c+="/"),d="/"===d.charAt(0)?c+d.substring(1):c+d)):d=thymol.resourcePath+d)),d}function u(b,c){var d,e,f,g,h,i,j=b,k=!1;return"string"==typeof b&&(d=b.trim(),j=d,j&&(e=thymol.ThUtils.getParameter(j),e||(f=j.match(ba),f&&f[1]&&f[1].length>0&&(e=thymol.ThUtils.getParameter(f[1]))),e?(j=e instanceof thymol.ThParam?e.value:e,"string"==typeof j&&j.match(da)&&(j=parseInt(j))):(d=thymol.ThUtils.unParenthesise(j),g=!1,"!"==d.charAt(0)&&(g=!0,d=d.substring(1,d.length),d=thymol.ThUtils.unParenthesise(d)),W.test(d)&&(h=thymol.booleanAndNullTokens[d],"undefined"!=typeof h&&(j=h.value,k=!0)),i=null,k||(i=d.match(ga),i&&i.length>0&&thymol.ThUtils.charOcurrences(i[1],"'")<2&&(d=a.prototype.doLiteralSubstExpr(d,i[1])),j="",""!=d&&(d=thymol.ThUtils.unParenthesise(d),d=thymol.preProcess(d,c),j=thymol.getParsedExpr(d,c,!0))),j==d&&typeof j==typeof d?j=null:"string"==typeof j&&(i||(j=j.replace(/[\\][\\]/g,"\\")),j=j.replace(/&#39;/g,"'").replace(/&apos;/gi,"'")),g&&("boolean"==typeof j?j=!j:"number"==typeof j?j=0==j:"string"==typeof j&&(j=!thymol.ThUtils.testLiteralFalse(j)))))),j}function v(a,b){var c,d,e,f=null;if(a&&"string"==typeof a&&thymol.mappings)for(c=0,d=thymol.mappings.length;d>c;c++){if(e=thymol.mappings[c][0],a==e){f=thymol.mappings[c][1];break}if(b&&0==a.indexOf(e)){f=a.substring(e.length),f=thymol.mappings[c][1]+f;break}}return f}function w(a,b,c){var d,e,f,g,h,i,j=a;for("string"==typeof j&&(j=j.trim()),d=j,e="";null!=e;)e=j.match(/.*([$\*#@]{(!?[^}]*)}).*/),null!=e&&e.length>0&&3==e.length&&(f=e[1],f=f.replace(/[$]/g,"[$]").replace(/[*]/g,"[*]").replace(/[\']/g,"[']").replace(/[+]/g,"[+]").replace(/[\(]/g,"[(]").replace(/[\)]/g,"[)]"),g=new RegExp(f),h=this.getExpression(e[2],b),h!=e[2]?(d=d.replace(g,h,"g"),"null"==d&&(d=null)):(h="",thymol.debug&&!c&&thymol.thWindow.alert('thymol variable substitution failed: "'+a+'"')),i=j,j=j.replace(g,h,"g"),i==j&&(j=""));return d}function x(a,b){var c=b.trim(),d=0;if(c)do{var e=thymol.ThParser.parse(c,!0,!1),f=e.tokens.shift();if(3!==f.type_)break;var g=e.evaluate(a),h=f.index_;h&&(d++,a.thLocalVars||(a.thLocalVars={}),a.thLocalVars[h]=g),c=c.substring(e.position)}while(c.length>0);return d}function y(a,b,c){var d,e=a;return d=thymol.ThParser.parse(e,!1,c),d=d.simplify(),e=d.evaluate(b),"number"==typeof e&&(e=thymol.ThUtils.getToPrecision(e,d.precision)),e}function z(a){var b,c,d=!1;return null!=a&&("boolean"==typeof a?d=a:"number"==typeof a?d=0!=a:(b=a,"[object Array]"===Object.prototype.toString.call(b)&&(b=1===b.length?b[0]:!0),"boolean"==typeof b?d=b:"number"==typeof b?d=0!=b:"string"==typeof b?(c=b.match(ca),c?(b=c[1],d=this.testParam(b)):d=!thymol.ThUtils.testLiteralFalse(b)):d=b instanceof thymol.ThParam?b.getBooleanValue():"undefined"!=typeof b&&null!==b)),d}function A(a){for(var b=!1,c=a.parentElement;c;){if(c.getAttribute(thymol.thFragment.name)||c.getAttribute(thymol.thFragment.synonym)){b=!0;break}c=c.parentElement}return b}function B(a){thymol.locale.value=a,E()}function C(){return thymol.locale.value}function D(){if(!thymol.locale.value&&"undefined"!=typeof navigator&&navigator){var a=navigator.language||navigator.userLanguage||navigator.browserLanguage||navigator.systemLanguage;a&&(thymol.locale.value=a.replace(/\-/g,"_"))}}function E(){thymol.locale.value||(thymol.locale.value=thymol.thDefaultLocale);var a,b,c=thymol.locale.value.replace(/\-/g,"_"),d=thymol.locale.value,e=[],f=[];do e.push(d),a=c.lastIndexOf("_"),a>=0&&(b=c.substring(a+1),f.push(b),c=c.substring(0,a),d=d.substring(0,a));while(a>=0);if(thymol.locale.language=d,f){f.reverse();for(var g=0,h=f.length;h>g;g++)0===g?thymol.locale.country=f[g]:1===g&&(thymol.locale.variant=f[g])}thymol.locale.levels=e,thymol.thExpressionObjects["#ctx"].locale=thymol.locale,thymol.thExpressionObjects["#locale"]=thymol.locale}function F(a,b,c){if(thymol.disableMessages)return void 0;var d,e=null;if(thymol.locale.levels)for(var f,g,h="$",i=thymol.localMessages?0:1,j=i;2>j;j++){for(var k=0,l=thymol.locale.levels.length;l+1>k&&(f=h,d=l>k?thymol.locale.levels[k]:"",f+=d,g=thymol.messages[f],g||(g=1>j?H(d):I(d)),!(g&&(thymol.messages[f]=g,e=g[a])));k++);if(e)break;h+="$"}if(!e)for(var k=0,l=thymol.locale.levels.length;l>=k&&(d=l>k?thymol.locale.levels[k]:"",!thymol.messages[d]||!(e=thymol.messages[d][a]));k++);return e?"undefined"==typeof b?e:thymol.ThUtils.renderMessage(e,b):void 0!==c&&c?"??"+a+"_"+thymol.locale.value+"??":null}function G(a){var b=null,c=[];if($.get(a,function(c,d){var e=null;try{"success"==d?b=c:thymol.debug&&thymol.thWindow.alert("read failed: "+a)}catch(e){thymol.debug&&thymol.thWindow.alert("properties file read failed: "+a+" error: "+e)}},"text"),null!==b){var d=b.split("\n");if(d.length>0)for(var e=0,f=d.length;f>e;e++){var g=d[e].trim();if("#"!==g.charAt(0)){var h=g.split("=");h.length>1&&(c[h[0].trim()]=thymol.ThUtils.unicodeUnescape(h[1].trim()))}}}return c}function H(a){var b=[];if(thymol.thDocument.location.href){var c=thymol.templateName;a&&""!==a&&(c+="_"+a),c+=".properties",b=G(c)}return b}function I(a){var b=null,c="";thymol.useAbsolutePath&&(c+=thymol.protocol+thymol.root+thymol.path),c+=thymol.messagePath,""!==c&&(c+="/");var d=c+thymol.messagesBaseName;return a&&""!==a&&(d+="_"+a),d+=".properties",b=G(d)}function J(a){var b,c,d=thymol.thDefaultPrecedence;if(null!==a&&"undefined"!=typeof a){if(null!==a.attributeProcessors&&"undefined"!=typeof a.attributeProcessors)for(b=0,c=a.attributeProcessors.length;c>b;b++)d=null!==a.attributeProcessors[b].precedence&&"undefined"!=typeof a.attributeProcessors[b].precedence?a.attributeProcessors[b].precedence:thymol.thDefaultPrecedence,k(a.prefix,a.attributeProcessors[b].name,a.attributeProcessors[b].processor,d,null);if(null!==a.elementProcessors&&"undefined"!=typeof a.elementProcessors)for(b=0,c=a.elementProcessors.length;c>b;b++)l(a.prefix,a.elementProcessors[b].name,a.elementProcessors[b].processor);if(null!==a.objects&&"undefined"!=typeof a.objects)for(b=0,c=a.objects.length;c>b;b++)null!==a.objects[b].name&&"undefined"!=typeof a.objects[b].name?(a.objects[b].object.thExpressionObjectName=a.objects[b].name,j(a.objects[b].object)):j(a.objects[b])}}function K(a,b,c,d,e,f,g,h,i){this.thDoc=a,this.visited=b,this.parentDoc=c,this.firstChild=d,this.nextSibling=e,this.fileName=f,this.fragName=g,this.isNode=h,this.element=i}function L(a,b,c){this.name="ThError",this.message=a||"Default Message",null!==b&&"undefined"!=typeof b&&b.isBlockChild?this.suppress=!0:(this.element=b||{},this.suppress=!1),c&&c.stack&&(this.stack=c.stack)}function M(a){this.value=a,this.globalValue,this["class"]=new thymol.ThClass("Thymol.ThParam"),this.getBooleanValue=function(){return!thymol.ThUtils.testLiteralFalse(this.value)},this.toString=function(){return this.value},this.getNumericValue=function(){return Number(this.value)}}function N(a,b,c,d,e,f){var g="",h=null,i="";if("undefined"!=typeof e&&null!==e&&(g=e+":",thymol.thThymeleafPrefixList.indexOf(g)<0&&thymol.thThymeleafPrefixList.push(g),i=e+"\\:","undefined"==typeof f||null===f?(h=thymol.dataPrefix+"-"+e+"-",thymol.thThymeleafPrefixList.indexOf(h)<0&&thymol.thThymeleafPrefixList.push(h)):h=f),this.suffix=a,this.name=g+a,this.regex=null,(a.indexOf("*")>=0||a.indexOf("?")>=0||a.indexOf("+")>=0||a.indexOf("\\")>=0||a.indexOf("|")>=0||a.indexOf("[")>=0||a.indexOf("]")>=0||a.indexOf("{")>=0||a.indexOf("}")>=0)&&("*"===a&&(a=".*"),a=g+a,this.regex=new RegExp(a)),this.escpName="["+i+a+"]",null!==h?(this.synonym=h+a,this.escpSynonym="["+this.synonym+"]"):(this.synonym=null,this.escpSynonym=null),this.precedence="undefined"!=typeof c&&null!==c?c:thymol.thDefaultPrecedence,d){var j=d[e];j||(j=[],d[e]=j,null!==h&&(d[h]=j)),j.push(this)}this.process=function(){thymol.thWindow.alert('unsupported processing function for attribute "'+this.name+'"')},"undefined"!=typeof b&&(this.process=b),this.disable=function(){this.name=null,this.escpName=null,this.escpSynonym=null,this.process=function(){}}}function O(a,b,c){var d=new thymol.ThAttr(a,null,0,null,c);this.name=d.name,this.synonym=d.synonym,this.endName="/"+d.name,this.endSynonym="/"+d.synonym,this.process=function(){thymol.thWindow.alert('unsupported processing function for element "'+this.name+'"')},"undefined"!=typeof b&&(this.process=b),this.disable=function(){this.name=null,this.synonym=null,this.endName=null,this.endSynonym=null,this.process=null},thymol.thThymeleafElementsList.push(this)}function P(){function a(a){var b,c=[],d=null;for(d in a)a.hasOwnProperty(d)&&"that"!==d&&"setSize"!==d&&(b=a[d],"function"!=typeof b&&c.push(b));return c}this.that=this,this.setSize=0,this.isContent=function(a){return this.hasOwnProperty(a)&&"function"!=typeof this[a]&&"that"!==a&&"setSize"!==a},this.add=function(a){var b="undefined"!=typeof this[a];this[a]=a,b!==("undefined"!=typeof this[a])&&this.setSize++},this.addAll=function(a){var b,c=null;for(c in a)a.hasOwnProperty(c)&&(b=a[c],"function"!=typeof b&&add(b))},this.clear=function(){for(var a in this)this.hasOwnProperty(a)&&delete this[a];setSize=0},this.contains=function(a){return"undefined"!=typeof this[a]},this.containsAll=function(a){var b=a,c=null;("Array"==typeof a||"[object Array]"===Object.prototype.toString.call(a))&&(b=P.prototype.fromArray(a));for(c in b)if(b.hasOwnProperty(c)&&"undefined"==typeof this[c])return!1;return!0},this.isEmpty=function(){return 0===this.setSize},this.size=function(){return this.setSize},this.remove=function(a){var b="undefined"!=typeof this[a];delete this[a],b!==("undefined"!=typeof this[a])&&this.setSize--},this.toArray=function(){return a(this)},this.toString=function(){var b=a();return b.toString()}}function Q(){P.apply(this),this.containsKey=function(a){return this.contains(a)},this.containsValue=function(a){var b,c=null;for(c in this.that)if(this.that.hasOwnProperty(c)&&"that"!==c&&(b=this.that[c],b===a))return!0;return!1},this.entrySet=function(){return this.that},this.get=function(a){return this.that[a]},this.keySet=function(){return this.that},this.put=function(a,b){var c="undefined"!=typeof this[a];this.that[a]=b,c!==("undefined"!=typeof this[a])&&this.setSize++},this.putAll=function(a){for(var b in a)put(b,a[b])},this.values=function(){return this.that}}function R(a){for(prop in a)a.hasOwnProperty(prop)&&prop&&(this[prop]||(this[prop]=a[prop]));this["class"]=new thymol.ThClass("Thymol.ThObject"),this.toNonThObject=function(){var a={};for(prop in this)this.hasOwnProperty(prop)&&prop&&(a[prop]||"toNonThObject"!==prop&&("class"!==prop||"class"===prop&&null!==this[prop]&&"Thymol.ThObject"!==this[prop].name)&&(a[prop]=this[prop]));return a}}function S(a,b){this.store=a,this.arrayName=b,this.length=function(){return this.store.length},this.get=function(a){return this.store[a]},this.set=function(a,b){this.store[a]=b}}function T(a){this.name=a}thymol.thVersion="2.0.0",thymol.thReleaseDate="2015-03-31",thymol.thURL="http://www.thymoljs.org",thymol.thAltURL="http://www.thymeleaf.org",thymol.thUsingNullPrefix=!1,thymol.thThymeleafPrefixList=[],thymol.thThymeleafElementsList=[],thymol.objects={};var U="~~~~",V=/([$#]{.*?})/,W=/^[a-zA-Z0-9\[\]\.\-_]*$/,X=/^\s*\/\*\s*$/,Y=/^\s*\*\/\s*$/,Z=/^\/\*[^\/].*/,_=/.*[^\/]\*\/$/,aa=/\/\*\/(.*)\/\*\//,ba=/[\$\*#@]{1}\{(.*)\}$/,ca=/[\$\*#]{1}\{(?:!?[^}]*)\}/,da=/^[+\-]?[0-9]*?[.]?[0-9]*?$/,ea=/([^(]*)\s*[(]([^)]*?)[)]/,fa=/([\/]{1,2})?([A-Za-z0-9_\-]*(?:[\(][\)])?)?([^\[]\S[A-Za-z0-9_\-]*(?:[\(][\)])?[\/]*(?:[\.\/#]?[^\[]\S[A-Za-z0-9_\-]*(?:[\(][\)])?[\/]*)*)?([\[][^\]]*?[\]])?/,ga=/\.*?([\|][^\|]*?[\|])\.*?/;return a.prototype={process:function(a){var b=a;try{for(;b.thDoc;)if(this.getChildren(b),b.firstChild&&b.firstChild.thDoc&&!b.visited)b.visited=!0,b=b.firstChild;else if(b.element!=b.thDoc&&(this.doReplace(b.isNode,b.element,b.thDoc),b.isNode||(b.thDoc=b.element)),b.nextSibling&&b.nextSibling.thDoc)b=b.nextSibling;else{if(b==a)break;b=b.parentDoc}this.processChildren(a)}catch(c){thymol.debug&&(c instanceof thymol.ThError?c.suppress||thymol.thWindow.alert(c):thymol.thWindow.alert(c))}},getChildren:function(a){var b,c,d,e,f,g,h,i,j,k,l,m=0,n=null,o=!1;if(!a.visited){this.processComments(a);var p=this.getContentRoot(a);for(c=$(p),d=$(c).add(c.find("*")),e=d.filter(thymol.thInclude.escpName).add(d.filter(thymol.thInclude.escpSynonym)).add(d.filter(thymol.thReplace.escpName)).add(d.filter(thymol.thReplace.escpSynonym)).add(d.filter(thymol.thSubstituteby.escpName)).add(d.filter(thymol.thSubstituteby.escpSynonym)),f=0,g=e.length;g>f;f++){for(j=e[f],k=[],h=0,i=j.attributes.length;i>h;h++)l=j.attributes[h],(thymol.thInclude.name==l.name||thymol.thInclude.synonym==l.name||thymol.thReplace.name==l.name||thymol.thReplace.synonym==l.name||thymol.thSubstituteby.name==l.name||thymol.thSubstituteby.synonym==l.name)&&k.push(l);for(h=0,i=k.length;i>h;h++)b=this.processImport(j,a,k[h]),null!=b&&(o=!0,0==m?a.firstChild=b:n.nextSibling=b,n=b,m++)}}return o},processChildren:function(a){var b,c,d,e,f,g,h=a.thDoc.getElementsByTagName("*");for(f=0,g=h.length;g>f;f++){var i=h[f];for(d=0,e=thymol.thThymeleafElementsList.length;e>d;d++)if(i.localName==thymol.thThymeleafElementsList[d].name||i.localName==thymol.thThymeleafElementsList[d].synonym){var j=thymol.thThymeleafElementsList[d].process(i);j&&(h=a.thDoc.getElementsByTagName("*"),f--,g=h.length);break}var k=i.attributes;if(k&&k.length>0){var l=[],m=0;if(thymol.thUsingNullPrefix)l=k;else for(b=0,c=k.length;c>b;b++){var n=k[b];if(n)for(d=0,e=thymol.thThymeleafPrefixList.length;e>d;d++){var o=n.name.toString();o.length>thymol.thThymeleafPrefixList[d].length&&(o=o.substring(0,thymol.thThymeleafPrefixList[d].length),o===thymol.thThymeleafPrefixList[d]&&(n.order=b,l[m++]=n))}}if(l.length>0){l.sort(function(a,b){return b.order-a.order});var p=[];for(b=0,c=l.length;c>b;b++){var q=l[b].name.toString().split(":");if(q&&q.length>0){var r,s="";if(q.length>1)s=q[0],r=q[1];else{r=q[0];var t=r.lastIndexOf("-");t>=0&&(s=r.substring(0,t+1))}var u=thymol.thThymeleafPrefixList[s];if(q.length>1&&(s+=":"),u)for(d=0,e=u.length;e>d;d++){var v=!1;if(r===u[d].suffix||r===u[d].synonym)v=!0;else if(null!==u[d].regex){var w=s+r;v=u[d].regex.test(w)}if(v){var x={};x.attr=u[d],x.elementAttr=l[b],p.push(x);break}}}}if(p.length>0){p.sort(function(a,b){return a.attr.precedence-b.attr.precedence});var j=!1;for(b=0,c=p.length;c>b;b++){var y=thymol.ThUtils.processElement(p[b].attr.process,i,p[b].elementAttr,p[b].attr,1);j=y||j}j&&(h=a.thDoc.getElementsByTagName("*"),f--,g=h.length)}}}}h=a.thDoc.getElementsByTagName("*");var z=0;for(f=0,g=h.length;g>f;f++){var i=h[z],A=i.nodeName.toLowerCase();A==thymol.thBlock.name||A==thymol.thBlock.synonym?(thymol.ThUtils.removeTag(i),h=a.thDoc.getElementsByTagName("*")):z++}},override:function(a,b){var c,d=b;return c=thymol.thWindow[a],"undefined"==typeof c&&(c=thymol.applicationContext.javascriptify(a)),c&&(d=c instanceof thymol.ThParam?c.value:c),c=thymol.applicationContext[a],c&&(d=c instanceof thymol.ThParam?c.value:c),c=thymol.requestContext[a],c&&(d=c instanceof thymol.ThParam?c.value:c),d},doDisable:function(a){var b=this.getThAttrByName(a);null!==b?b.disable():thymol.debug&&thymol.thWindow.alert('cannot disable unknown attribute "'+a+'"')},getThAttrByName:function(a){var b=thymol.thThymeleafPrefixList[thymol.prefix];b.push(thymol.thInclude),b.push(thymol.thReplace),b.push(thymol.thSubstituteby),b.push(thymol.thFragment);var c,d=b.length;for(c=0;d>c;c++)if(a===b[c].suffix)return b[c];return null},getContents:function(a){var b=this.getContentRoot(a),c=$(b),d=c.find("*");return d},getContentRoot:function(a){var b=a.thDoc;return"#document"!==b.nodeName&&(b=b.childNodes),b},processComments:function(a){var b,c,d,e,f,g,h,i,j,k=null;do for(b=this.getContents(a),k=b.contents().getComments(),c=!1,d=0,e=k.length;e>d;d++)if(f=k[d],g=f.parentNode,h=f.nodeValue.trim(),X.test(h))for(i=f;null!=i;){if(Y.test(i.nodeValue)){c=null!=g.removeChild(i);break}j=i.nextSibling,c=null!=g.removeChild(i),i=j}else Z.test(h)&&_.test(h)&&(g.removeChild(f),c=!0);while(c);this.processPrototypeOnlyComments(a)},processPrototypeOnlyComments:function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A=null;do for(b=this.getContents(a),A=b.contents().getComments(),c=!1,d=A.length-1,e=0,f=A.length;f>e;e++)if(k=A[e],l=k.parentNode,null!=l&&(startValue=k.nodeValue.trim(),m=[],m.push(k),startValue=startValue.replace(/\n/g,""),n=startValue.match(aa)))if(o=startValue,"table"==l.localName||"tbody"==l.localName){if(startValue.indexOf(thymol.thBlock.name)>=0||startValue.indexOf(thymol.thBlock.synonym)>=0)if(startValue.indexOf(thymol.thBlock.endName)<0||startValue.indexOf(thymol.thBlock.endSynonym)<0){o=o.replace(n[0],n[1]),p=[],q=!1,r=k;do r=r.nextSibling,null!=r?(m.push(r),d>e&&(r==A[e+1]?(s=r.nodeValue,(s.indexOf(thymol.thBlock.endName)>=0||s.indexOf(thymol.thBlock.endSynonym)>=0)&&(t=s.match(aa),t&&(s=s.replace(t[0],t[1]),o+=s),q=!0)):p.push(r))):q=!0;while(!q);for(u=null,v=(new thymol.thDomParser).parseFromString(o,"text/html"),w=$(v).find("body")[0],g=0,h=w.childNodes.length;h>g;g++)if(w.childNodes[g].localName==thymol.thBlock.name||w.childNodes[g].localName==thymol.thBlock.synonym)for(u=w.childNodes[g],i=0,j=p.length;j>i;i++)y=v.importNode(p[i],!0),u.appendChild(y);null!=u?(x=new K(v,!1,null,null,null,v.nodeName,"::",!1,v),this.processChildren(x),c=this.insertUncommented(x.thDoc,m,l)):(l.removeChild(k),c=!0)}else l.removeChild(k),c=!0}else startValue=startValue.substring(3,startValue.length-3),z=(new thymol.thDomParser).parseFromString(startValue,"text/html"),c=this.insertUncommented(z,m,l);while(c)},insertUncommented:function(a,b,c){var d,e,f,g=$(a).find("body")[0];for(d=0,e=g.childNodes.length;e>d;d++)c.ownerDocument===a?f=g.childNodes[d].cloneNode(!0):(f=c.ownerDocument.importNode(g.childNodes[d],!0),f.parentNode=c),c.insertBefore(f,b[0]);for(d=0,e=b.length;e>d;d++)c.removeChild(b[d]);return!0},getList:function(a,b){var c,d,e,f,g=b.trim(),h=0,i=[];if(g){for(c=g.split(","),d=0,e=c.length;e>d;d++)f=thymol.getExpression(c[d],a),i[d]=f;a.thLocalVars||(a.thLocalVars={}),a.thLocalVars["..."]=i,h=i.length}return h},testParam:function(a){var b=a,c=!1,d=null,e=!1;return"boolean"==typeof b?c=b:(d=null,
+e=!1,"object"==typeof b&&b instanceof thymol.ThParam?d=b:(b=b.valueOf(),"!"==b.charAt(0)&&(e=!0,b=b.substring(1))),d=thymol.applicationContext[b],null!=d&&(c=d.getBooleanValue()),e&&(c=!c)),c?!0:!1},processImport:function(b,c,d){var e,f,g,h,i,j,k,l,m,n,o=null;if(e=null,d.value.indexOf("::")<0?(e=d.value,f="::"):(g=d.value.split("::"),e=g[0].trim(),f=g[1].trim()),e="this"===e?"":this.getFilePath(e,b),null!=e&&(h=e.match(ea),i=null,h&&(h.length>1&&(e=h[1].trim()),h.length>2&&(i=h[2].trim())),""!=e||!A(b)))if(j=thymol.thReplace.name==d.localName||thymol.thReplace.synonym==d.localName||thymol.thSubstituteby.name==d.localName||thymol.thSubstituteby.synonym==d.localName,null!=thymol.thCache[e]&&null!=thymol.thCache[e][f])j=j||"::"==f,o=new K(thymol.thCache[e][f],!1,c,null,null,e,f,j,b);else if(k=null,n=null,""!=e?(l=e+thymol.templateSuffix,$.get(l,function(c,d){try{"success"==d?(m=(new thymol.thDomParser).parseFromString(c,"text/html"),k=a.prototype.getImportNode(b,e,f,i,m)):thymol.debug&&thymol.thWindow.alert("thymol.processImport file read failed: "+e+" fragment: "+f)}catch(g){n=g}},"text")):k=this.getImportNode(b,e,f,i,thymol.thDocument),null==k){if(null!==n)throw n;thymol.debug&&thymol.thWindow.alert("thymol.processImport fragment import failed: "+e+" fragment: "+f)}else o=new K(k,!1,c,null,null,e,f,j,b);return b.removeAttribute(d.name),o},getImportNode:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x=null,y=c.trim(),z=y;if(y=y.replace(/text\(\)/g,U),f=y.match(ea),null==f&&null!=d&&(f=[],f[1]=y,f[2]=d),g=0,f&&f.length>1&&(y=f[1].trim(),f.length>2&&(g=f[2].indexOf("=")>0?thymol.getWith(a,f[2]):this.getList(a,f[2]))),null==thymol.thCache[b]&&(thymol.thCache[b]=new Object),h=!1,i=null,"::"==y)j=$("html",e)[0],x=j,h=!0;else for(k=$(thymol.thFragment.escpName,e),l=0,m=k.length;m>l;l++){for(i=k[l],n=0,o=i.attributes.length;o>n;n++){if(q=i.attributes[n],q=q.value.replace(/\s/g,""),r=null,s=q.match(ea),s&&s.length>1&&(r=s[1].trim()),y==r&&g>0&&s.length>2&&(t=s[2].trim().split(","))){if(t.length==g){if(u=a.thLocalVars["..."],null!=u){for(p=0;g>p;p++)v=t[p].trim(),a.thLocalVars[v]=u[p];a.thLocalVars["..."]=null}h=!0;break}if(t.length>g)break}if(y==q||z==q||y==r){h=!0;break}}if(h){x=i;break}}if(!h)if(i=this.getDOMSelection(y,e))h=!0,x=i;else if(!a.isBlockChild)throw new thymol.ThError('getImportNode cannot match fragment: "'+y+'"',a);return thymol.thCache[b][z]=x,h&&(w=x.cloneNode(!0),1==w.nodeType&&(w.removeAttribute(thymol.thFragment.name),w.removeAttribute(thymol.thFragment.synonym)),x=w,x.thLocalVars=a.thLocalVars),x},getDOMSelection:function(a,b){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z=a,A=null,B="",C=new Array,D="",E=thymol.ThUtils.unBracket(z);for(z!=E&&"]"==E.charAt(E.length-1)&&(z=E);""!=z&&(D=z.match(fa),null!=D&&D.length>1);)for(c=1,d=D.length;d>c;c++)if(null!=D[c]){k=D[c],l=null,E=thymol.ThUtils.unBracket(k),k!=E&&E.match(da)&&(l=E),m=z,z=z.replace(k,""),m==z&&(z=""),l?(k=C[C.length-1],n=new String(k),n.indx=l,C[C.length-1]=n):C.push(k.trim());break}for(o=0,C.length>0&&""!=C[0]&&"/"==C[0].charAt(0)&&(B=C[0],o=1),p=[],p.push(b),q=!1,c=o,d=C.length;d>c;c++){if(r=C[c],E=thymol.ThUtils.unBracket(r),r!=E)for(E=E.replace(/[']/g,'"'),r="",s=E.split(/\s{1}\s*((?:and)|(?:or))\s{1}\s*/),e=0,f=s.length;f>e;e++)"and"!=s[e]&&"or"!=s[e]?(t=s[e].match(/[@]?\s*(?:class)\s*(\W?[=])\s*[\"]((?:\w*[\-_]*)*)[\"]/),t&&t.length>0?("="==t[1]&&(r=r+"[class~='"+t[2]+"']"),"^="==t[1]&&(r=r+"[class^='"+t[2]+"'],[class*=' "+t[2]+"']")):r=r+"["+s[e]+"]"):"or"==s[e]&&(r+=",");for(u=r.split("/"),e=0,f=u.length;f>e;e++)if(""!=u[e]){for(u[e]=u[e].replace(/[@]/g,""),null!=r.indx&&(u[e]=u[e]+":eq("+r.indx+")"),v=[],g=0,h=p.length;h>g;g++)if(w=null,u[e]==U?w=$(p[g]).contents().filter(function(){return 3===this.nodeType}):q?w=$(p[g]).children(u[e]):0==e?"/"==B?(x=$("html",p[g]),x.length>0&&(p[g]=x),w=$(p[g]).children("body").children(u[e]),B=""):0==c||"//"==B?(w=$(p[g]).find(u[e]),B=""):w=$(p[g]).filter(u[e]):w=$(p[g]).children(u[e]),null!=w)for(i=0,j=w.length;j>i;i++)v.push(w[i]);p=v}q=""==u[u.length-1]}if(A=p,null!=A&&void 0!==A.length)if(A.length>1){for(y=thymol.thDocument.createDocumentFragment(),c=0,d=A.length;d>c;c++){var F=thymol.thDocument.importNode(A[c],!0);y.appendChild(F)}A=y}else A=A[0];return A},getFilePath:function(a,b){var c,d=thymol.substitute(a,b),e=null;if(d&&thymol.mappings&&(e=thymol.getMapped(d,!1)),e)d=e;else{var f="."===d.charAt(0);if(d&&(thymol.useAbsolutePath||!f)&&(c=d.indexOf("/"),thymol.useAbsolutePath||c>=0)){0!=c||thymol.useAbsolutePath||(d=d.substring(1));var g="";thymol.useAbsolutePath&&(g=thymol.protocol),d=thymol.useAbsolutePath&&thymol.absolutePath?g+thymol.absolutePath+d:f?thymol.templatePath+d:g+thymol.root+thymol.path+d}}return d},doLiteralSubstExpr:function(a,b){var c,d,e,f=a.trim();if(thymol.ThUtils.isLiteralSubst(f))f=this.decodeLiteralSubst(f);else for(c=b;null!=c&&thymol.ThUtils.isLiteralSubst(c)&&(d=this.decodeLiteralSubst(c),f=f.replace(c,d),e=f.match(ga),e&&e.length>0);)c=e[1];return f},decodeLiteralSubst:function(a){var b,c,d,e,f=a;if(f=f.trim(),f=f.substring(1,f.length-1),f=f.replace(/[\']/g,"&#39;"),b=f.split(V),b&&b.length>0){for(c="",d=0,e=b.length;e>d;d++)""!=b[d]&&(b[d].match(V)||(b[d]="'"+b[d]+"'"),c=""==c?b[d]:c+"+"+b[d]);f=c}return f},doReplace:function(a,b,c){if(a){var d=b.parentNode;if("html"==c.nodeName.toLowerCase())this.doInsertion(b,c,function(a,b){1==b.nodeType&&(b.removeAttribute(thymol.thFragment.name),b.removeAttribute(thymol.thFragment.synonym)),a.parentNode.insertBefore(b,a)}),d.removeChild(b);else{var e=this.doClone(c,d.ownerDocument);1==e.nodeType&&(e.removeAttribute(thymol.thFragment.name),e.removeAttribute(thymol.thFragment.synonym)),d.replaceChild(e,b),e.parentNode=d}}else try{for(;null!=b.firstChild&&(b.removeChild(b.firstChild),null!=b.firstChild););this.doInsertion(b,c,function(a,b){1==b.nodeType&&(b.removeAttribute(thymol.thFragment.name),b.removeAttribute(thymol.thFragment.synonym)),a.appendChild(b)})}catch(f){b.innerHTML=c.innerHTML}},doClone:function(a,b){var c,d,e,f,g;if(c=a.parentNode&&a.parentNode.ownerDocument===b?a.cloneNode(!1):b.importNode(a,!1),null!==c&&(1==c.nodeType&&null!==a.thLocalVars&&(c.thLocalVars=a.thLocalVars),null!==a.childNodes&&(d=a.childNodes.length,d>0)))for(e=0;d>e;e++)f=a.childNodes[e],null!==f&&(g=this.doClone(f,b),null!==g&&c.appendChild(g));return c},doInsertion:function(a,b,c){var d,e,f,g,h,i,j,k,l,m=!0,n=a.parentElement;for(null!=n&&(m="html"==a.parentElement.nodeName.toLowerCase()),d=0,e=b.childNodes.length;e>d;d++)if(f=b.childNodes[d])if(m)l=this.doClone(f,n.ownerDocument),c(a,l);else if(g=f.nodeName.toLowerCase(),"head"!=g)if("body"==g)for(h=0,i=f.childNodes.length;i>h;h++)j=f.childNodes[h],j&&(k=this.doClone(j,n.ownerDocument),c(a,k));else l=this.doClone(f,n.ownerDocument),c(a,l)},getThParam:function(a,b,c,d){var e=d,f=thymol.thWindow[a],g=thymol.ThUtils.getParameter(a);return"undefined"==typeof f&&(f=thymol.applicationContext.javascriptify(a)),g?(g instanceof M&&g.globalValue!==f&&(g.globalValue=f,g.value=f,e=f),b&&(e=g.getBooleanValue())):"undefined"!=typeof f&&null!=f&&(e=b?1==f:f),!b&&c&&e.length>0&&"/"!=e.charAt(e.length-1)&&(e+="/"),thymol.applicationContext.createVariable(a,e),e}},L.prototype=new Error,L.prototype.constructor=L,P.prototype.fromArray=function(a){var b,c,d=new thymol.ThSet;for(b=0,c=a.length;c>b;b++)d.add(a[b]);return d},Q.prototype=new P,Q.prototype.constructor=Q,{Thymol:a,ThError:L,ThParam:M,ThAttr:N,ThElement:O,ThSet:P,ThMap:Q,ThObject:R,ThVarsAccessor:S,ThClass:T,thDomParser:thymol.thDomParser,thDocument:thymol.thDocument,thWindow:thymol.thWindow,thTop:thymol.thTop,thRequest:thymol.thRequest,thVersion:thymol.thVersion,thReleaseDate:thymol.thReleaseDate,thURL:thymol.thURL,thAltURL:thymol.thAltURL,thInclude:thymol.thInclude,thReplace:thymol.thReplace,thSubstituteby:thymol.thSubstituteby,thFragment:thymol.thFragment,thRemove:thymol.thRemove,thBlock:thymol.thBlock,thScriptName:thymol.thScriptName,thDefaultPrefix:thymol.thDefaultPrefix,thDefaultDataPrefix:thymol.thDefaultDataPrefix,thDefaultPrecision:thymol.thDefaultPrecision,thDefaultProtocol:thymol.thDefaultProtocol,thDefaultLocale:thymol.thDefaultLocale,thDefaultPrecedence:thymol.thDefaultPrecedence,thDefaultMessagePath:thymol.thDefaultMessagePath,thDefaultResourcePath:thymol.thDefaultResourcePath,thDefaultMessagesBaseName:thymol.thDefaultMessagesBaseName,thDefaultRelativeRootPath:thymol.thDefaultRelativeRootPath,thDefaultExtendedMapping:thymol.thDefaultExtendedMapping,thDefaultLocalMessages:thymol.thDefaultLocalMessages,thDefaultDisableMessages:thymol.thDefaultDisableMessages,thDefaultTemplateSuffix:thymol.thDefaultTemplateSuffix,thThymeleafPrefixList:thymol.thThymeleafPrefixList,thThymeleafElementsList:thymol.thThymeleafElementsList,thLocation:thymol.thLocation,messagePath:thymol.messagePath,resourcePath:thymol.resourcePath,relativeRootPath:thymol.relativeRootPath,messagesBaseName:thymol.messagesBaseName,extendedMapping:thymol.extendedMapping,scriptPath:thymol.scriptPath,absolutePath:thymol.absolutePath,useAbsolutePath:thymol.useAbsolutePath,useFullURLPath:thymol.useFullURLPath,localMessages:thymol.localMessages,indexFile:thymol.indexFile,disableMessages:thymol.disableMessages,templateSuffix:thymol.templateSuffix,prefix:thymol.prefix,dataPrefix:thymol.dataPrefix,templateName:thymol.templateName,templatePath:thymol.templatePath,objects:thymol.objects,jqSetup:d,isClientSide:b,execute:c,updatePrefix:g,init:h,ready:e,addDialect:J,isFragmentChild:A,preProcess:r,substitute:w,substituteParam:s,configureModule:j,configureAttributeProcessor:k,configureElementProcessor:l,configurePreExecution:m,configurePostExecution:n,getStandardURL:t,getMessage:F,getExpression:u,getWith:x,getParsedExpr:y,getLocale:C,getMapped:v,getBooleanValue:z,setLocale:B}}(),thymol.makeContext=function(a,b){var c="(?:\\W*([\\'][A-Za-z]+(?:\\w|[$])*[\\'])\\s*[:])?\\s*([#][A-Za-z]+(?:\\w|[$])*)(?:\\W|[^$])*",d=new RegExp(c),e=new Array;return e.contextName=a,e.varAccessor=b,e.varStore=[],e.varNamePrefix="","undefined"==typeof b&&(e.varAccessor=new thymol.ThVarsAccessor(e.varStore,"varStore")),e.varNamePrefix=e.varAccessor.arrayName+"[",e.getJSONView=function(a,b){var c,d=typeof a,e="";return"string"===d?e=e+"'"+a+"'":"number"===d||"boolean"===d?e+=a:"object"===d&&a instanceof Object&&(c=Object.prototype.toString.call(a),"[object Array]"===c?e=this.getJSONViewArray(a,!1):"[object Object]"===c&&(e=this.getJSONViewObject(a,!1)),e="#"+e),e},e.init=function(){var a,b,c,d,e,f,g=thymol.thTop.name;if(g&&""!==g&&(c=this.javascriptify(g),c&&c.length>0))for(d=0,e=c.length;e>d;d++)a=c[d],a&&(b=a[0],b&&(f=a[1],this.createVariable(b,f)))},e.getJSONViewObject=function(a,b){var c,d,f,g,h,i,j,k,l,m=!0,n=null,o="{";"boolean"==typeof b&&(m=b);for(n in a)if(n&&(c=a[n],"function"!=typeof c))if("{"!=o&&(o+=","),d=this.getJSONView(n,!1),f=this.getJSONView(c,!1),o=o+d+":",m||"object"!=typeof c)o+=f;else{g=1,h=n+"$",instanceName=null,i=!1;do if(instanceName=h+g++,l=e[instanceName],null===l||"undefined"==typeof l){for(i=!1,j=0,k=varStore.length;k>j;j++)if(instanceName===varStore[j][0]){i=!0;break}i||this.addAttribute(instanceName,f)}while(i);null!==instanceName&&(o=o+"#"+instanceName)}return o+="}"},e.getJSONViewArray=function(a,b){var c,d="[";for(c=0;c<a.length;c++)d+=this.getJSONView(a[c],!1),c<a.length-1&&(d+=",");return d+="]"},e.getAttribute=function(a){return e[a]},e.addAttribute=function(a,b){var c=[];c[0]=a,c[1]=b,varStore.push(c)},e.serialise=function(){varStore=[];var a,b,c,d,f,g,h="[",i=null;for(i in e)i&&(a=e[i],null!=a&&"object"==typeof a&&(b=Object.prototype.toString.call(a),"[object Array]"===b||a instanceof thymol.ThClass||a instanceof thymol.ThVarsAccessor||("["!==h&&(h+=","),c=this.getJSONView(a,!0),h+="[",h=h+'"'+i+'"',h+=",",h=h+'"'+c+'"',h+="]")));for(f=0,g=varStore.length;g>f;f++)d=varStore[f][0],c=varStore[f][1],h+=",[",h=h+'"'+d+'"',h+=",",h=h+'"'+c+'"',h+="]";return h+="]"},e.javascriptify=function(a){try{return new Function("return "+a)()}catch(b){return void 0}},e.createVariable=function(a,b,c){var d,f,g,h,i,j,k,l=b;if(d=l,!(l instanceof thymol.ThParam)&&(f=typeof b,"function"!==f&&"object"!==f)){if("string"===f)try{l=c?decodeURIComponent(l):decodeURI(l)}catch(m){}if("boolean"===f||"number"===f)d=new thymol.ThParam(l);else if(l||""===l)if(g=thymol.ThUtils.testLiteralFalse(l))d=!1;else if(h=new String(l),i=h.trim(),"#"===i.charAt(0)){i=i.substring(1);try{d=this.createJSONVariable(i)}catch(m){m instanceof ReferenceError,m instanceof EvalError,(null==d||c)&&(d=new thymol.ThParam(l))}}else d=new thymol.ThParam(h.toString())}return c?(j=e[a],"undefined"!=typeof j&&null!==j?"[object Array]"===Object.prototype.toString.call(j)?j.push(d):thymol.debug&&thymol.thWindow.alert('request parameters should be of type string array "'+a+'"'):(k=new Array,k["class"]={},k["class"].name="[Thymol.ThParam]",k.push(d),e[a]=k)):e[a]=d,d},e.createJSONVariable=function(a){var b,c,e,f,g,h,i=a.trim(),j=" ";for(b=this.varAccessor.length()+1;j;)j=i.match(d),j&&j.length>2&&(c=j[2],c=c.replace(/[\']/g,"[']").replace(/[$]/g,"[$]"),e=new RegExp(c),f=this.varNamePrefix+b+"]",g=new Object,g.name=j[2].substring(1),this.varAccessor.set(b,g),b+=1,i=i.replace(e,"'"+f+"'","g"));return i=i.replace(/[\']/g,'"'),h=$.parseJSON(i),"[object Array]"!==Object.prototype.toString.call(h)&&(h=new thymol.ThObject(h)),h},e.resolveJSONReferences=function(){var a,b,c,d,f=null,g=null,h="request"===this.contextName;for(f in e)if(f&&(a=e[f],null!=a&&"object"==typeof a&&!(a instanceof thymol.ThVarsAccessor||a instanceof thymol.ThClass)))if(a instanceof thymol.ThParam)"string"==typeof a.value&&"#"==a.value.charAt(0)&&(d=e[a.value.substring(1)],e[f]=d);else if(h&&"[object Array]"===Object.prototype.toString.call(a))for(var i=0,j=a.length;j>i;i++){var k=a[i];if(k&&"string"==typeof k.value&&"#"==k.value.charAt(0)){var l=thymol.ThUtils.getParameter(k.value.substring(1));a[i]=l}}else for(g in a)g&&(b=a[g],"string"==typeof b&&0==b.indexOf(this.varNamePrefix)&&(d=null,g.match(/\d*/)?(c=b.substring(this.varNamePrefix.length,b.length-1),c=this.varAccessor.get(c),d=e[c.name]):d=e[g],a[g]=d))},e},thymol.ThUtils=function(){function a(a,b){var c=a,d=null;c||(c={});for(d in b)b.hasOwnProperty(d)&&d&&(c[d]||(c[d]=b[d]));return c}function b(b,c,d,e){var f=null,g=c.parentElement;if(!thymol.isFragmentChild(c)){if(!c.thObjectVar)for(g=c.parentElement;g;){if(g.thObjectVar){c.thObjectVar=g.thObjectVar;break}g=g.parentElement}for(g=c.parentElement;g;){if(g.thLocalVars){c.thLocalVars=a(c.thLocalVars,g.thLocalVars);break}g=g.parentElement}f=b(c,d,e)}return f}function c(a){var b,c=a;return c&&"string"==typeof c&&(c=c.trim(),'"'==c.charAt(0)?'"'==c.charAt(c.length-1)&&(b=c.substring(1,c.length-1),0==e(b,'"','"')&&(c=b)):"'"==c.charAt(0)&&"'"==c.charAt(c.length-1)&&(b=c.substring(1,c.length-1),0==e(b,"'","'")&&(c=b))),c}function d(a){var b,c=a;return c&&"string"==typeof c&&(c=c.trim(),"("==c.charAt(0)&&")"==c.charAt(c.length-1)&&(b=c.substring(1,c.length-1).trim(),0==e(b,"(",")")&&(c=b))),c}function e(a,b,c){var d,e,f=a.length,g=0;for(d=0;f>d;d++)if(e=a.charAt(d),e==b)g++;else if(e==c&&(g--,0>g))break;return g}function f(a){var b,c=a;return"string"==typeof c&&(c=c.trim()),c&&"["==c.charAt(0)&&"]"==c.charAt(c.length-1)&&(b=c.substring(1,c.length-1),0==e(b,"[","]")&&(c=b)),c}function g(a,b){if("undefined"==typeof b)return a;var c,d,e,f,g=thymol.thDefaultPrecision,i=0;return b>g?g=b:(c=a.toString(),d=c.length,e=c.indexOf("."),e>=0&&(i=d-1-e),i>g&&(f=a.toPrecision(i+1),f=h(f),c=f.toString(),d=c.length,e>=0&&(i=d-1-e)),b>i?g=b:g>i&&(g=i)),f=parseFloat(a),f=f.toFixed(g),0===b&&(f=Number(f)),f}function h(a){var b,c=a,d=a.length-1;for(b=d;b>=0&&"0"===c.charAt(b);b--)c=c.substr(0,b);return c}function i(a){var b,c,d=0;return b=a.toString(),c=b.indexOf(".")+1,c>0&&(d=b.length-c),d}function j(a){var b,c=!1;return"string"==typeof a?(b=a.toLowerCase(),c="false"==b||"off"==b||"no"==b):"boolean"==typeof a&&(c=!a),c}function k(a,b){var c,d,e=a;if("[object Array]"==Object.prototype.toString.call(b))for(c=0,d=b.length;d>c;c++)e=l(e,c,b[c]);else e=l(a,0,b);return e}function l(a,b,c){var d,e,f,g,h=a;if(d=a.split("{"+b+"}"),d.length>0)for(h="",e=0,f=d.length,g=f-1;f>e;e++)h+=d[e],g>e&&(h+=c);return h}function m(a){var b,c;return b=thymol.requestContext[a],c=typeof b,"undefined"===c?(b=thymol.sessionContext[a],"undefined"==typeof b&&(b=thymol.applicationContext[a])):"object"===c&&"[object Array]"===Object.prototype.toString.call(b)&&1===b.length&&(b=b[0]),b}function n(a,b){for(var c=0,d=0,e=a.length;e>d;d++)a.charAt(d)===b&&c++;return c}function o(a){var b,c;if("string"==typeof a){if(b=a.charAt(0),c=a.charAt(a.length-1),"'"==b&&"'"==c)return!0;if('"'==b&&'"'==c)return!0}return!1}function p(a){var b=!1,c=a;return"string"==typeof c&&(c=c.trim()),c&&"|"==c.charAt(0)&&"|"==c.charAt(c.length-1)&&(b=!0),b}function q(a){{var b=thymol.Thymol.prototype.getFilePath(a),c="";$.ajax({type:"GET",url:b,dataType:"script",cache:!0,async:!1}).done(function(){c="success"}).fail(function(){c="error"})}}function r(a){var b,c,d,e,f,g=a;if(null!==a&&"undefined"!=typeof a)for(g="",c=a.length,d=c-3,b=0;c>b;b++)e=a.charAt(b),d>b&&"&"===e&&(f=a.charAt(b+1).toLowerCase(),"g"!==f&&"l"!==f||"t"!==a.charAt(b+2).toLowerCase()||";"!==a.charAt(b+3)?d-1>b&&"a"===f&&"m"===a.charAt(b+2).toLowerCase()&&"p"===a.charAt(b+3).toLowerCase()&&";"===a.charAt(b+4)?b+=4:d-2>b&&("q"===f&&"u"===a.charAt(b+2).toLowerCase()&&"o"===a.charAt(b+3).toLowerCase()&&"t"===a.charAt(b+4).toLowerCase()&&";"===a.charAt(b+5)?(b+=5,e='"'):"a"===f&&"p"===a.charAt(b+2).toLowerCase()&&"o"===a.charAt(b+3).toLowerCase()&&"s"===a.charAt(b+4).toLowerCase()&&";"===a.charAt(b+5)&&(b+=5,e="'")):(b+=3,e="g"===f?">":"<")),g+=e;return g}function s(a){var b=a.replace(/\\u([\da-f]{4})/gi,function(a,b){return String.fromCharCode(parseInt(b,16))});return b=r(b)}function t(a){var b,c,d=a.parentNode,e=a.thObjectVar,f=a.thLocalVars;if(d){for(b=0,c=a.childNodes.length;c>b;b++){var g=a.childNodes[b].cloneNode(!0);1===g.nodeType&&(e&&(g.thObjectVar=e),f&&(g.thLocalVars=f)),d.insertBefore(g,a)}d.removeChild(a)}}function u(a){var b=a;return b=encodeURIComponent(b),b=b.replace(/%20/g,"+"),b=b.replace(/%26/g,"&"),b=b.replace(/%3A/g,":"),b=b.replace(/!/g,"%21"),b=b.replace(/'/g,"%27"),b=b.replace(/\(/g,"%28"),b=b.replace(/\)/g,"%29"),b=b.replace(/\*/g,"%2A"),b=b.replace(/~/g,"%7E")}return{getParameter:m,processElement:b,unQuote:c,unParenthesise:d,unBracket:f,getToPrecision:g,getDecimalDigits:i,testLiteralFalse:j,renderMessage:k,charOcurrences:n,isLiteral:o,isLiteralSubst:p,loadScript:q,unescape:r,unicodeUnescape:s,removeTag:t,getRequestEncoded:u}}(),thymol.ThParser=function(a){function b(a){function b(){}return b.prototype=a,new b}function c(a){this.varName=a}function d(a,b,c,d,e,f){this.type_=a,this.index_=b||0,this.prio_=c||0,this.number_=void 0!==d&&null!==d?d:0,this.mode_=void 0!==e&&null!==e?e:0,this.meta_=f,this.toString=function(){switch(this.type_){case E:return this.number_;case F:case G:case H:return this.index_;case I:case J:case K:return"CALL";default:return"Invalid Token"}}}function e(a,b,c,d,e,f){this.tokens=a,this.ops1=b,this.ops2=c,this.functions=d,this.precision=e,this.position=f}function f(a,b){return a+b}function g(a){return a}function h(a,b){return a-b}function i(a,b){return a*b}function j(a,b){return a/b}function k(a,b){return a%b}function l(a,b){return""+a+b}function m(a){return-a}function n(a){var b=thymol.getBooleanValue(a);return!b}function o(a){return Math.random()*(a||1)}function p(a){for(var b=Math.floor(a),c=b;b>1;)c*=--b;return c}function q(a,b){if(null==a)return null!=b?b.arrayResult===!0||"[object Array]"!=Object.prototype.toString.call(b)?[a,b]:b:null;if(a.arrayResult===!0||"[object Array]"!=Object.prototype.toString.call(a))return[a,b];var c=a.slice();return c.push(b),c}function r(a,b){return a==b}function s(a,b){return a!=b}function t(a,b){return a>b}function u(a,b){return a>=b}function v(a,b){return b>a}function w(a,b){return b>=a}function x(a,b){return a&&b}function y(a,b){return a||b}function z(a,b){return a[b]}function A(a,b){return a?b:null}function B(a,b){return null!=a?a:b}function C(a,b,c,d,e){var f=c,g="",h=b.charAt(a),i=a+1,j=b.length,k=h;(4===f||"#"===h)&&(k="}",f=4);var l=i,m=!1,n=null,o=-1,p=null;if(4!==f&&"'"!==h&&'"'!==h){for(;j>=l;l++){if(h.toUpperCase()===h.toLowerCase()){if("{"===h?(m=!0,n=l,null===p&&(p={},p.paths=[])):2===c&&"#"===h&&(o=l),(l===a||!m&&"}"===h||"_"!==h&&"?"!==h&&":"!==h&&("0">h||h>"9"))&&((!d||"-"!=h)&&(2!==c&&6!==c||!("/"===h||"."===h||"~"===h||"?"===h||"="===h||":"===h||"-"===h||"_"===h||"["===h||"]"===h||"#"===h||m&&"{"===h||m&&"}"===h))||6===c&&"="===h)){l-=1;break}if(m&&"}"===h){if(m=!1,null===p){var q='bad path variable definition in expression: "'+b+'" near column '+a;throw new thymol.ThError(q,element)}var r=b.substring(n,l-1),s=[];p.paths[r]=s}}g+=h,h=b.charAt(l)}if(o>=0){var t=b.substring(o-1,l);g=g.substring(0,g.length-t.length),null===p&&(p={},p.urlFragment=t)}}else{var u=!1,v=!1;for(("'"===h||'"'===h)&&(u=!0,k=h);j>=l;){if(h===k&&l>i&&!v){4!==f||u?g+=h:l-=1;break}var w=b.charAt(l);if("_"!==h||"_"!==w||e||(v=!v),"\\"===h&&"'"===w&&"\\"!==g.charAt(g.length-1)){if(h="&#39;",l+1>j)break;l+=1,w=b.charAt(l)}if(!u){if("."===h){var x=thymol.thExpressionObjects[g];if("undefined"!=typeof x&&null!==x){l-=1;break}}if("("===h){l-=1;break}}if(g+=h,l+1>j)break;l+=1,h=w}}var y=new Object;return y.str=g,y.pos=l,null!==p&&(y.meta=p),y}function D(){this.precision,this.success=!1,this.errormsg="",this.expression="",this.pos=0,this.tokennumber=0,this.tokenprio=0,this.tokenindex=0,this.tmpprio=0,this.ops1={sin:Math.sin,cos:Math.cos,tan:Math.tan,asin:Math.asin,acos:Math.acos,atan:Math.atan,sqrt:Math.sqrt,log:Math.log,abs:Math.abs,ceil:Math.ceil,floor:Math.floor,round:Math.round,"-":m,"!":n,not:n,exp:Math.exp,"=":g},this.ops2={"?":A,":":B,"?:":B,"+":f,"-":h,"*":i,"/":j,"%":k,"^":Math.pow,",":q,"||":l,"==":r,eq:r,"!=":s,ne:s,neq:s,div:j,mod:k,and:x,or:y,">":t,gt:t,">=":u,"=>":u,ge:u,"<":v,lt:v,"<=":w,"=<":w,le:w,".":z,"[":z},this.functions={random:o,fac:p,min:Math.min,max:Math.max,pow:Math.pow},this.consts={E:Math.E,PI:Math.PI}}var E=0,F=1,G=2,H=3,I=4,J=5,K=6;e.prototype={simplify:function(a){var c,f,g,h,i=a||{},j=[],k=[],l=this.tokens.length,m=0;for(m=0;l>m;m++){h=this.tokens[m];var n=h.type_;if(n===E)j.push(h);else if(n===H&&!(h.index_ in new Object)&&h.index_ in i)h=new d(E,0,0,i[h.index_]),j.push(h);else if(n===G&&j.length>1)g=this.ops2[h.index_],g&&(f=j.pop(),c=j.pop(),h=new d(E,0,0,g(c.number_,f.number_))),j.push(h);else if(n===F&&j.length>0)"{"==h.index_?2==h.mode_&&j.push(h):(c=j.pop(),g=this.ops1[h.index_],h=new d(E,0,0,g(c.number_)),j.push(h));else{for(;j.length>0;)k.push(j.shift());k.push(h)}}for(;j.length>0;)k.push(j.shift());var o=new e(k,b(this.ops1),b(this.ops2),b(this.functions),this.precision);return o},evaluate:function(a){var b,d,e,f,g,h=[],i=null,j=this.tokens.length,k=0;for(k=0;j>k;k++){if(f=this.tokens[k],0===k&&thymol.disableMessages&&4===f.mode_){var l=new thymol.ThClass;return l.abort=!0,l}var m=f.type_;if(m===E){if(h.push(f.number_),k==j-1)break}else if(m===G){d=h.pop(),("undefined"==typeof d||d instanceof c)&&(d=null),b=h.pop(),("undefined"==typeof b||b instanceof c)&&(b=null),e=this.ops2[f.index_];var n=!1;try{if(6===f.mode_)if(e===z)i=b+"["+d+"]";else if(e===q){if(f.meta_&&f.meta_.paths){var o=f.meta_.paths[b];o&&(o.push(d),n=!0,i=null)}if(!n){f.meta_||(f.meta_={}),f.meta_.params||(f.meta_.params=[]);var o=f.meta_.params[b];o||(o=[],f.meta_.params[b]=o),o.push(d),n=!0}}else i=d,h.push(b);else{if(e===z&&"class"===d&&b&&!b["class"]){var p=typeof d;i="object"===p&&d instanceof thymol.ThParam?e(b,d):new thymol.ThClass("JavaScript:"+p)}else i=e(b,d),"function"==typeof i&&j-1>k&&(v=this.tokens[k+1],v.type_===E&&"[object Array]"==Object.prototype.toString.call(v.number_)&&0==v.number_.length&&(k+=1,h.push(i),b.isDirect=!0,i=b));e!==q&&"[object Array]"==Object.prototype.toString.call(i)&&(i.arrayResult=!0)}}catch(r){if(!a.isBlockChild){var s=null==b?"null":b,t=null==d?"null":d,u="while evaluating expression: "+this.tokens[k-2].index_+": "+s+", "+this.tokens[k-1].index_+": "+t;throw new thymol.ThError(u,a,r)}}n||h.push(i)}else if(m===H){var v=null,w=h.length;if(null!=f.index_){if(j-1>k&&(v=this.tokens[k+1],v.type_===G&&"."===v.index_&&h.push(f.index_)),w===h.length){var x=thymol.substituteParam(f.index_,f.mode_,a);"[object Array]"==Object.prototype.toString.call(x)&&(x.arrayResult=!0),this.updatePrecision(x),null===x&&(x=new c(f.index_)),h.push(x)}}else if(w===h.length&&f.index_ in this.functions)h.push(this.functions[f.index_]);else if(!a.isBlockChild)throw new thymol.ThError("Exception undefined variable: "+f.index_,a)}else if(m===F){if(b=h.pop(),("undefined"==typeof b||b instanceof c)&&(b=2===f.mode_?"":null),i=b,"{"===f.index_){var y=this.tokens[k-1];if(7==y.mode_&&thymol.conversionService&&(b=thymol.conversionService(b),i=b),"string"==typeof b)if(2===f.mode_)i=thymol.getStandardURL(b);else{var A=thymol.substituteParam(b,f.mode_,a);null!=A&&(this.updatePrecision(A),i=A)}}else{e=this.ops1[f.index_];try{i=e(b)}catch(r){if(!a.isBlockChild){var s=null==b?"null":b,u="while evaluating expression: "+this.tokens[k-2].index_+": "+s;throw new thymol.ThError(u,a,r)}}}"[object Array]"==Object.prototype.toString.call(i)&&(i.arrayResult=!0),h.push(i)}else if(m===I||m===J||m===K){if(b=h.pop(),e=h.pop(),m===J)i=e instanceof c?"??"+e.varName+"_"+thymol.locale.value+"??":thymol.ThUtils.renderMessage(e,b),h.push(i);else if(m===K){var n=!1;if(d=h.pop(),"undefined"==typeof d&&(d=e,e=b,b=""),f.meta_&&f.meta_.paths){var o=f.meta_.paths[e];o&&(o.push(b),n=!0);for(var B in f.meta_.paths)if(f.meta_.paths.hasOwnProperty(B)){var o=f.meta_.paths[B],C=d.indexOf("?")>=0;if(o&&o.length>0){var D="{"+B+"}",L=new RegExp(D,"g"),M="";o.reverse();for(var N=0,O=o.length;O>N;N++)M.length>0&&(M+=","),M+=C?thymol.ThUtils.getRequestEncoded(o[N]):encodeURIComponent(o[N]);d=d.replace(L,M)}}}if(n?i=d:(e="undefined"==typeof e||e instanceof c?"":e.toString(),e=thymol.ThUtils.getRequestEncoded(e),e="?"+e,b=b.toString(),"?"!=e&&""!=b&&(e+="="),""!=b&&(b=thymol.ThUtils.getRequestEncoded(b),e+=b),d="undefined"==typeof d||d instanceof c?"":d.toString(),i=d+e),f.meta_){var P=i.indexOf("?")>=0?"&":"?";for(var B in f.meta_.params)if(f.meta_.params.hasOwnProperty(B)){var o=f.meta_.params[B];if(o&&o.length>0)for(var N=0,O=o.length;O>N;N++)i=i+P+thymol.ThUtils.getRequestEncoded(B)+"="+thymol.ThUtils.getRequestEncoded(o[N]),0==N&&(P="&")}f.meta_.urlFragment&&(i+=f.meta_.urlFragment)}h.push(i)}else if(e.apply&&e.call)b&&b.isDirect?i=e.call(b):(b instanceof c&&(b=null),i=null==b||!b.arrayResult&&"[object Array]"===Object.prototype.toString.call(b)?e.apply(a,b):e.call(a,b)),i instanceof String?(i.precision&&("undefined"==typeof this.precision||i.precision>this.precision)&&(this.precision=i.precision),i=i.toString()):"[object Array]"==Object.prototype.toString.call(i)&&(i.arrayResult=!0),h.push(i);else if(!a.isBlockChild)throw new thymol.ThError(e+" is not a function",a)}else if(!a.isBlockChild)throw new thymol.ThError("invalid expression item type: "+m,a)}if(h.length>1&&!a.isBlockChild)throw new thymol.ThError("invalid Expression (parity)",a);return g=h[0]},updatePrecision:function(a){if("number"==typeof a){var b=thymol.ThUtils.getDecimalDigits(a);("undefined"==typeof this.precision||b>this.precision)&&(this.precision=b)}}},D.parse=function(a,b,c){return(new thymol.ThParser).parse(a,b,c)},D.evaluate=function(a,b,c){return thymol.ThParser.parse(a,b,!1).evaluate(c)},D.Expression=e,D.values={sin:Math.sin,cos:Math.cos,tan:Math.tan,asin:Math.asin,acos:Math.acos,atan:Math.atan,sqrt:Math.sqrt,log:Math.log,abs:Math.abs,ceil:Math.ceil,floor:Math.floor,round:Math.round,random:o,fac:p,exp:Math.exp,min:Math.min,max:Math.max,pow:Math.pow,E:Math.E,PI:Math.PI};var L=1,M=2,N=4,O=8,P=16,Q=32,R=64,S=128,T=256,U=512,V=1024,W=2048,X=2048,Y=4096,Z=8192;return D.prototype={parse:function(a,c,f){this.errormsg="",this.success=!0;var g=[],h=[],i=[];this.tmpprio=0;var j=L|O|W|N|M|R|Y,k=0;for(this.expression=a,this.pos=0,this.mode=0;this.pos<this.expression.length;)if(this.isWhite());else if(this.isOperator())this.isSign()&&j&R?(this.isNegativeSign()&&(this.tokenprio=6,this.tokenindex="-",k++,this.addfunc(h,g,F)),j=L|O|W|N|R|Y):this.isAssign()&&j&Z?(k++,j=L|O|W|N|R|Y):this.isComment()||("!"==this.tokenindex?(0===(j&R)&&this.error_parsing(this.pos,"unexpected sign"),k+=1,this.addfunc(h,g,F)):(0===(j&M)&&this.error_parsing(this.pos,"unexpected operator"),k+=2,this.addfunc(h,g,G)),"["===this.expression.charAt(this.pos-1)&&(this.tmpprio+=20),j=L|M|O|W|N|R|Y);else if(this.isNumber()){0===(j&L)&&this.error_parsing(this.pos,"unexpected number");var l=new d(E,0,0,this.tokennumber);h.push(l),j=M|P|V|X|Q}else if(this.isLeftParenth()){if(0===(j&O)&&this.error_parsing(this.pos,'unexpected "("'),i.push(this.mode),j&S){k+=2,this.tokenprio=-2,this.tokenindex=-1,this.tmpprio+=2;var m=I;if(4===this.mode)m=J,this.mode=5;else if(2===this.mode){m=K,this.mode=6;var n=h[h.length-1];n.meta_||(n.meta_={}),this.meta=n.meta_}else this.mode=5;this.addfunc(h,g,m),this.tmpprio-=2}(5===this.mode||6===this.mode)&&(this.tmpprio+=10),j=L|M|O|W|N|R|Y|T}else if(this.isRightParenth()){if(j&T){var l=new d(E,0,0,[]);h.push(l)}else 0===(j&P)&&this.error_parsing(this.pos,'unexpected ")"');(5===this.mode||6===this.mode)&&(this.tmpprio-=10),this.mode=i.pop(),j=M|P|V|X|Q|O|W|S|Y}else if(this.isRightBracket())0===(j&V)&&this.error_parsing(this.pos,'unexpected "]"'),j=M|P|V|X|Q|O|W|S|Y;else if(this.isLeftVarBrk(i))0===(j&W)&&this.error_parsing(this.pos,'unexpected "{"'),k+=1,this.addfunc(h,g,F),j=L|O|W|N|R|Y;else if(this.isRightVarBrk())0===(j&X)&&this.error_parsing(this.pos,'unexpected "}"'),this.mode=i.pop(),j=N|M|P|V|X|Q|O|W|S|Y;else if(this.isLeftCurly())1==this.mode||2==this.mode||3==this.mode||4==this.mode?(i.push(this.mode),this.mode=7):this.error_parsing(this.pos,'unexpected "{"');else if(this.isRightCurly())7==this.mode?this.mode=i.pop():this.error_parsing(this.pos,'unexpected "}"');else if(this.isComma()){if(0===(j&Q)&&this.error_parsing(this.pos,'unexpected ","'),c)break;(5===this.mode||6===this.mode)&&(this.tmpprio-=10),this.tmpprio+=2,this.addfunc(h,g,G),this.tmpprio-=2,(5===this.mode||6===this.mode)&&(this.tmpprio+=10),k+=2,j=L|O|W|N|R|Y}else if(this.isConst()){0===(j&L)&&this.error_parsing(this.pos,"unexpected constant");var o=new d(E,0,0,this.tokennumber);h.push(o),j=M|P|X|V|Q}else{var p=C(this.pos,this.expression,this.mode,c,f);if(this.isOpX(p,this.ops2)&&2!==this.mode&&"/"!==p)("and"===p.str||"or"===p.str)&&(this.tokenprio=3),0===(j&M)&&this.error_parsing(this.pos,"unexpected binary operator"),this.addfunc(h,g,G),k+=2,j=L|O|W|N|M|R|Y;else if(this.isOpX(p,this.ops1))0===(j&M)&&this.error_parsing(this.pos,"unexpected unary operator"),this.addfunc(h,g,F),k++,j=L|O|W|N;else if(this.isLiteralValue(p)){0===(j&L)&&this.error_parsing(this.pos,"unexpected literal value");var l=new d(E,0,0,this.tokennumber);h.push(l),j=N|M|P|V|X|Q|O|X|U|S|Y,6===this.mode&&(j|=Z)}else if(this.isVar(p)){0===(j&L)&&this.error_parsing(this.pos,"unexpected variable");var q=new d(H,this.tokenindex,0,0,this.mode,p.meta);h.push(q),j=N|M|P|V|X|Q|O|X|U|S|Y|Z}else""===this.errormsg?this.error_parsing(this.pos,"unknown character"):this.error_parsing(this.pos,this.errormsg)}for((this.tmpprio<0||this.tmpprio>=10)&&this.error_parsing(this.pos,'unmatched "() or []"');g.length>0;){var r=g.pop();h.push(r)}k+1!==h.length&&this.error_parsing(this.pos,"parity");var s=new e(h,b(this.ops1),b(this.ops2),b(this.functions),this.precision,this.pos);return s},evaluate:function(a,b){return this.parse(a).evaluate(b)},error_parsing:function(a,b){throw this.success=!1,this.errormsg="parse error [column "+a+"]: "+b,new Error(this.errormsg)},addfunc:function(a,b,c){for(var e=new d(c,this.tokenindex,this.tokenprio+this.tmpprio,0,this.mode,this.meta);b.length>0&&e.prio_<=b[b.length-1].prio_;)a.push(b.pop());b.push(e)},isNumber:function(){
+for(var a=!1,b="",c=-1;this.pos<this.expression.length;){var d=this.expression.charCodeAt(this.pos);if(!(d>=48&&57>=d||46===d))break;b+=this.expression.charAt(this.pos),(c>=0||46===d)&&c++,this.pos++,a=!0}return a&&(c>=0&&("undefined"==typeof this.precision||c>this.precision)&&(this.precision=c),this.tokennumber=parseFloat(b)),a},isConst:function(){var a;for(var b in this.consts){var c=b.length;if(a=this.expression.substr(this.pos,c),b===a)return this.tokennumber=this.consts[b],this.pos+=c,!0}return!1},isOperator:function(){var a=this.expression.charAt(this.pos);if("+"===a)this.tokenprio=0,this.tokenindex="+";else if("-"===a)this.tokenprio=0,this.tokenindex="-";else if("|"===a){if("|"!==this.expression.charAt(this.pos+1))return!1;this.pos++,this.tokenprio=0,this.tokenindex="||"}else if("*"===a){if("{"===this.expression.charAt(this.pos+1))return!1;this.tokenprio=1,this.tokenindex="*"}else if("/"===a&&2!=this.mode&&this.pos>0)this.tokenprio=2,this.tokenindex="/";else if("%"===a)this.tokenprio=2,this.tokenindex="%";else if("^"===a)this.tokenprio=3,this.tokenindex="^";else if("="===a||"!"===a)if("="===this.expression.charAt(this.pos+1)){if("="===a)this.tokenindex="==";else{if("!"!==a)return!1;this.tokenindex="!="}this.pos++,this.tokenprio=6}else if("!"===a)this.tokenprio=7,this.tokenindex="!";else{if("="!==a)return!1;this.tokenindex="="}else if("<"===a)"="===this.expression.charAt(this.pos+1)?(this.tokenindex="<=",this.pos++):this.tokenindex="<",this.tokenprio=4;else if(">"===a)"="===this.expression.charAt(this.pos+1)?(this.tokenindex=">=",this.pos++):this.tokenindex=">",this.tokenprio=4;else{if("."!==a&&"["!==a)return!1;this.tokenprio=10,this.tokenindex="."}return this.pos++,!0},isRightBracket:function(){var a=this.expression.charCodeAt(this.pos);return 93===a?(this.pos++,this.tmpprio-=20,!0):!1},isSign:function(){var a=this.expression.charCodeAt(this.pos-1);return 45===a||43===a?!0:!1},isAssign:function(){var a=this.expression.charCodeAt(this.pos-1);if(61===a){var b=this.expression.charAt(this.pos-2);return"!"===b||">"===b||"<"===b||"="===b?!1:(b=this.expression.charAt(this.pos),">"===b||"<"===b||"="===b?!1:!0)}return!1},isPositiveSign:function(){var a=this.expression.charCodeAt(this.pos-1);return 43===a?!0:!1},isNegativeSign:function(){var a=this.expression.charCodeAt(this.pos-1);return 45===a?!0:!1},isLeftParenth:function(){var a=this.expression.charCodeAt(this.pos);return 40===a?(this.pos++,this.tmpprio+=10,!0):!1},isRightParenth:function(){var a=this.expression.charCodeAt(this.pos);return 41===a?(this.pos++,this.tmpprio-=10,!0):!1},isLeftCurly:function(){var a=this.expression.charCodeAt(this.pos);return 123===a?(this.pos++,this.tmpprio+=10,!0):!1},isRightCurly:function(){var a=this.expression.charCodeAt(this.pos);return 125===a?(this.pos++,this.tmpprio-=10,!0):!1},isComma:function(){var a=this.expression.charCodeAt(this.pos);return 44===a?(this.pos++,this.tokenprio=-1,this.tokenindex=",",!0):!1},isWhite:function(){var a=this.expression.charCodeAt(this.pos);return 32===a||9===a||10===a||13===a?(this.pos++,!0):!1},isLeftVarBrk:function(a){var b=this.pos,c=this.expression.charAt(b);if("$"===c||"@"===c||"*"===c||"#"===c){b++;var d=this.expression.charAt(b);if("{"===d){b++,this.tmpprio+=10,this.tokenprio=-4;var e=this.mode;return a.push(e),"$"===c?this.mode=1:"@"===c?this.mode=2:"*"===c?this.mode=3:"#"===c&&(this.mode=4),this.tokenindex="{",this.pos=b,!0}}return!1},isRightVarBrk:function(){var a=this.expression.charCodeAt(this.pos);return 125===a?(this.pos++,this.tmpprio-=10,!0):!1},isOpX:function(a,b){if(a.str.length>0){if(a.str in new Object)return!1;if(a.str in b)return this.tokenindex=a.str,this.tokenprio=5,this.pos=a.pos,!0}return!1},isLiteralValue:function(a){if("string"==typeof a.str){var b=a.str.charAt(0),c=a.str.charAt(a.str.length-1);if("'"==b&&"'"==c||'"'==b&&'"'==c)return this.tokennumber=a.str.substring(1,a.str.length-1),this.pos=a.pos,!0}return!1},isVar:function(a){return a.str.length>0?(this.tokenindex=a.str,this.tokenprio=4,this.pos=a.pos,!0):!1},isComment:function(){var a=this.expression.charCodeAt(this.pos-1);return 47===a&&42===this.expression.charCodeAt(this.pos)?(this.pos=this.expression.indexOf("*/",this.pos)+2,1===this.pos&&(this.pos=this.expression.length),!0):!1}},D}(),function(){var a,b=["abbr","accept","accept-charset","accesskey","action","align","alt","archive","audio","autocomplete","axis","background","bgcolor","border","cellpadding","cellspacing","challenge","charset","cite","class","classid","codebase","codetype","cols","colspan","compact","content","contenteditable","contextmenu","data","datetime","dir","draggable","dropzone","enctype","for","form","formaction","formenctype","formmethod","formtarget","frame","frameborder","headers","height","high","href","hreflang","hspace","http-equiv","icon","id","keytype","kind","label","lang","list","longdesc","low","manifest","marginheight","marginwidth","max","maxlength","media","method","min","name","optimum","pattern","placeholder","poster","preload","radiogroup","rel","rev","rows","rowspan","rules","sandbox","scheme","scope","scrolling","size","sizes","span","spellcheck","src","srclang","standby","start","step","style","summary","tabindex","target","title","type","usemap","value","valuetype","vspace","width","wrap","xmlbase","xmllang","xmlspace"],c=["async","autofocus","autoplay","checked","controls","declare","default","defer","disabled","formnovalidate","hidden","ismap","loop","multiple","novalidate","nowrap","open","pubdate","readonly","required","reversed","scoped","seamless","selected"],d=["onabort","onafterprint","onbeforeprint","onbeforeunload","onblur","oncanplay","oncanplaythrough","onchange","onclick","oncontextmenu","ondblclick","ondrag","ondragend","ondragenter","ondragleave","ondragover","ondragstart","ondrop","ondurationchanged","onemptied","onended","onerror","onfocus","onformchange","onforminput","onhashchange","oninput","oninvalid","onkeydown","onkeypress","onkeyup","onload","onloadeddata","onloadedmetadata","onloadstart","onmessage","onmousedown","onmousemove","onmouseout","onmouseover","onmouseup","onmousewheel","onoffline","ononline","onpause","onplay","onplaying","onpopstate","onprogress","onratechange","onreadystatechange","onredo","onreset","onresize","onscroll","onseeked","onseeking","onselect","onshow","onstalled","onstorage","onsubmit","onsuspend","ontimeupdate","onundo","onunload","onvolumechange","onwaiting"],e=/^[a-zA-Z0-9\[\]\.\-_]*$/,f=/^[+\-]?[0-9]*?[.]?[0-9]*?$/,g=/[\$\*#]{1}\{(?:!?[^}]*)\}/,h=/[\$\*#@]{1}\{(!?[^}]*)\}/,i=/\[\[(.*)\]\]/,j=/\/\*\[\[(.*)\]\]\*\//,k=/\s*(?:['][^']*['])*(?:["][^"]*["])*(?:[\(][^\(\)]*[\)])*(?:[\{][^\{\}]*[\}])*(?:[\[][^\[\]]*[\]])*((?:[;,\(\)\[\]:\{\}](?=(?:\s*\/\/.*?(?:\n|$)))(?:\s*\/\/.*?(?:\n|$)))|(?:\s*\/\/.*?(?:\n|$))|(?:[;,\(\)\[\]:\{\}](?=(?:\s*(?:\n|$)))(?:\s*(?:\n|$)))|(?:\s*(?:\n|$)))/;thymol.getThAttribute=function(a,b){var c=thymol.ThUtils.unParenthesise(a);return c=thymol.doExpression(c,b),"[object Array]"===Object.prototype.toString.call(c)&&1===c.length&&(c=c[0]),c instanceof thymol.ThParam&&(c=c.value),c},thymol.doExpression=function(a,b){var c,d,g,h=thymol.ThUtils.unParenthesise(a);return c=null,d=thymol.ThUtils.unQuote(h),d!=h?h=thymol.preProcess(d,b):e.test(h)?(g=thymol.booleanAndNullTokens[h],"undefined"!=typeof g?h=g:h.match(f)?h=thymol.ThUtils.getToPrecision(h,thymol.ThUtils.getDecimalDigits(h)):(c=thymol.getExpression(h,b),void 0!==c&&null!==c&&c==c&&(h=c))):(c=thymol.getExpression(h,b),h=null!==c&&c==c?c:null),h},thymol.processText=function(a,b,c){var d,e,f,g,h,i=thymol.getThAttribute(b.value,a),j=!1;if(null==i){if(!thymol.allowNullText)return thymol.debug&&thymol.thWindow.alert("thymol.processText cannot process: "+b.name+'="'+b.value+'"\n'+a.innerHTML),j;i=""}else if(i instanceof thymol.ThParam||i instanceof thymol.ThObject)i.value&&(i=i.value);else if(i instanceof thymol.ThClass&&i.abort)return a.removeAttribute(b.name),!0;try{for(;null!=a.firstChild&&(a.removeChild(a.firstChild),j=!0,null!=a.firstChild););if("text"==c.suffix){if("[object Array]"===Object.prototype.toString.call(i)){for(d="[",f=0,g=i.length,h=i.length-1;g>f;f++)d+=i[f].toString(),h>f&&(d+=", ");d+="]"}else d=i.toString();d=thymol.ThUtils.unescape(d),e=a.ownerDocument.createTextNode(d),a.appendChild(e),j=!0}"utext"==c.suffix&&(a.innerHTML=i),a.removeAttribute(b.name)}catch(k){thymol.debug&&thymol.thWindow.alert("text replace error")}return j},thymol.processSpecAttrMod=function(a,b,c){var d=thymol.getThAttribute(b.value,a);d&&d instanceof thymol.ThClass&&d.abort||a.setAttribute(c.suffix,d),a.removeAttribute(b.name)},thymol.processAttr=function(a,b,d){var e,f,g,h,i,j,k,l=b.value.trim(),m=null;if(l)do{if(e=thymol.ThParser.parse(l,!0,!1),g=e.tokens.shift(),3!==g.type_)break;m=g.index_,m&&(h=l.indexOf("="),h>=0&&(i=e.position-1,e.position===l.length&&(i=l.position),f=l.substring(h+1,i).trim(),c.indexOf(m)>=0?thymol.doFixedValBoolAttr(f,a,m):(j=thymol.getThAttribute(f,a),k=typeof j,("attrappend"==d.suffix||"attrprepend"==d.suffix)&&null!==j&&("number"===k||"string"===k&&j.length>0)&&(existing=a.getAttribute(m),existing&&("attrappend"==d.suffix?j=existing+j:"attrprepend"==d.suffix&&(j+=existing))),null!==j&&("number"===k||"string"===k&&j.length>0)&&a.setAttribute(m,j)))),l=l.substring(e.position)}while(l.length>0);a.removeAttribute(b.name)},thymol.processCSSAttr=function(a,b,c){var d,e,f,g,h,i,j,k=b.value.split(",");for(d=0,e=k.length;e>d;d++)f=k[d],g="classappend"==c.suffix?"class":"style",g&&f&&(h=thymol.getThAttribute(f,a),i=typeof h,null!==h&&("number"===i||"string"===i&&h.length>0)&&(j=a.getAttribute(g),j&&(h=j+" "+h)),null!==h&&("number"===i||"string"===i&&h.length>0)&&a.setAttribute(g,h));a.removeAttribute(b.name)},thymol.processFixedValBoolAttr=function(a,b,c){var d=thymol.doFixedValBoolAttr(b.value,a,c.suffix);null!=d?a.removeAttribute(b.name):thymol.debug&&thymol.thWindow.alert("thymol.processFixedValBoolAttr cannot process: "+b.name+'="'+b.value+'"\n'+a.innerHTML)},thymol.doFixedValBoolAttr=function(a,b,c){var d=thymol.getBoolean(a,b);return d&&b.setAttribute(c,c),d},thymol.processPairedAttr=function(a,b,c){var d=thymol.getThAttribute(b.value,a);""!=d?("alt-title"===c.suffix&&(a.setAttribute("alt",d),a.setAttribute("title",d)),"lang-xmllang"===c.suffix&&(a.setAttribute("lang",d),a.setAttribute("xml:lang",d)),a.removeAttribute(b.name)):thymol.debug&&thymol.thWindow.alert("thymol.processPairedAttr cannot process: "+b.name+'="'+b.value+'"\n'+a.innerHTML)},thymol.processConditional=function(a,b,c){var d=!1;return b.value&&(d=thymol.doIfOrUnless(a,b.value,"if"===c.suffix)),a.removeAttribute(b.name),d},thymol.doIfOrUnless=function(a,b,c){var d,e=!1;if(b)if(d=thymol.getBoolean(b,a),e=!0,d){if(!c)return a.parentNode.removeChild(a),!0}else if(c)return a.parentNode.removeChild(a),!0;return!e&&thymol.debug&&thymol.thWindow.alert("thymol.processConditional cannot process conditional: "+b+"\n"+a.innerHTML),!1},thymol.processEach=function(a,b,c){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r=!1,s=b.value.trim();if(d=s.indexOf(":"),d>0&&(e=s.substring(0,d),e&&(e=e.trim(),f=e.split(","),e=f[0].trim(),g=f.length>1?f[1].trim():e+"Stat",h=s.substr(d+1))))if(h=h.trim(),h=thymol.getExpression(h,a),h instanceof thymol.ThSet&&(h=h.toArray()),i=a.parentNode,h&&h instanceof Object&&h.length>0)for(j=a,l=h.length,a.removeAttribute(b.name),k=0;l>k;k++)m=h[k],n=new Object,n.current=m,n.size=h.length,n.index=k,o=k+1,n.count=o,n.first=0==k?!0:!1,n.last=k==h.length-1?!0:!1,k%2?(n.odd=!0,n.even=!1):(n.odd=!1,n.even=!0),j.thLocalVars||(j.thLocalVars={}),j.thLocalVars[e]=m,j.thLocalVars[g]=n,o<h.length&&(p=a.cloneNode(!0),q=null!=j.nextElementSibling?i.insertBefore(p,j.nextElementSibling):i.appendChild(p),j=q,r=!0);else null!==i&&(a.thLocalVars||(a.thLocalVars={}),a.thLocalVars[e]||(a.thLocalVars[e]=new Object),a.thLocalVars[g]||(a.thLocalVars[g]=new Object),i.removeChild(a),r=!0);return r},thymol.processObject=function(a,b){var c,d=b.value.trim();d&&(c=thymol.getExpression(d,a),c&&(a.thObjectVar=c)),a.removeAttribute(b.name)},thymol.processInline=function(a,b,c){var d=thymol.getThAttribute(b.value,a);"text"==d?thymol.doInlineText(a):"javascript"==d||"dart"==d?thymol.doInlineJavascript(a):thymol.debug&&thymol.thWindow.alert('thymol.processInline cannot process scripting mode: "'+d+'" - it isn\'t supported by version "'+thymol.thVersion+'"\n'),a.removeAttribute(b.name)},thymol.doInlineText=function(a){var b,c,d,e,f,g,h;for(d=0,e=a.childNodes.length;e>d;d++)do b=!1,1==a.childNodes[d].nodeType?thymol.doInlineText(a.childNodes[d]):3==a.childNodes[d].nodeType&&(c=a.childNodes[d].nodeValue,c&&(f=i.exec(c),f&&(g="",f.length>1&&(g="[["+f[1]+"]]"),f.length>1&&(h=thymol.getThAttribute(f[1],a),h=c.replace(g,h),a.childNodes[d].nodeValue=h,b=!0),f=null)));while(b)},thymol.doInlineJavascript=function(a){var b,c,d,e,f,g,h,i,l,m,n,o;for(e=0,f=a.childNodes.length;f>e;e++)do d=null,b=!1,c=a.childNodes[e].nodeValue,c&&(g=j.exec(c),g&&(l=g.index,m="",g.length>1&&(m="/*[["+g[1]+"]]*/"),l+=m.length,i=c.substring(l),h=k.exec(i),h&&h.length>1&&(n=i.indexOf(h[1]),d=i.substring(n),c=c.substring(0,l),c+=d),g.length>1&&(o=thymol.getExpression(g[1],a),o instanceof thymol.ThObject&&(o=o.toNonThObject()),thymol.ThUtils.isLiteral(o)||(o=thymol.getStringView(o)),o=c.replace(m,o),a.childNodes[e].nodeValue=o,b=!0),g=null,h=null));while(b)},thymol.getStringView=function(a){var b,c="";return"string"==typeof a?c=c+"'"+a+"'":"number"==typeof a||"boolean"==typeof a?c+=a:"object"==typeof a&&a instanceof Object&&(b=Object.prototype.toString.call(a),"[object Array]"==b?c=thymol.getStringViewArray(a):"[object Object]"==b&&(c=thymol.getStringViewObject(a))),c},thymol.getStringViewArray=function(a){var b,c,d="[";for(b=0,c=a.length;c>b;b++)d+=thymol.getStringView(a[b]),b<a.length-1&&(d+=",");return d+="]"},thymol.getStringViewObject=function(a){var b="{",c=null;for(c in a)c&&("{"!=b&&(b+=","),b=b+thymol.getStringView(c)+":",b+=thymol.getStringView(a[c]));return b+="}"},thymol.processRemove=function(a,b){var c,d,e,f=!1,g=a.thLocalVars,h=a.thLocalVars;return g||(g={}),g.tag||(g.tag="tag"),g.body||(g.body="body"),g.none||(g.none="none"),g.all||(g.all="all"),g["all-but-first"]||(g["all-but-first"]="all-but-first"),a.thLocalVars=g,c=thymol.getThAttribute(b.value,a),a.thLocalVars=h,a.removeAttribute(b.name),"all"==c?null!=a.parentNode&&(a.parentNode.removeChild(a),f=!0):"body"==c?(a.innerHTML="",f=!0):"tag"==c?(thymol.ThUtils.removeTag(a),f=!0):"all-but-first"==c&&(d=a.childNodes,e=!0,$(d).each(function(){1==this.nodeType&&(e||(a.removeChild(this),f=!0),e=!1)})),f},thymol.processSwitch=function(b,c){var d,e,f,h,i,j=thymol.ThUtils.unParenthesise(c.value),k=!1,l=!1;return j=thymol.getThAttribute(j,b),"string"==typeof j&&(d=j.match(g),d&&(j=d[1])),j=thymol.ThUtils.unQuote(j),e=$(a.escpName,b),e.each(function(){f=this,h=!0,$(f.attributes).each(function(){i=this,(a.name==i.name||a.synonym==i.name)&&(l||(l=thymol.processCase(b,i,j),l&&(h=!1)),f.removeAttribute(i.name))}),h&&(b.removeChild(f),k=!0)}),k},thymol.processCase=function(a,b,c){var d=thymol.substitute(b.value,a);return d=thymol.ThUtils.unQuote(d),"*"==d||c&&c==d?!0:!1},thymol.processWith=function(a,b){thymol.getWith(a,b.value),a.removeAttribute(b.name)},thymol.processAssert=function(a,b){var c,d,e,f,g,h,i=b.value.trim(),j=!0,k="";if(i)for(c=i.split(","),d=0,e=c.length;e>d;d++){if(k=c[d],f=thymol.ThUtils.unParenthesise(k),null==f){j=!1;break}if(g=thymol.getExpression(f,a),!g){j=!1;break}if(h=thymol.getBoolean(g,a),!h){j=!1;break}}j||(i=i!=k?" list is: "+i:"",""!=k&&(k=' false term is: "'+k+'"'),thymol.debug&&thymol.thWindow.alert("thymol.processAssert assertion failure -"+i+k+"\n")),a.removeAttribute(b.name)},thymol.processFragment=function(a,b,c){a.removeAttribute(b.name)},thymol.getBoolean=function(a,b){if(null==a)return!1;if("boolean"==typeof a)return a;if("number"==typeof a)return 0!=a;var c,d,e,f=thymol.ThUtils.unParenthesise(a),g=!1;return"!"==f.charAt(0)&&(g=!0,f=f.substring(1,f.length),f=thymol.ThUtils.unParenthesise(f)),c=thymol.getThAttribute(f,b),null==c&&(d=f.match(h),d&&"!"==d[1].charAt(0)&&(g=!g)),e=thymol.getBooleanValue(c),g&&(e=!e),e},thymol.appendToAttrList=function(a,b,c){var d,e=c.length,f=null;for(d=0;e>d;d++)f=new thymol.ThAttr(c[d],a,b,thymol.thThymeleafPrefixList,thymol.prefix);d=f},thymol.setupAttrList=function(){a=new thymol.ThAttr("case",null,275,thymol.thThymeleafPrefixList,thymol.prefix),thymol.addDialect({prefix:thymol.prefix,attributeProcessors:[{name:"each",processor:thymol.processEach,precedence:200},{name:"switch",processor:thymol.processSwitch,precedence:250},{name:"if",processor:thymol.processConditional,precedence:300},{name:"unless",processor:thymol.processConditional,precedence:400},{name:"object",processor:thymol.processObject,precedence:500},{name:"with",processor:thymol.processWith,precedence:600},{name:"attr",processor:thymol.processAttr,precedence:700},{name:"attrprepend",processor:thymol.processAttr,precedence:800},{name:"attrappend",processor:thymol.processAttr,precedence:900},{name:"alt-title",processor:thymol.processPairedAttr,precedence:990},{name:"lang-xmllang",processor:thymol.processPairedAttr,precedence:990},{name:"inline",processor:thymol.processInline,precedence:1e3},{name:"classappend",processor:thymol.processCSSAttr,precedence:1100},{name:"styleappend",processor:thymol.processCSSAttr,precedence:1100},{name:"text",processor:thymol.processText,precedence:1300},{name:"utext",processor:thymol.processText,precedence:1400},{name:"fragment",processor:thymol.processFragment,precedence:1500},{name:"assert",processor:thymol.processAssert,precedence:1550},{name:"remove",processor:thymol.processRemove,precedence:1600}]}),thymol.appendToAttrList(thymol.processSpecAttrMod,1e3,b),thymol.appendToAttrList(thymol.processSpecAttrMod,1e3,d),thymol.appendToAttrList(thymol.processFixedValBoolAttr,1e3,c)}}(),thymol.objects.thHttpSessionObject=function(){function a(a){var b=thymol.sessionContext[a];return b}function b(a){var b=thymol.sessionContext[a];return b}function c(){var a=thymol.applicationContext;return a}function d(){var a=thymol.sessionContext;return a}function e(){var a="";return a}function f(){var a="";return a}function g(a){var b=thymol.sessionContext[a];return b}var h="#httpSession";return{thExpressionObjectName:h,getAttribute:a,getParameter:b,getServletContext:c,getSessionContext:d,getContextPath:e,getRequestName:f,getParameterValues:g}}(),thymol.objects.thHttpServletRequestObject=function(){function a(a){var b=thymol.requestContext[a][0];return b instanceof thymol.ThParam&&(b=thymol.ThUtils.unQuote(b.value)),b}function b(a){var b=thymol.requestContext[a];return b}function c(){var a="";return a}function d(){var a="";return a}function e(a){var b=thymol.requestContext[a];return b}function f(a){return thymol.objects.thHttpSessionObject}var g="#httpServletRequest";return{thExpressionObjectName:g,getAttribute:a,getParameter:b,getContextPath:c,getRequestName:d,getParameterValues:e,getSession:f}}(),thymol.objects.thAggregatesObject=function(){function a(a){return c(a,!1,"sum")}function b(a){return c(a,!0,"avg")}function c(a,b,c){if(null!==a){var d,e=0,f=typeof a,g=Object.prototype.toString.call(a);if("Array"===f||"[object Array]"===g){d=a.length;for(var h=0;d>h;h++){if(null===a[h])throw new thymol.ThError("#aggregates."+c+" Cannot aggregate on object containing nulls");e+=a[h]}}else{d=0;for(var i in a){var j=a[i],k=!1;if(null===j)throw new thymol.ThError("#aggregates."+c+" Cannot aggregate on object containing nulls");k=a instanceof thymol.ThSet?a.isContent(i):a.hasOwnProperty(i)&&"function"!=typeof j,k&&(e+=j,d++)}}if(b){if(0==d)throw new thymol.ThError("#aggregates."+c+" Cannot get size of object");e/=d}return e}throw new thymol.ThError("#aggregates."+c+" Cannot aggregate on null")}var d="#aggregates";return{thExpressionObjectName:d,sum:a,avg:b}}(),thymol.objects.thArraysObject=function(){function a(a){if(null!==a)return e(null,a);throw new thymol.ThError("#arrays.toArray Cannot convert null to array")}function b(a){if(null!==a)return e("string",a);throw new thymol.ThError("#arrays.toStringArray Cannot convert null to array")}function c(a){if(null!==a)return e("number",a);throw new thymol.ThError("#arrays.toNumberArray Cannot convert null to array")}function d(a){if(null!==a)return e("boolean",a);throw new thymol.ThError("#arrays.toBooleanArray Cannot convert null to array")}function e(a,b){if(b instanceof Array){if(null===a||"undefined"===a)return b;var c=new Array;try{for(var d=0,e=b.length;e>d;d++)null!==b[d]&&c.push("string"===a?new String(b[d]).valueOf():"number"===a?new Number(b[d]).valueOf():"boolean"===a?new Boolean(b[d]).valueOf():b[d])}catch(f){throw new IllegalArgumentException('#arrays.toArray Cannot convert object of class "'+targetComponentClass.getName()+'[]" to an array of '+a.getClass().getSimpleName())}return c}if(b instanceof Object){var c=new Array;try{for(var g in b){var h=b[g],i=!1;null!==h&&(i=b instanceof thymol.ThSet?b.isContent(g):b.hasOwnProperty(g)&&"function"!=typeof h),i&&c.push("string"===a?new String(h).valueOf():"number"===a?new Number(h).valueOf():"boolean"===a?new Boolean(h).valueOf():h)}}catch(f){throw new IllegalArgumentException('#arrays.toArray Cannot convert object of class "'+targetComponentClass.getName()+'[]" to an array of '+a.getClass().getSimpleName())}return c}throw new thymol.ThError('#arrays.toArray Cannot convert object of type "'+typeof b+'" to an array'+(null==a?"":" of "+a))}function f(a){if(null!==a)return a.length;throw new thymol.ThError("#arrays.length Cannot get array length of null")}function g(a){return null===a||a.length<=0}function h(a,b){if(null!==a){for(var c=0,d=a.length;d>c;c++)if(null===a[c]){if(null===b)return!0}else if(null!==b&&a[c]===b)return!0;return!1}throw new thymol.ThError("#arrays.contains Cannot execute array contains: target is null")}function i(a,b){if(null!==a){if(null!==b){var c;if(b instanceof Array)c=[].concat(b);else if(b instanceof thymol.ThSet)c=b.toArray();else{c=[];for(var d in b)b.hasOwnProperty(d)&&"function"!=typeof b[d]&&c.push(b[d])}for(var e=0,f=a.length;f>e;e++)for(var g=0,h=c.length;h>g;g++)a[e]===c[g]&&c.splice(g,1);return 0===c.length}throw new thymol.ThError("#arrays.containsAll Cannot execute array containsAll: elements is null")}throw new thymol.ThError("#arrays.containsAll Cannot execute array containsAll: target is null")}var j="#arrays";return{thExpressionObjectName:j,toArray:a,toStringArray:b,toIntegerArray:c,toLongArray:c,toDoubleArray:c,toFloatArray:c,toBooleanArray:d,length:f,isEmpty:g,contains:h,containsAll:i}}(),thymol.objects.thBoolsObject=function(){function a(a){var b,c=!0;return null==a||"undefined"==(b=typeof a)?c=!1:"boolean"===b?c=a:"number"===b?c=0!=a:"string"===b&&(1===a.length?c=0!=a.charCodeAt(0):thymol.ThUtils.testLiteralFalse(a)&&(c=!1)),c}function b(b){if(null!==b){for(var c=[],d=0,e=b.length;e>d;d++)c.push(a(b[d]));return c}throw new thymol.ThError("#bools.arrayIsTrue Target cannot be null")}function c(b){if(null!==b){var c=new thymol.ThSet;for(var d in b)b.isContent(d)&&c.add(a(b[d]));return c}throw new thymol.ThError("#bools.setIsTrue Target cannot be null")}function d(b){return!a(b)}function e(b){if(null!==b){for(var c=[],d=0,e=b.length;e>d;d++)c.push(!a(b[d]));return c}throw new thymol.ThError("#bools.arrayIsFalse Target cannot be null")}function f(b){if(null!==b){var c=new thymol.ThSet;for(var d in b)b.isContent(d)&&c.add(!a(b[d]));return c}throw new thymol.ThError("#bools.setIsFalse Target cannot be null")}function g(b){if(null!==b){for(var c=0,d=b.length;d>c;c++)if(!a(b[c]))return!1;return!0}throw new thymol.ThError("#bools.arrayAnd Target cannot be null")}function h(b){if(null!==b){for(var c in b)if(b.isContent(c)&&!a(b[c]))return!1;return!0}throw new thymol.ThError("#bools.setAnd Target cannot be null")}function i(b){if(null!==b){for(var c=0,d=b.length;d>c;c++)if(a(b[c]))return!0;return!1}throw new thymol.ThError("#bools.arrayOr Target cannot be null")}function j(b){if(null!==b){for(var c in b)if(b.isContent(c)&&a(b[c]))return!0;return!1}throw new thymol.ThError("#bools.setOr Target cannot be null")}var k="#bools";return{thExpressionObjectName:k,isTrue:a,arrayIsTrue:b,listIsTrue:b,setIsTrue:c,isFalse:d,arrayIsFalse:e,listIsFalse:e,setIsFalse:f,arrayAnd:g,listAnd:g,setAnd:h,arrayOr:i,listOr:i,setOr:j}}(),thymol.objects.thDatesObject=function(){function a(){return null!==arguments?arguments.length>6?b(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6]):arguments.length>5?b(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],0):arguments.length>4?b(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],0,0):b(arguments[0],arguments[1],arguments[2],0,0,0,0):void 0}function b(a,b,c,d,e,f,g){var h=new Date;return h.setMilliseconds(g),h.setSeconds(f),h.setMinutes(e),h.setHours(d),h.setDate(c),h.setMonth(b-1),h.setFullYear(a),h}function c(a){var b=a.getMonth()+1,c=a.getFullYear(),d=a.getDate(),e=Math.floor((14-b)/12),f=c+4800-e,g=b+12*e-3,h=d+Math.floor((153*g+2)/5)+365*f+Math.floor(f/4);2331254>h?h-=32083:h=h-Math.floor(f/100)+Math.floor(f/400)-32045;var i=(h+1)%7;return i}function d(){return new Date}function e(){var a=new Date;return a.setHours(0,0,0,0),a}function f(a,b,c){var d,e="";return null===arguments?d=new Date:(arguments.length>1&&(e=b),d=a),g(d,e,c)}function g(a,b,c){var d="";arguments.length>1&&(d=b);var e=X(a,d,!1);return e}function h(a,b){var c="";arguments.length>1&&(c=b);for(var d=[],e=0,f=a.length;f>e;e++)d.push(X(a[e],c,!1));return d}function i(a,b){var c="";arguments.length>1&&(c=b);var d=new thymol.ThSet;for(var e in a)a.isContent(e)&&d.add(X(a[e],c,!1));return d}function j(a){return a.getDate()}function k(a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(a[c].getDate());return b}function l(a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(a[c].getDate());return b}function m(a){return a.getMonth()+1}function n(a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(a[c].getMonth()+1);return b}function o(a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(a[c].getMonth()+1);return b}function p(a){return X.i18n.monthNames[a.getMonth()+12]}function q(a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(X.i18n.monthNames[a[c].getMonth()+12]);return b}function r(a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(X.i18n.monthNames[a[c].getMonth()+12]);return b}function s(a){return X.i18n.monthNames[a.getMonth()]}function t(a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(X.i18n.monthNames[a[c].getMonth()]);return b}function u(a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(X.i18n.monthNames[a[c].getMonth()]);return b}function v(a){return a.getFullYear()}function w(a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(a[c].getFullYear());return b}function x(a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(a[c].getFullYear());return b}function y(a){return c(a)+1}function z(a){for(var b=[],d=0,e=a.length;e>d;d++)b.push(c(a[d])+1);return b}function A(a){var b=new thymol.ThSet;for(var d in a)a.isContent(d)&&b.add(c(a[d])+1);return b}function B(a){return X.i18n.dayNames[c(a)+7]}function C(a){for(var b=[],d=0,e=a.length;e>d;d++)b.push(X.i18n.dayNames[c(a[d])+7]);return b}function D(a){var b=new thymol.ThSet;for(var d in a)a.isContent(d)&&b.add(X.i18n.dayNames[c(a[d])+7]);return b}function E(a){return X.i18n.dayNames[c(a)]}function F(a){for(var b=[],d=0,e=a.length;e>d;d++)b.push(X.i18n.dayNames[c(a[d])]);return b}function G(a){var b=new thymol.ThSet;for(var d in a)a.isContent(d)&&b.add(X.i18n.dayNames[c(a[d])]);return b}function H(a){return a.getHours()}function I(a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(a[c].getHours());return b}function J(a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(a[c].getHours());return b}function K(a){return a.getMinutes()}function L(a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(a[c].getMinutes());return b}function M(a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(a[c].getMinutes());return b}function N(a){return a.getSeconds()}function O(a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(a[c].getSeconds());return b}function P(a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(a[c].getSeconds());return b}function Q(a){return a.getMilliseconds()}function R(a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(a[c].getMilliseconds());return b}function S(a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(a[c].getMilliseconds());return b}function T(a){var b=String(a),c=b;if(c=(c.match(V)||[""]).pop(),""!==c){c=c.replace(W,"");var d=b.match(/[\(]((?:[GL]M|BS)T[^\)]*?)[\)]/);d&&(c=a.getFullYear()>1916||1916===a.getFullYear()&&a.getMonth()>4||1916===a.getFullYear()&&4===a.getMonth()&&a.getDate()>20?c.replace(/GMT\+\d{1,4}/,"BST"):c.replace(/GMT\+\d{1,4}/,"GMT"))}return c}var U="#dates",V=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,W=/[^-+\dA-Z]/g,X=function(){var a=/d{1,4}|M{1,4}|yy(?:yy)?|([HhmsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,b=function(a,b){for(var c=String(a),d=b||2;c.length<d;)c="0"+c;return c};return function(d,e,f){var g=X,h=e,i=d,j=f;if(1!=arguments.length||"[object String]"!=Object.prototype.toString.call(i)||/\d/.test(i)||(h=i,i=void 0),i=i?new Date(i):new Date,isNaN(i))throw SyntaxError("invalid date");h=String(g.masks[h]||h||g.masks["default"]),"UTC:"==h.slice(0,4)&&(h=h.slice(4),j=!0);var k=j?"getUTC":"get",l=i[k+"Date"](),m=c(i),n=i[k+"Month"](),o=i[k+"FullYear"](),p=i[k+"Hours"](),q=i[k+"Minutes"](),r=i[k+"Seconds"](),s=i[k+"Milliseconds"](),t=j?0:i.getTimezoneOffset(),u={d:l,dd:b(l),ddd:g.i18n.dayNames[m],dddd:g.i18n.dayNames[m+7],M:n+1,MM:b(n+1),MMM:g.i18n.monthNames[n],MMMM:g.i18n.monthNames[n+12],yy:String(o).slice(2),yyyy:o,h:p%12||12,hh:b(p%12||12),H:p,HH:b(p),m:q,mm:b(q),s:r,ss:b(r),l:b(s,3),L:b(s>99?Math.round(s/10):s),t:12>p?"a":"p",tt:12>p?"am":"pm",T:12>p?"A":"P",TT:12>p?"AM":"PM",Z:j?"UTC":T(i),o:(t>0?"-":"+")+b(100*Math.floor(Math.abs(t)/60)+Math.abs(t)%60,4),S:["th","st","nd","rd"][l%10>3?0:(l%100-l%10!=10)*l%10]};return h.replace(a,function(a){return a in u?u[a]:a.slice(1,a.length-1)})}}();return X.masks={"default":"dd MMMM yyyy HH:mm:ss Z",shortDate:"M/d/yy",mediumDate:"MMM d, yyyy",longDate:"d MMMM yyyy",fullDate:"dddd, MMMM d, yyyy",shortTime:"h:mm TT",mediumTime:"h:mm:ss TT",longTime:"h:mm:ss TT Z",isoDate:"yyyy-MM-dd",isoTime:"HH:mm:ss",isoDateTime:"yyyy-MM-dd'T'HH:mm:ss",isoUtcDateTime:"UTC:yyyy-MM-dd'T'HH:mm:ss'Z'"},X.i18n={dayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"]},Date.prototype.format=function(a,b){return X(this,a,b)},{thExpressionObjectName:U,create:a,createNow:d,createNowForTimeZone:d,createToday:e,createTodayForTimeZone:e,format:f,dateFormat:X,arrayFormat:h,listFormat:h,setFormat:i,day:j,arrayDay:k,listDay:k,setDay:l,month:m,arrayMonth:n,listMonth:n,setMonth:o,monthName:p,arrayMonthName:q,listMonthName:q,setMonthName:r,monthNameShort:s,arrayMonthNameShort:t,listMonthNameShort:t,setMonthNameShort:u,year:v,arrayYear:w,listYear:w,setYear:x,dayOfWeek:y,arrayDayOfWeek:z,listDayOfWeek:z,setDayOfWeek:A,dayOfWeekName:B,arrayDayOfWeekName:C,listDayOfWeekName:C,setDayOfWeekName:D,dayOfWeekNameShort:E,arrayDayOfWeekNameShort:F,listDayOfWeekNameShort:F,setDayOfWeekNameShort:G,hour:H,arrayHour:I,listHour:I,setHour:J,minute:K,arrayMinute:L,listMinute:L,setMinute:M,second:N,arraySecond:O,listSecond:O,setSecond:P,millisecond:Q,arrayMillisecond:R,listMillisecond:R,setMillisecond:S}}(),thymol.objects.thCalendarsObject=function(){var a="#calendars";return{thExpressionObjectName:a,create:thymol.objects.thDatesObject.create,createNow:thymol.objects.thDatesObject.createNow,
+createNowForTimeZone:thymol.objects.thDatesObject.createNow,createToday:thymol.objects.thDatesObject.createToday,createTodayForTimeZone:thymol.objects.thDatesObject.createToday,format:thymol.objects.thDatesObject.format,dateFormat:thymol.objects.thDatesObject.dateFormat,arrayFormat:thymol.objects.thDatesObject.arrayFormat,listFormat:thymol.objects.thDatesObject.arrayFormat,setFormat:thymol.objects.thDatesObject.setFormat,day:thymol.objects.thDatesObject.day,arrayDay:thymol.objects.thDatesObject.arrayDay,listDay:thymol.objects.thDatesObject.arrayDay,setDay:thymol.objects.thDatesObject.setDay,month:thymol.objects.thDatesObject.month,arrayMonth:thymol.objects.thDatesObject.arrayMonth,listMonth:thymol.objects.thDatesObject.arrayMonth,setMonth:thymol.objects.thDatesObject.setMonth,monthName:thymol.objects.thDatesObject.monthName,arrayMonthName:thymol.objects.thDatesObject.arrayMonthName,listMonthName:thymol.objects.thDatesObject.arrayMonthName,setMonthName:thymol.objects.thDatesObject.setMonthName,monthNameShort:thymol.objects.thDatesObject.monthNameShort,arrayMonthNameShort:thymol.objects.thDatesObject.arrayMonthNameShort,listMonthNameShort:thymol.objects.thDatesObject.arrayMonthNameShort,setMonthNameShort:thymol.objects.thDatesObject.setMonthNameShort,year:thymol.objects.thDatesObject.year,arrayYear:thymol.objects.thDatesObject.arrayYear,listYear:thymol.objects.thDatesObject.arrayYear,setYear:thymol.objects.thDatesObject.setYear,dayOfWeek:thymol.objects.thDatesObject.dayOfWeek,arrayDayOfWeek:thymol.objects.thDatesObject.arrayDayOfWeek,listDayOfWeek:thymol.objects.thDatesObject.arrayDayOfWeek,setDayOfWeek:thymol.objects.thDatesObject.setDayOfWeek,dayOfWeekName:thymol.objects.thDatesObject.dayOfWeekName,arrayDayOfWeekName:thymol.objects.thDatesObject.arrayDayOfWeekName,listDayOfWeekName:thymol.objects.thDatesObject.arrayDayOfWeekName,setDayOfWeekName:thymol.objects.thDatesObject.setDayOfWeekName,dayOfWeekNameShort:thymol.objects.thDatesObject.dayOfWeekNameShort,arrayDayOfWeekNameShort:thymol.objects.thDatesObject.arrayDayOfWeekNameShort,listDayOfWeekNameShort:thymol.objects.thDatesObject.arrayDayOfWeekNameShort,setDayOfWeekNameShort:thymol.objects.thDatesObject.setDayOfWeekNameShort,hour:thymol.objects.thDatesObject.hour,arrayHour:thymol.objects.thDatesObject.arrayHour,listHour:thymol.objects.thDatesObject.arrayHour,setHour:thymol.objects.thDatesObject.setHour,minute:thymol.objects.thDatesObject.minute,arrayMinute:thymol.objects.thDatesObject.arrayMinute,listMinute:thymol.objects.thDatesObject.arrayMinute,setMinute:thymol.objects.thDatesObject.setMinute,second:thymol.objects.thDatesObject.second,arraySecond:thymol.objects.thDatesObject.arraySecond,listSecond:thymol.objects.thDatesObject.arraySecond,setSecond:thymol.objects.thDatesObject.setSecond,millisecond:thymol.objects.thDatesObject.millisecond,arrayMillisecond:thymol.objects.thDatesObject.arrayMillisecond,listMillisecond:thymol.objects.thDatesObject.arrayMillisecond,setMillisecond:thymol.objects.thDatesObject.setMillisecond}}(),thymol.objects.thIdsObject=function(){function a(a){if(null!==a){var b=a.toString(),c=e(b),f=b+c;return c++,d(b,c),f}throw new thymol.ThError("#ids.seq ID Cannot be null")}function b(a){if(null!==a){var b=a.toString(),c=e(b);return b+c}throw new thymol.ThError("#ids.next ID Cannot be null")}function c(a){if(null!==a){var b=a.toString(),c=e(b);return b+(c-1)}throw new thymol.ThError("#ids.prev ID Cannot be null")}function d(a,b){thymol.objects.thIdsObject.thLocalVars||(thymol.objects.thIdsObject.thLocalVars=[]),thymol.objects.thIdsObject.thLocalVars.thIdCounts||(thymol.objects.thIdsObject.thLocalVars.thIdCounts=[]),thymol.objects.thIdsObject.thLocalVars.thIdCounts[a]=b}function e(a){return thymol.objects.thIdsObject.thLocalVars||(thymol.objects.thIdsObject.thLocalVars=[]),thymol.objects.thIdsObject.thLocalVars.thIdCounts||(thymol.objects.thIdsObject.thLocalVars.thIdCounts=[]),thymol.objects.thIdsObject.thLocalVars.thIdCounts[a]||(thymol.objects.thIdsObject.thLocalVars.thIdCounts[a]=1),thymol.objects.thIdsObject.thLocalVars.thIdCounts[a]}var f="#ids";return{thExpressionObjectName:f,seq:a,next:b,prev:c}}(),thymol.objects.thListsObject=function(){function a(a,b){if(null!==a){if(arguments.length>1){if(null!==b){if("function"==typeof b)return a.sort(b);throw new thymol.ThError("#lists.sort Cannot execute list sort: comparator is not a function")}throw new thymol.ThError("#lists.sort Cannot execute list sort: comparator is null")}return a.sort()}throw new thymol.ThError("#lists.sort Cannot execute list sort: list is null")}var b="#lists";return{thExpressionObjectName:b,toList:thymol.objects.thArraysObject.toArray,size:thymol.objects.thArraysObject.length,isEmpty:thymol.objects.thArraysObject.isEmpty,contains:thymol.objects.thArraysObject.contains,containsAll:thymol.objects.thArraysObject.containsAll,sort:a}}(),thymol.objects.thMapsObject=function(){function a(a){if(null!==a){if(a instanceof thymol.ThMap)return a.size();throw new thymol.ThError('#maps.size Cannot get size of non-map type "'+typeof a+'"')}throw new thymol.ThError("#maps.size Cannot get size of null")}function b(a){if(null!==a){if(a instanceof thymol.ThMap)return a.isEmpty();throw new thymol.ThError('#maps.size Cannot get isEmpty of non-map type "'+typeof a+'"')}throw new thymol.ThError("#maps.size Cannot get isEmpty of null")}function c(a,b){if(null!==a){if(a instanceof thymol.ThMap)return a.containsKey(b);throw new thymol.ThError('#maps.size Cannot get containsKey of non-map type "'+typeof a+'"')}throw new thymol.ThError("#maps.containsKey Cannot execute map containsKey: target is null")}function d(a,b){if(null!==a){if(a instanceof thymol.ThMap)return a.containsValue(b);throw new thymol.ThError('#maps.size Cannot get containsValue of non-map type "'+typeof a+'"')}throw new thymol.ThError("#maps.containsKey Cannot execute map containsValue: target is null")}function e(a,b){if(null!==a){if(a instanceof thymol.ThMap){var c=Object.prototype.toString.call(b);if(b instanceof thymol.ThSet||b instanceof Array||"[object Array]"===c)return a.containsAll(b);throw new thymol.ThError('#maps.size Cannot get containsAllKeys with non-collection type "'+c+'"')}throw new thymol.ThError('#maps.size Cannot get containsAllKeys of non-map type "'+typeof a+'"')}throw new thymol.ThError("#maps.containsKey Cannot execute map containsAllKeys: target is null")}function f(a,b){if(null!==a){if(a instanceof thymol.ThMap){var c=Object.prototype.toString.call(b);if(b instanceof thymol.ThSet||b instanceof Array||"[object Array]"===c){var d=b;b instanceof thymol.ThSet&&(d=b.toArray());for(var e=0,f=d.length;f>e;e++){var g=!1;for(var h in a)if(a.hasOwnProperty(h)){var i=a[h];if(i===d[e]){g=!0;break}}if(!g)return!1}return!0}throw new thymol.ThError('#maps.size Cannot get containsAllValues with non-collection type "'+c+'"')}throw new thymol.ThError('#maps.size Cannot get containsAllValues of non-map type "'+typeof a+'"')}throw new thymol.ThError("#maps.containsKey Cannot execute map containsAllValues: target is null")}var g="#maps";return{thExpressionObjectName:g,size:a,isEmpty:b,containsKey:c,containsValue:d,containsAllKeys:e,containsAllValues:f}}(),thymol.objects.thMessagesObject=function(){function a(){if(null!==arguments){if(arguments.length>0)return b(arguments[0],Array.prototype.slice.call(arguments,1));throw new thymol.ThError("#messages.msg Invoked with no arguments!")}throw new thymol.ThError("#messages.msg Target cannot be null")}function b(a,b){if(null!==a)return thymol.getMessage(a,b,!0);throw new thymol.ThError("#messages.msgWithParams Target cannot be null")}function c(){if(null!==arguments){if(arguments.length>0)return d(arguments[0],Array.prototype.slice.call(arguments,1));throw new thymol.ThError("#messages.msgOrNull Invoked with no arguments!")}throw new thymol.ThError("#messages.msgOrNull Target cannot be null")}function d(a,b){if(null!==a)return thymol.getMessage(a,b,!1);throw new thymol.ThError("#messages.msgOrNullWithParams Target cannot be null")}function e(){if(null!==arguments){if(arguments.length>0)return f(arguments[0],Array.prototype.slice.call(arguments,1));throw new thymol.ThError("#messages.arrayMsg Invoked with no arguments!")}throw new thymol.ThError("#messages.arrayMsg Target cannot be null")}function f(a,c){if(null!==a){for(var d=[],e=0,f=a.length;f>e;e++)d.push(b(a[e],c));return d}throw new thymol.ThError("#messages.arrayMsgWithParams Target cannot be null")}function g(){if(null!==arguments){if(arguments.length>0)return h(arguments[0],Array.prototype.slice.call(arguments,1));throw new thymol.ThError("#messages.setMsg Invoked with no arguments!")}throw new thymol.ThError("#messages.setMsg Target cannot be null")}function h(a,c){if(null!==a){var d=new thymol.ThSet;for(var e in a)a.isContent(e)&&d.add(b(a[e],c));return d}throw new thymol.ThError("#messages.setMsgWithParams Target cannot be null")}function i(){if(null!==arguments){if(arguments.length>0)return j(arguments[0],Array.prototype.slice.call(arguments,1));throw new thymol.ThError("#messages.arrayMsgOrNull Invoked with no arguments!")}throw new thymol.ThError("#messages.arrayMsgOrNull Target cannot be null")}function j(a,b){if(null!==a){for(var c=[],e=0,f=a.length;f>e;e++)c.push(d(a[e],b));return c}throw new thymol.ThError("#messages.arrayMsgOrNullWithParams Target cannot be null")}function k(){if(null!==arguments){if(arguments.length>0)return l(arguments[0],Array.prototype.slice.call(arguments,1));throw new thymol.ThError("#messages.setMsgOrNull Invoked with no arguments!")}throw new thymol.ThError("#messages.setMsgOrNull Target cannot be null")}function l(a,b){if(null!==a){var c=new thymol.ThSet;for(var e in a)a.isContent(e)&&c.add(d(a[e],b));return c}throw new thymol.ThError("#messages.setMsgOrNullWithParams Target cannot be null")}var m="#messages";return{thExpressionObjectName:m,msg:a,msgWithParams:b,msgOrNull:c,msgOrNullWithParams:d,arrayMsg:e,listMsg:e,setMsg:g,arrayMsgWithParams:f,listMsgWithParams:f,setMsgWithParams:h,arrayMsgOrNull:i,listMsgOrNull:i,setMsgOrNull:k,arrayMsgOrNullWithParams:j,listMsgOrNullWithParams:j,setMsgOrNullWithParams:l}}(),thymol.objects.thNumbersObject=function(){function a(){return null!==arguments?arguments.length>4?k(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]):arguments.length>3?j(arguments[0],arguments[1],arguments[2],arguments[3]):i(arguments[0],arguments[1],arguments[2]):void 0}function b(){return null!==arguments?arguments.length>4?k(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]):arguments.length>3?k(arguments[0],arguments[1],"NONE",arguments[2],arguments[3]):arguments.length>2?"string"==typeof arguments[2]?k(arguments[0],arguments[1],arguments[2],0,"POINT"):k(arguments[0],arguments[1],"NONE",arguments[2],"POINT"):k(arguments[0],arguments[1],"NONE",0,"POINT"):void 0}function c(){return null!==arguments?arguments.length>2?m(arguments[0],arguments[1],arguments[2],0,"POINT"):m(arguments[0],arguments[1],"NONE",0,"POINT"):void 0}function d(){return null!==arguments?arguments.length>2?n(arguments[0],arguments[1],arguments[2],0,"POINT"):n(arguments[0],arguments[1],"NONE",0,"POINT"):void 0}function e(){return null!==arguments?arguments.length>4?m(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]):arguments.length>3?m(arguments[0],arguments[1],"NONE",arguments[2],arguments[3]):m(arguments[0],arguments[1],"NONE",arguments[2],"POINT"):void 0}function f(){return null!==arguments?arguments.length>4?n(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4]):arguments.length>3?n(arguments[0],arguments[1],"NONE",arguments[2],arguments[3]):n(arguments[0],arguments[1],"NONE",arguments[2],"POINT"):void 0}function g(){return null!==arguments?arguments.length>2?p(arguments[0],arguments[1],arguments[2]):p(arguments[0],arguments[1],1):void 0}function h(a){var b=a.toString(),c=b.length,d=b.indexOf(".");return d>0&&(c=d),c}function i(a,b,c){var d=a.toString(),e=new Number(a);if(e=e.toFixed(c),b>0){d=e,e=new Number(e);var f=Math.abs(e);if(f<Math.pow(10,b)){0>a&&(d=d.substring(1));var g=h(f),i=b-g;if(i>0)for(var j=0;i>j;j++)d="0"+d;0>a&&(d="-"+d)}}else d=e.toString();return d=new String(d),d.precision=c,d}function j(a,b,c,d){var e,f=i(a,b,c);return e="DEFAULT"===d?s:"NONE"===d?t:l(d),"."!==e&&(f=f.replace(".",e,"g")),f}function k(a,b,c,d,e){var f,g=a.toString();f="DEFAULT"===e?s:"NONE"===e?t:l(e),g=""!==f?j(a,b,d,e):i(a,b,d);var h;return h="DEFAULT"===c?r:l(c),""!==h&&(g=o(g.toString(),f,h)),g}function l(a){var b=".";return"COMMA"===a?b=",":"WHITESPACE"===a?b=" ":"NONE"===a&&(b=""),b}function m(a,b,c,d,e){for(var f=[],g=0,h=a.length;h>g;g++)f.push(k(a[g],b,c,d,e));return f}function n(a,b,c,d,e){var f=new thymol.ThSet;for(var g in a)a.hasOwnProperty(g)&&"function"!=typeof a[g]&&f.add(k(a[g],b,c,d,e));return f}function o(a,b,c){for(var d=a.split(b),e=d[0],f=d.length>1?b+d[1]:"",g=/(\d+)(\d{3})/;g.test(e);)e=e.replace(g,"$1"+c+"$2");return e+f}function p(a,b,c){var d=[];if(c>0){var e=a;if(b>=a){do d.push(e),e+=c;while(b>=e)}else do d.push(e),e-=c;while(e>=b)}return d}var q="#numbers",r=",",s=".",t="?";return{thExpressionObjectName:q,formatDecimal:a,formatInteger:b,arrayFormatInteger:c,arrayFormatDecimal:e,listFormatInteger:c,listFormatDecimal:e,setFormatInteger:d,setFormatDecimal:f,sequence:g}}(),thymol.objects.thObjectsObject=function(){function a(a,b){return null!=a?a:b}function b(b,c){if(null!==b){for(var d=[],e=0,f=b.length;f>e;e++)d.push(a(b[e],c));return d}throw new thymol.ThError("#objects.arrayNullSafe Target cannot be null")}function c(b,c){if(null!==b){var d=new thymol.ThSet;for(var e in b)b.isContent(e)&&d.add(a(b[e],c));return d}throw new thymol.ThError("#objects.setNullSafe Target cannot be null")}var d="#objects";return{thExpressionObjectName:d,nullSafe:a,arrayNullSafe:b,listNullSafe:b,setNullSafe:c}}(),thymol.objects.thSetsObject=function(){function a(a){if(null!==a){var b,c=typeof a,d=Object.prototype.toString.call(a);if("thymol.ThSet"===c&&(b=a),"Array"===c||"[object Array]"===d)b=thymol.ThSet.prototype.fromArray(a);else{if("object"!==c)throw new thymol.ThError('#sets.toSet Cannot convert object of type "'+c+'" to a set');b=new thymol.ThSet;for(var e in a){var f=a[e],g=!1;null!==f&&(g=a instanceof thymol.ThSet?a.isContent(e):a.hasOwnProperty(e)&&"function"!=typeof f),g&&b.add(f)}}return b}throw new thymol.ThError("#sets.toSet Cannot convert null to set")}function b(a){if(null!==a){if(a instanceof thymol.ThSet)return a.size();throw new thymol.ThError('#sets.size Cannot get size of non-set type "'+typeof a+'"')}throw new thymol.ThError("#sets.size Cannot get size of null")}function c(a){if(null!==a){if(a instanceof thymol.ThSet)return a.isEmpty();throw new thymol.ThError('#sets.size Cannot get isEmpty of non-set type "'+typeof a+'"')}throw new thymol.ThError("#sets.size Cannot get isEmpty of null")}function d(a,b){if(null!==a){for(var c in a)if(a.isContent(c))if(null===a[c]){if(null===b)return!0}else if(null!==b&&a[c]===b)return!0;return!1}throw new thymol.ThError("#sets.contains Cannot execute sets contains: target is null")}function e(a,b){if(null!==a){if(null!==b){var c;if(b instanceof Array)c=[].concat(b);else if(b instanceof thymol.ThSet)c=b.toArray();else{c=[];for(var d in b)b.hasOwnProperty(d)&&"function"!=typeof b[d]&&c.push(b[d])}for(var d in a)if(a.isContent(d))for(var e=0,f=c.length;f>e;e++)a[d]===c[e]&&c.splice(e,1);return 0===c.length}throw new thymol.ThError("#sets.containsAll Cannot execute sets containsAll: elements is null")}throw new thymol.ThError("#sets.containsAll Cannot execute sets containsAll: target is null")}var f="#sets";return{thExpressionObjectName:f,toSet:a,size:b,isEmpty:c,contains:d,containsAll:e}}(),thymol.objects.thStringsObject=function(){function a(a){var b=null;return null!==a&&"undefined"!=typeof a&&(b=a.toString()),b}function b(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=[];for(var c=0,d=a.length;d>c;c++)b.push(null!==a[c]?a[c].toString():null)}return b}function c(b){var c=null;if(null!==b&&"undefined"!=typeof b){c=new thymol.ThSet;for(var d in b)b.isContent(d)&&c.add(a(b[d]))}return c}function d(a,b,c){if(b>=3){var d=null;return null!==a&&"undefined"!=typeof a&&(d=a.toString(),d.length>b&&(d=d.substring(0,b-3)+"...")),d}g("abbreviate",b)}function e(a,b){if(b>=3){var c=null;if(null!==a&&"undefined"!=typeof a){c=[];for(var e=0,f=a.length;f>e;e++)c.push(d(a[e],b))}return c}g("arrayAbbreviate",b)}function f(a,b){if(b>=3){var c=null;if(null!==a&&"undefined"!=typeof a){c=new thymol.ThSet;for(var e in a)a.isContent(e)&&c.add(d(a[e],b))}return c}g("setAbbreviate",b)}function g(a,b){throw new thymol.ThError("#strings."+a+' Maximum size must be greater than or equal to 3 but was: "'+b+'"')}function h(a,b){return null===a?null===b:null!==b?a.toString()===b.toString():!1}function i(a,b){return null===a?null===b:null!==b?a.toString().toLowerCase()===b.toString().toLowerCase():!1}function j(a,b){if(null!==a){if(null!==b)return a.toString().indexOf(b)>=0;throw new thymol.ThError("#strings.contains Fragment cannot be null")}throw new thymol.ThError("#strings.contains Cannot apply contains on null")}function k(a,b){if(null!==a){for(var c=[],d=0,e=a.length;e>d;d++)c.push(j(a[d],b));return c}throw new thymol.ThError("#strings.arrayContains Cannot apply arrayContains on null")}function l(a,b){if(null!==a){var c=new thymol.ThSet;for(var d in a)a.isContent(d)&&c.add(j(a[d],b));return c}throw new thymol.ThError("#strings.setContains Cannot apply setContains on null")}function m(a,b){if(null!==a){if(null!==b)return a.toString().toLowerCase().indexOf(b.toLowerCase())>=0;throw new thymol.ThError("#strings.containsIgnoreCase Fragment cannot be null")}throw new thymol.ThError("#strings.containsIgnoreCase Cannot apply containsIgnoreCase on null")}function n(a,b){if(null!==a){for(var c=[],d=0,e=a.length;e>d;d++)c.push(m(a[d],b));return c}throw new thymol.ThError("#strings.arrayContainsIgnoreCase Cannot apply arrayContainsIgnoreCase on null")}function o(a,b){if(null!==a){var c=new thymol.ThSet;for(var d in a)a.isContent(d)&&c.add(m(a[d],b));return c}throw new thymol.ThError("#strings.setContainsIgnoreCase Cannot apply setContainsIgnoreCase on null")}function p(a,b){if(null!==a){if(null!==b)return 0===a.toString().indexOf(b);throw new thymol.ThError("#strings.startsWith Prefix cannot be null")}throw new thymol.ThError("#strings.startsWith Cannot apply startsWith on null")}function q(a,b){if(null!==a){for(var c=[],d=0,e=a.length;e>d;d++)c.push(p(a[d],b));return c}throw new thymol.ThError("#strings.arrayStartsWith Target cannot be null")}function r(a,b){if(null!==a){var c=new thymol.ThSet;for(var d in a)a.isContent(d)&&c.add(p(a[d],b));return c}throw new thymol.ThError("#strings.setStartsWith Target cannot be null")}function s(a,b){if(null!==a){if(null!==b){var c=a.toString();return c.indexOf(b)===c.length-b.length}throw new thymol.ThError("#strings.startsWith Suffix cannot be null")}throw new thymol.ThError("#strings.endsWith Cannot apply endsWith on null")}function t(a,b){if(null!==a){for(var c=[],d=0,e=a.length;e>d;d++)c.push(s(a[d],b));return c}throw new thymol.ThError("#strings.arrayEndsWith Target cannot be null")}function u(a,b){if(null!==a){var c=new thymol.ThSet;for(var d in a)a.isContent(d)&&c.add(s(a[d],b));return c}throw new thymol.ThError("#strings.setEndsWith Target cannot be null")}function v(a,b,c){if(null!==a)return a.toString().substring(b,c);throw new thymol.ThError("#strings.substring Target cannot be null")}function w(a,b,c){if(null!==a){for(var d=[],e=0,f=a.length;f>e;e++)d.push(v(a[e],b,c));return d}throw new thymol.ThError("#strings.arraySubstring Target cannot be null")}function x(a,b,c){if(null!==a){var d=new thymol.ThSet;for(var e in a)a.isContent(e)&&d.add(v(a[e],b,c));return d}throw new thymol.ThError("#strings.setSubstring Target cannot be null")}function y(a,b){if(null!==a){if(null!==b){var c=a.toString(),d=c.indexOf(b);return 0>d?null:c.substring(d+b.length)}throw new thymol.ThError("#strings.substringAfter Parameter substring cannot be null")}throw new thymol.ThError("#strings.substringAfter Cannot apply substringAfter on null")}function z(a,b){if(null!==a){for(var c=[],d=0,e=a.length;e>d;d++)c.push(y(a[d],b));return c}throw new thymol.ThError("#strings.arraySubstringAfter Cannot apply arraySubstringAfter on null")}function A(a,b){if(null!==a){var c=new thymol.ThSet;for(var d in a)a.isContent(d)&&c.add(y(a[d],b));return c}throw new thymol.ThError("#strings.setSubstringAfter Cannot apply setSubstringAfter on null")}function B(a,b){if(null!==a){if(null!==b){var c=a.toString(),d=c.indexOf(b);return 0>d?null:c.substring(0,d)}throw new thymol.ThError("#strings.substringBefore Parameter substring cannot be null")}throw new thymol.ThError("#strings.substringBefore Cannot apply substringBefore on null")}function C(a,b){if(null!==a){for(var c=[],d=0,e=a.length;e>d;d++)c.push(B(a[d],b));return c}throw new thymol.ThError("#strings.arraySubstringBefore Cannot apply arraySubstringBefore on null")}function D(a,b){if(null!==a){var c=new thymol.ThSet;for(var d in a)a.isContent(d)&&c.add(B(a[d],b));return c}throw new thymol.ThError("#strings.setSubstringBefore Cannot apply setSubstringBefore on null")}function E(a,b){if(null!==a){if(null!==b)return b.toString()+a.toString();throw new thymol.ThError("#strings.prepend Prefix cannot be null")}throw new thymol.ThError("#strings.prepend Cannot apply prepend on null")}function F(a,b){if(null!==a){for(var c=[],d=0,e=a.length;e>d;d++)c.push(E(a[d],b));return c}throw new thymol.ThError("#strings.arrayPrepend Cannot apply arrayPrepend on null")}function G(a,b){if(null!==a){var c=new thymol.ThSet;for(var d in a)a.isContent(d)&&c.add(E(a[d],b));return c}throw new thymol.ThError("#strings.setPrepend Cannot apply setPrepend on null")}function H(a,b){for(var c="",d=0;b>d;d++)c+=a.toString();return c}function I(a,b){if(null!==a){if(null!==b)return a.toString()+b.toString();throw new thymol.ThError("#strings.append Suffix cannot be null")}throw new thymol.ThError("#strings.append Cannot apply append on null")}function J(){for(var a="",b=0,c=arguments.length;c>b;b++)null!==arguments[b]&&(a+=arguments[b]);return a}function K(){for(var a="",b=1,c=arguments.length;c>b;b++)a+=null===arguments[b]?arguments[0]:arguments[b];return a}function L(a,b){if(null!==a){for(var c=[],d=0,e=a.length;e>d;d++)c.push(I(a[d],b));return c}throw new thymol.ThError("#strings.arrayAppend Target cannot be null")}function M(a,b){if(null!==a){var c=new thymol.ThSet;for(var d in a)a.isContent(d)&&c.add(I(a[d],b));return c}throw new thymol.ThError("#strings.setAppend Target cannot be null")}function N(a,b){if(null!==a){if(null!==b){var c=a.toString(),d=c.indexOf(b);return d}throw new thymol.ThError("#strings.indexOf Fragment cannot be null")}throw new thymol.ThError("#strings.indexOf Cannot apply indexOf on null")}function O(a,b){if(null!==a){for(var c=[],d=0,e=a.length;e>d;d++)c.push(N(a[d],b));return c}throw new thymol.ThError("#strings.arrayIndexOf Cannot apply arrayIndexOf on null")}function P(a,b){if(null!==a){var c=new thymol.ThSet;for(var d in a)a.isContent(d)&&c.add(N(a[d],b));return c}throw new thymol.ThError("#strings.setIndexOf Cannot apply setIndexOf on null")}function Q(a){if(null!==a){var b=a.toString();if(null!==b&&(b=b.replace(/(?:[\\]t)/g,"     ").replace(/(?:[\\]n)/g,"\n").replace(/(?:[\\]v)/g,"\v").replace(/(?:[\\]f)/g,"\f").replace(/(?:[\\]r)/g,"\r"),b=b.trim(),0!==b.length))return!1}return!0}function R(a){if(null!==a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(Q(a[c]));return b}throw new thymol.ThError("#strings.arrayIsEmpty Target cannot be null")}function S(a){if(null!==a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(Q(a[c]));return b}throw new thymol.ThError("#strings.setIsEmpty Target cannot be null")}function T(a,b){if(null!==a){if(null!==b){for(var c=b.toString(),d="",e=0,f=a.length;f>e;e++)""!==d&&(d+=c),d+=a[e];return d}throw new thymol.ThError("#strings.arrayJoin Separator cannot be null")}throw new thymol.ThError("#strings.arrayJoin Cannot apply join on null")}function U(a,b){if(null!==a){if(null!==b){var c=b.toString(),d="";for(var e in a)a.isContent(e)&&(""!==d&&(d+=c),d+=a[e]);return d}throw new thymol.ThError("#strings.setJoin Separator cannot be null")}throw new thymol.ThError("#strings.setJoin Cannot apply join on null")}function V(a,b){var c=a.toString();return c=c.replace(/[\\]/g,"\\").replace(/[\^]/g,"^").replace(/[\[]/g,"[").replace(/[\]]/g,"]").replace(/[\(]/g,"(").replace(/[\)]/g,")"),c="["+c+"]",new RegExp(c,b)}function W(a,b){for(var c=V(b),d=a.split(c),e=[],f=0,g=d.length;g>f;f++)d[f]&&e.push(d[f]);return e}function X(a,b){if(null!==a){if(null!==b)return W(a,b);throw new thymol.ThError("#strings.arraySplit Separator cannot be null")}throw new thymol.ThError("#strings.arraySplit Cannot apply split on null")}function Y(a,b){if(null!==a){if(null!==b){for(var c=new thymol.ThSet,d=W(a,b),e=0,f=d.length;f>e;e++)c.add(d[e]);return c}throw new thymol.ThError("#strings.setSplit Separator cannot be null")}throw new thymol.ThError("#strings.setSplit Cannot apply split on null")}function Z(a){if(null!==a)return a.toString().length;throw new thymol.ThError("#strings.length Cannot apply length on null")}function $(a){if(null!==a){for(var b=[],c=0,d=a.length;d>c;c++)b.push(Z(a[c]));return b}throw new thymol.ThError("#strings.arrayLength Target cannot be null")}function _(a){if(null!==a){var b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(Z(a[c]));return b}throw new thymol.ThError("#strings.setLength Target cannot be null")}function aa(a){var b=a.replace(/[$]/g,"[$]").replace(/[*]/g,"[*]").replace(/[\']/g,"[']").replace(/[+]/g,"[+]").replace(/[\(]/g,"[(]").replace(/[\)]/g,"[)]");return new RegExp(b,"g")}function ba(a,b,c){if(null!==a){if(null!==b){var d=Ba(b);if(null!==c){var e=aa(d),f=Ba(c);return a.replace(e,f)}throw new thymol.ThError("#strings.replace After cannot be null")}throw new thymol.ThError("#strings.replace Before cannot be null")}throw new thymol.ThError("#strings.replace Cannot apply replace on null")}function ca(a,b,c){if(null!==a){if(null!==b){var d=Ba(b);if(null!==c){for(var e=aa(d),f=Ba(c),g=[],h=0,i=a.length;i>h;h++)g.push(a[h].toString().replace(e,f));return g}throw new thymol.ThError("#strings.arrayReplace After cannot be null")}throw new thymol.ThError("#strings.arrayReplace Before cannot be null")}throw new thymol.ThError("#strings.arrayReplace Cannot apply replace on null")}function da(a,b,c){if(null!==a){if(null!==b){var d=Ba(b);if(null!==c){var e=aa(d),f=Ba(c),g=new thymol.ThSet;for(var h in a)a.isContent(h)&&g.add(a[h].toString().replace(e,f));return g}throw new thymol.ThError("#strings.setReplace Array of 'after' values cannot be null")}throw new thymol.ThError("#strings.setReplace Array of 'before' values cannot be null")}throw new thymol.ThError("#strings.setReplace Cannot apply replace on null")}function ea(a,b,c){if(null!==a){if(null!==b){if("[object Array]"==Object.prototype.toString.call(b)){if(null!==c){if("[object Array]"==Object.prototype.toString.call(c)){if(b.length===c.length){for(var d,e,f=a,g=0,h=b.length;h>g;g++){d=Ba(b[g]);var i=aa(d);e=Ba(c[g]),f=f.replace(i,e)}return f}throw new thymol.ThError("#strings.multipleReplace Arrays of 'before' and 'after' values must have the same length")}throw new thymol.ThError("#strings.multipleReplace After must be an array type")}throw new thymol.ThError("#strings.multipleReplace After cannot be null")}throw new thymol.ThError("#strings.multipleReplace Before must be an array type")}throw new thymol.ThError("#strings.multipleReplace Before cannot be null")}throw new thymol.ThError("#strings.multipleReplace Target cannot be null")}function fa(a,b,c){if(null!==a){for(var d=[],e=0,f=a.length;f>e;e++)d.push(ea(a[e].toString(),b,c));return d}throw new thymol.ThError("#strings.arrayMultipleReplace Target cannot be null")}function ga(a,b,c){if(null!==a){var d=new thymol.ThSet;for(var e in a)a.isContent(e)&&d.add(ea(a[e].toString(),b,c));return d}throw new thymol.ThError("#strings.setMultipleReplace Target cannot be null")}function ha(a){var b=null;return null!==a&&"undefined"!=typeof a&&(b=a.toString().toUpperCase()),b}function ia(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=[];for(var c=0,d=a.length;d>c;c++)b.push(null!==a[c]?a[c].toString().toUpperCase():null)}return b}function ja(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(a[c].toString().toUpperCase())}return b}function ka(a){var b=null;return null!==a&&"undefined"!=typeof a&&(b=a.toString().toLowerCase()),b}function la(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=[];for(var c=0,d=a.length;d>c;c++)b.push(null!==a[c]?a[c].toString().toLowerCase():null)}return b}function ma(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(a[c].toString().toLowerCase())}return b}function na(a){var b=null;return null!==a&&"undefined"!=typeof a&&(b=a.toString().trim()),b}function oa(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=[];for(var c=0,d=a.length;d>c;c++)b.push(null!==a[c]?a[c].toString().trim():null)}return b}function pa(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(a[c].toString().trim())}return b}function qa(a){var b=null;return null!==a&&"undefined"!=typeof a&&(b=a.toString(),b.length>0&&(b=b.charAt(0).toUpperCase()+b.substr(1))),b}function ra(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=[];for(var c=0,d=a.length;d>c;c++)b.push(null!==a[c]?qa(a[c]):null)}return b}function sa(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(qa(a[c]))}return b}function ta(a){var b=null;return null!==a&&"undefined"!=typeof a&&(b=a.toString(),b.length>0&&(b=b.charAt(0).toLowerCase()+b.substr(1))),b}function ua(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=[];for(var c=0,d=a.length;d>c;c++)b.push(null!==a[c]?ta(a[c]):null)}return b}function va(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(ta(a[c]))}return b}function wa(a,b){var c;if("undefined"==typeof b)c=new RegExp("[^        \r\n\f\v]\\w*","g");else{var d="[^ "+b+"]\\w*";c=new RegExp(d,"g")}var e=null;if(null!==a&&"undefined"!=typeof a){var f=a.toString();if(f.length>0){e="";for(var g,h=0;null!==(g=c.exec(f));)e+=f.substring(h,g.index),e+=g[0].charAt(0).toUpperCase()+g[0].substr(1),h=c.lastIndex;e+=f.substring(h)}}return e}function xa(a,b){var c=null;if(null!==a&&"undefined"!=typeof a){c=[];for(var d=0,e=a.length;e>d;d++)c.push(null!==a[d]?wa(a[d],b):null)}return c}function ya(a,b){var c=null;if(null!==a&&"undefined"!=typeof a){c=new thymol.ThSet;for(var d in a)a.isContent(d)&&c.add(wa(a[d],b))}return c}function za(a,b){var c=a;if(null!==a&&"undefined"!=typeof a){var d=null!==b&&"undefined"!=typeof b&&b;if(d)c=Aa(a);else{c="";for(var e=0,f=a.length;f>e;e++){var g=a.charAt(e);"&"===g?Da(a,e)||(g="&amp;"):"<"===g?g="&amp;lt;":">"===g?g="&amp;gt;":'"'===g?g="&amp;quot;":"'"===g&&(g="&amp;#39;"),c+=g}}}return c}function Aa(a){for(var b="",c=0,d=a.length;d>c;c++){var e=a.charAt(c);"&"===e?Da(a,c)||(e="&amp;"):"<"===e?e="&lt;":">"===e?e="&gt;":'"'===e?e="&quot;":"'"===e&&(e="&#39;"),b+=e}return b}function Ba(a){for(var b="",c=0,d=a.length;d>c;c++){var e=a.charAt(c);"&"===e&&(e=Ca(a,c),"&"!==e?(c+=e.length,"&lt;"===e?e="<":"&gt;"===e?e=">":"&amp;"===e?e="&":"&quot;"===e?e='"':"&#39;"===e&&(e="'")):e="&amp;"),b+=e}return b}function Ca(a,b){for(var c="&",d=b+1;d<a.length;){var e=a[d];if(!(e>="A"&&"Z">=e||e>="a"&&"z">=e||e>="0"&&"9">=e||";"==e||"#"==e))return"&";if(c+=e,";"==e)return c;d++}return"&"}function Da(a,b){for(var c=b+1;c<a.length;){var d=a[c];if(!(d>="A"&&"Z">=d||d>="a"&&"z">=d||d>="0"&&"9">=d||";"==d||"#"==d))return!1;if(";"==d)return!0;c++}return!1}function Ea(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=[];for(var c=0,d=a.length;d>c;c++)b.push(null!==a[c]?za(a[c],!1):null);
+
+}return b}function Fa(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(za(a[c],!1))}return b}function Ga(a){var b=a;return null!==a&&"undefined"!=typeof a&&(b=Ha(a,!0)),b}function Ha(a,b){for(var c="",d=0,e=a.length;e>d;d++){var f=a.charAt(d),g=a.charCodeAt(d);if(g>=32&&127>=g)switch(f){case"\\":f="\\";break;case'"':f='\\"';break;case"'":b&&(f="\\'");break;case"/":b&&d>0&&"<"==a.charAt(d-1)&&(f="\\/");break;case">":b&&d>1&&"]"==a.charAt(d-1)&&"]"==a.charAt(d-2)&&(f="\\>")}else switch(f){case"     ":f="\\t";break;case"\n":f="\\n";break;case"\b":f="\\b";break;case"\f":f="\\f";break;case"\r":f="\\r";break;default:f=b?Ja(g):Ia(g)}c+=f}return c}function Ia(a){var b=a+65536;b=b.toString(16),b=b.slice(1);var c="\\u"+b.toUpperCase();return c}function Ja(a){var b=a+256;b=b.toString(16),b=b.slice(1);var c="\\x"+b.toUpperCase();return c}function Ka(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=[];for(var c=0,d=a.length;d>c;c++)b.push(null!==a[c]?Ga(a[c]):null)}return b}function La(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(Ga(a[c]))}return b}function Ma(a){var b=a;return null!==a&&"undefined"!=typeof a&&(b=Na(a)),b}function Na(a){for(var b="",c="",d=-1,e="",f=-1,g=!1,h=0,i=a.length;i>h;h++){var j=a.charAt(h);if(d>=0){if(c+=j,!(j>="0"&&"9">=j||j>="A"&&"F">=j||j>="a"&&"f">=j))return a;if(d++,d>3){var k=parseInt(c,16);j=String.fromCharCode(k),c="",d=-1,b+=j,g=!1}}else if(f>=0){if(e+=j,!(j>="0"&&"9">=j||j>="A"&&"F">=j||j>="a"&&"f">=j))return a;if(f++,f>1){var k=parseInt(e,16);j=String.fromCharCode(k),e="",f=-1,b+=j,g=!1}}else if(g)if("u"===j)d=0;else if("x"===j)f=0;else{switch(j){case"t":j="      ";break;case"n":j="\n";break;case"b":j="\b";break;case"f":j="\f";break;case"r":j="\r"}b+=j,g=!1}else"\\"==j?g=!0:(b+=j,g=!1)}return d>=0?b+="\\u"+c:f>=0?b+="\\x"+e:g&&(b+="\\"),b}function Oa(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=[];for(var c=0,d=a.length;d>c;c++)b.push(null!==a[c]?Ma(a[c]):null)}return b}function Pa(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(Ma(a[c]))}return b}function Qa(a){var b=a;return null!==a&&"undefined"!=typeof a&&(b=Ha(a,!1)),b}function Ra(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=[];for(var c=0,d=a.length;d>c;c++)b.push(null!==a[c]?Qa(a[c]):null)}return b}function Sa(a){var b=null;if(null!==a&&"undefined"!=typeof a){b=new thymol.ThSet;for(var c in a)a.isContent(c)&&b.add(Qa(a[c]))}return b}function Ta(a){for(var b="",c=0;a>c;c++)b+=$a.charAt(Math.floor(Math.random()*$a.length));return b}function Ua(a,b){if(null!==b&&"undefined"!=typeof b){if(null==a)return b.toString();var c=a.toString();return Q(c)?b.toString():c}throw new thymol.ThError("#strings.defaultString defaultValue cannot be null")}function Va(a,b){if(null==a||"undefined"==typeof a)return a;for(var c=[],d=0,e=a.length;e>d;d++)c.push(Ua(a[d],b));return c}function Wa(a,b){if(null!==b&&"undefined"!=typeof b)return Va(a,b);throw new thymol.ThError("#strings.arrayDefaultString defaultValue cannot be null")}function Xa(a,b){if(null!==b&&"undefined"!=typeof b)return Va(a,b);throw new thymol.ThError("#strings.listDefaultString defaultValue cannot be null")}function Ya(a,b){if(null!==b&&"undefined"!=typeof b){if(null==a||"undefined"==typeof a)return a;result=new thymol.ThSet;for(var c in a)a.isContent(c)&&result.add(Ua(a[c],b));return result}throw new thymol.ThError("#strings.setDefaultString defaultValue cannot be null")}var Za="#strings",$a="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";return{thExpressionObjectName:Za,toString:a,arrayToString:b,listToString:b,setToString:c,abbreviate:d,arrayAbbreviate:e,listAbbreviate:e,setAbbreviate:f,equals:h,equalsIgnoreCase:i,contains:j,arrayContains:k,listContains:k,setContains:l,containsIgnoreCase:m,arrayContainsIgnoreCase:n,listContainsIgnoreCase:n,setContainsIgnoreCase:o,startsWith:p,arrayStartsWith:q,listStartsWith:q,setStartsWith:r,endsWith:s,arrayEndsWith:t,listEndsWith:t,setEndsWith:u,substring:v,arraySubstring:w,listSubstring:w,setSubstring:x,substringAfter:y,arraySubstringAfter:z,listSubstringAfter:z,setSubstringAfter:A,substringBefore:B,arraySubstringBefore:C,listSubstringBefore:C,setSubstringBefore:D,prepend:E,arrayPrepend:F,listPrepend:F,setPrepend:G,repeat:H,append:I,concat:J,concatReplaceNulls:K,arrayAppend:L,listAppend:L,setAppend:M,indexOf:N,arrayIndexOf:O,listIndexOf:O,setIndexOf:P,isEmpty:Q,arrayIsEmpty:R,listIsEmpty:R,setIsEmpty:S,arrayJoin:T,listJoin:T,setJoin:U,arraySplit:X,listSplit:X,setSplit:Y,length:Z,arrayLength:$,listLength:$,setLength:_,replace:ba,arrayReplace:ca,listReplace:ca,setReplace:da,multipleReplace:ea,arrayMultipleReplace:fa,listMultipleReplace:fa,setMultipleReplace:ga,toUpperCase:ha,arrayToUpperCase:ia,listToUpperCase:ia,setToUpperCase:ja,toLowerCase:ka,arrayToLowerCase:la,listToLowerCase:la,setToLowerCase:ma,trim:na,arrayTrim:oa,listTrim:oa,setTrim:pa,capitalize:qa,arrayCapitalize:ra,listCapitalize:ra,setCapitalize:sa,unCapitalize:ta,arrayUnCapitalize:ua,listUnCapitalize:ua,setUnCapitalize:va,capitalizeWords:wa,arrayCapitalizeWords:xa,listCapitalizeWords:xa,setCapitalizeWords:ya,escapeXml:za,arrayEscapeXml:Ea,listEscapeXml:Ea,setEscapeXml:Fa,escapeJavaScript:Ga,arrayEscapeJavaScript:Ka,listEscapeJavaScript:Ka,setEscapeJavaScript:La,unescapeJavaScript:Ma,arrayUnescapeJavaScript:Oa,listUnescapeJavaScript:Oa,setUnescapeJavaScript:Pa,escapeJava:Qa,arrayEscapeJava:Ra,listEscapeJava:Ra,setEscapeJava:Sa,unescapeJava:Ma,arrayUnescapeJava:Oa,listUnescapeJava:Oa,setUnescapeJava:Pa,randomAlphanumeric:Ta,defaultString:Ua,arrayDefaultString:Wa,listDefaultString:Xa,setDefaultString:Ya}}(),thymol.thObjectsConfigureModules=function(){thymol.addDialect({objects:[thymol.objects.thAggregatesObject,thymol.objects.thArraysObject,thymol.objects.thBoolsObject,thymol.objects.thDatesObject,thymol.objects.thCalendarsObject,thymol.objects.thIdsObject,thymol.objects.thListsObject,thymol.objects.thMapsObject,thymol.objects.thMessagesObject,thymol.objects.thNumbersObject,thymol.objects.thObjectsObject,thymol.objects.thSetsObject,thymol.objects.thStringsObject]})},thymol.isServerSide=function(){return!0},exports.thymol=thymol;
\ No newline at end of file
diff --git a/dist/js/thymol.js b/dist/js/thymol.js
new file mode 100644 (file)
index 0000000..a23289f
--- /dev/null
@@ -0,0 +1,100 @@
+/*-------------------- Thymol - the flavour of Thymeleaf --------------------*
+
+   Thymol version 2.0.0 Copyright (C) 2012-2015 James J. Benson
+   jjbenson .AT. users.sf.net (http://www.thymoljs.org/)
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" basis,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ *---------------------------------------------------------------------------*/
+
+(function() {
+    var thymolConfiguration = {
+        thScriptName: "thymol-full.js",
+        thJQuerySource: "http://code.jquery.com/jquery-1.11.1.min.js",
+        thDefaultPrefix: "th",
+        thDefaultDataPrefix: "data",
+        thDefaultPrecision: 10,
+        thDefaultProtocol: "file:///",
+        thDefaultLocale: "en",
+        thDefaultPrecedence: 2e4,
+        thDefaultMessagePath: "",
+        thDefaultResourcePath: "",
+        thDefaultMessagesBaseName: "Messages",
+        thDefaultRelativeRootPath: "",
+        thDefaultExtendedMapping: false,
+        thDefaultLocalMessages: true,
+        thDefaultDisableMessages: false,
+        thDefaultTemplateSuffix: ".html"
+    };
+    thymol = function(conf) {
+        conf.ready = function(func) {
+            if (typeof thymolDeferredFunctions === "undefined" || thymolDeferredFunctions === null) {
+                thymolDeferredFunctions = [];
+            }
+            thymolDeferredFunctions.push(func);
+        };
+        return conf;
+    }(thymolConfiguration);
+    thymol.thDomParser = DOMParser;
+    thymol.thWindow = window;
+    var toc = 0;
+    var loadScript = function(script, params) {
+        var el = document.createElement("script");
+        el.async = false;
+        if (typeof script !== "undefined" && script !== null) {
+            el.src = script;
+        }
+        if (typeof params !== "undefined" && params !== null) {
+            el.src += params.charAt(0) === "?" ? params : "?" + params;
+        }
+        el.type = "text/javascript";
+        (document.getElementsByTagName("HEAD")[0] || document.body).appendChild(el);
+    };
+    var scripts = document.getElementsByTagName("script");
+    var script = document.currentScript || scripts[scripts.length - 1];
+    var scriptSrc = script.getAttribute("src");
+    var pathEnd = scriptSrc.lastIndexOf("/");
+    if (pathEnd >= 0) {
+        thymol.thLocation = scriptSrc.substring(0, 1 + pathEnd);
+    }
+    var jquerySrc = script.getAttribute("data-jquery-src");
+    if (!!jquerySrc || "" === jquerySrc) {
+        thymol.thJQuerySource = jquerySrc;
+        if ("" !== thymol.thJQuerySource) {
+            loadScript(thymol.thJQuerySource);
+        }
+    } else if (typeof thymol.thJQuerySource !== "undefined" && thymol.thJQuerySource !== null && thymol.thJQuerySource.length > 0) {
+        var hasProtocol = thymol.thJQuerySource.indexOf(":/") >= 0;
+        if (hasProtocol || thymol.thJQuerySource.charAt(0) === "/") {
+            if (!hasProtocol) {
+                loadScript(thymol.thDefaultProtocol + thymol.thJQuerySource);
+            } else {
+                loadScript(thymol.thJQuerySource);
+            }
+        } else {
+            loadScript(thymol.thLocation + thymol.thJQuerySource);
+        }
+    }
+    var thymolSrc = script.getAttribute("data-thymol-src");
+    if (!!thymolSrc) {
+        thymol.thScriptName = thymolSrc;
+    }
+    var parameters = null;
+    for (var i = 0, iLimit = scripts.length; i < iLimit; i++) {
+        parameters = scripts[i].getAttribute("data-thymol-parameters");
+        if (!!parameters) {
+            break;
+        }
+    }
+    loadScript(thymol.thLocation + thymol.thScriptName, parameters);
+})();
\ No newline at end of file