WIP: Thymoljs
[website] / dist / js / thymol-full.js
1 /*-------------------- Thymol - the flavour of Thymeleaf --------------------*
2
3    Thymol version 2.0.0 Copyright (C) 2012-2015 James J. Benson
4    jjbenson .AT. users.sf.net (http://www.thymoljs.org/)
5
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" basis,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expressed or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17
18  *---------------------------------------------------------------------------*/
19
20 thymol = function() {
21     thymol.thVersion = "2.0.0";
22     thymol.thReleaseDate = "2015-03-31";
23     thymol.thURL = "http://www.thymoljs.org";
24     thymol.thAltURL = "http://www.thymeleaf.org";
25     thymol.thUsingNullPrefix = false;
26     thymol.thThymeleafPrefixList = [];
27     thymol.thThymeleafElementsList = [];
28     thymol.objects = {};
29     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 = /\.*?([\|][^\|]*?[\|])\.*?/;
30     function Thymol() {}
31     function isClientSide() {
32         if (typeof thymol.isServerSide !== "undefined" && !!thymol.isServerSide()) {
33             thymol.isClientSide = function() {
34                 return false;
35             };
36             return false;
37         }
38         thymol.isClientSide = function() {
39             return true;
40         };
41         return true;
42     }
43     function execute(doc) {
44         if (typeof thymol.protocol === "undefined") {
45             thymol.protocol = "";
46         }
47         if (typeof thymol.root === "undefined") {
48             thymol.root = "";
49         }
50         if (typeof thymol.path === "undefined") {
51             thymol.path = "";
52         }
53         thymol.thDocument = doc;
54         var theWindow = thymol.thWindow;
55         if (typeof thymol.thWindow === "undefined") {
56             if (typeof doc.defaultView !== "undefined") {
57                 theWindow = doc.defaultView;
58             } else if (typeof doc.parentWindow !== "undefined") {
59                 theWindow = doc.parentWindow;
60             }
61         }
62         thymol.thWindow = theWindow;
63         var theTop = thymol.thTop;
64         if (typeof thymol.thTop === "undefined") {
65             if (typeof top !== "undefined") {
66                 theTop = top;
67             }
68         }
69         thymol.thTop = theTop;
70         thymol.init();
71         var base = new ThNode(thymol.thDocument, false, null, null, null, thymol.thDocument.nodeName, "::", false, thymol.thDocument);
72         Thymol.prototype.process(base);
73         postExecute();
74         return thymol.thDocument;
75     }
76     function jqSetup(jq) {
77         jq.fn.extend({
78             getComments: function() {
79                 return this.filter(function() {
80                     return this.nodeType === 8;
81                 });
82             },
83             getThDecorated: function(thInst) {
84                 var i, iAttrName, iLength, j, jLength, instances = [], result = null, expanded = false;
85                 if (thInst.escpName !== null) {
86                     instances = this.filter(thInst.escpName);
87                 }
88                 if (thInst.escpSynonym !== null) {
89                     instances = instances.add(this.filter(thInst.escpSynonym));
90                 }
91                 for (i = 0, iLength = instances.length; i < iLength; i++) {
92                     if (instances[i]) {
93                         for (j = 0, jLength = instances[i].attributes.length; j < jLength; j++) {
94                             if (instances[i].attributes[j]) {
95                                 iAttrName = instances[i].attributes[j].name;
96                                 if (iAttrName && (thInst.name == iAttrName || thInst.synonym == iAttrName)) {
97                                     expanded = thymol.ThUtils.processElement(thInst.process, instances[i], instances[i].attributes[j], thInst);
98                                     if (expanded) {
99                                         if (result === null) {
100                                             result = [];
101                                         }
102                                         result.push(instances[i]);
103                                     }
104                                 }
105                             }
106                         }
107                     }
108                 }
109                 return result;
110             }
111         });
112     }
113     function ready(func) {
114         if (typeof thymolDeferredFunctions === "undefined" || thymolDeferredFunctions === null) {
115             thymolDeferredFunctions = [];
116         }
117         thymolDeferredFunctions.push(func);
118     }
119     function setupEnv() {
120         thymol.prefix = Thymol.prototype.getThParam("thPrefix", false, false, thymol.thDefaultPrefix);
121         thymol.dataPrefix = Thymol.prototype.getThParam("thDataPrefix", false, false, thymol.thDefaultDataPrefix);
122         thymol.messagePath = Thymol.prototype.getThParam("thMessagePath", false, true, thymol.thDefaultMessagePath);
123         thymol.resourcePath = Thymol.prototype.getThParam("thResourcePath", false, true, thymol.thDefaultResourcePath);
124         thymol.messagesBaseName = Thymol.prototype.getThParam("thMessagesBaseName", false, false, thymol.thDefaultMessagesBaseName);
125         thymol.relativeRootPath = Thymol.prototype.getThParam("thRelativeRootPath", false, true, thymol.thDefaultRelativeRootPath);
126         thymol.extendedMapping = Thymol.prototype.getThParam("thExtendedMapping", true, false, thymol.thDefaultExtendedMapping);
127         thymol.localMessages = Thymol.prototype.getThParam("thLocalMessages", true, false, thymol.thDefaultLocalMessages);
128         thymol.disableMessages = Thymol.prototype.getThParam("thDisableMessages", true, false, thymol.thDefaultDisableMessages);
129         thymol.templateSuffix = Thymol.prototype.getThParam("thTemplateSuffix", false, false, thymol.thDefaultTemplateSuffix);
130         thymol.scriptPath = "";
131         if (typeof thymol.thScriptPath !== "undefined") {
132             thymol.scriptPath = Thymol.prototype.getThParam("thScriptPath", false, true, thymol.thScriptPath);
133         }
134         thymol.absolutePath = "";
135         if (typeof thymol.thAbsolutePath !== "undefined") {
136             thymol.absolutePath = Thymol.prototype.getThParam("thAbsolutePath", false, true, thymol.thAbsolutePath);
137         }
138         thymol.useAbsolutePath = false;
139         if (typeof thymol.thUseAbsolutePath !== "undefined") {
140             thymol.useAbsolutePath = Thymol.prototype.getThParam("thUseAbsolutePath", true, false, thymol.thUseAbsolutePath);
141         }
142         thymol.useFullURLPath = true;
143         if (typeof thymol.thUseFullURLPath !== "undefined") {
144             thymol.useFullURLPath = Thymol.prototype.getThParam("thUseFullURLPath", true, false, thymol.thUseFullURLPath);
145         }
146         thymol.indexFile = Thymol.prototype.getThParam("thIndexFile", false, false, null);
147         thymol.debug = Thymol.prototype.getThParam("thDebug", true, false, false);
148         thymol.allowNullText = Thymol.prototype.getThParam("thAllowNullText", true, false, true);
149         thymol.location = thymol.thLocation;
150         if ("" !== thymol.relativeRootPath) {
151             thymol.root = thymol.location + thymol.relativeRootPath;
152             thymol.messagePath = thymol.root + thymol.messagePath;
153         } else {
154             if (typeof thymol.thMessagePath !== "undefined") {
155                 thymol.messagePath = Thymol.prototype.getThParam("thMessagePath", false, true, thymol.thMessagePath);
156             }
157             if (typeof thymol.thRoot !== "undefined") {
158                 thymol.root = Thymol.prototype.getThParam("thRoot", false, true, thymol.thRoot);
159             }
160         }
161         thymol.root = Thymol.prototype.getThParam("thRoot", false, true, thymol.root);
162         if (typeof thymol.thPath !== "undefined") {
163             thymol.path = Thymol.prototype.getThParam("thPath", false, true, thymol.thPath);
164         }
165         thymol.path = Thymol.prototype.getThParam("thPath", false, true, thymol.path);
166         thymol.protocol = thymol.thDocument.location.protocol;
167         if ("" == thymol.protocol) {
168             thymol.protocol = thymol.thDefaultProtocol;
169         } else {
170             thymol.protocol += "//";
171             if ("" == thymol.thDocument.location.host) {
172                 thymol.protocol += "/";
173             }
174         }
175         thymol.protocol = Thymol.prototype.getThParam("thProtocol", false, false, thymol.protocol);
176         thymol.resourcePath = Thymol.prototype.getThParam("thResourcePath", false, true, thymol.resourcePath);
177     }
178     function updatePrefix(pref) {
179         thymol.prefix = pref;
180         thymol.thThymeleafPrefixList = [];
181         thymol.thThymeleafElementsList = [];
182     }
183     function init() {
184         this.messages = null;
185         this.mappings = null;
186         this.debug = null;
187         getLocations(this);
188         this.locale = new thymol.ThObject();
189         getLanguage();
190         var accessor = undefined, i, iLimit, j, jLimit;
191         if (typeof thVars !== "undefined") {
192             accessor = new thymol.ThVarsAccessor(thVars, "thVars");
193         }
194         this.applicationContext = thymol.makeContext("application", accessor);
195         this.sessionContext = thymol.makeContext("session", undefined);
196         this.sessionContext.persist = function() {
197             var save = this.serialise();
198             thymol.thTop.name = save;
199         };
200         this.requestContext = thymol.makeContext("request", undefined);
201         this.booleanAndNullTokens = new Array();
202         this.booleanAndNullTokens["null"] = this.applicationContext.createVariable("null", null);
203         this.booleanAndNullTokens["true"] = this.applicationContext.createVariable("true", true);
204         this.booleanAndNullTokens["false"] = this.applicationContext.createVariable("false", false);
205         this.allowNullText = null;
206         setupEnv();
207         this.thCache = {};
208         this.thExpressionObjects;
209         this.thDeferredFunctions;
210         this.thPreExecutionFunctions;
211         this.thPostExecutionFunctions;
212         if (typeof this.thExpressionObjects === "undefined" || this.thExpressionObjects === null) {
213             this.thExpressionObjects = {};
214         }
215         this.thExpressionObjects["#object"] = {};
216         this.thExpressionObjects["#locale"] = {};
217         this.thExpressionObjects["#ctx"] = [];
218         this.thExpressionObjects["#ctx"]["variables"] = {};
219         thymol.configureModule(thymol.objects.thHttpServletRequestObject);
220         thymol.configureModule(thymol.objects.thHttpSessionObject);
221         if (typeof thymol.thObjectsConfigureModules !== "undefined") {
222             thymol.thObjectsConfigureModules();
223         }
224         var scripts = thymol.thDocument.getElementsByTagName("script");
225         for (var i = 0, iLimit = scripts.length; i < iLimit; i++) {
226             var parameters = scripts[i].getAttribute("data-thymol-load");
227             if (!!parameters) {
228                 var splits = parameters.split(",");
229                 for (var j = 0, jLimit = splits.length; j < jLimit; j++) {
230                     thymol.ThUtils.loadScript(splits[j]);
231                 }
232             }
233         }
234         setupEnv();
235         if (typeof thymol.thPreExecutionFunctions === "undefined" || thymol.thPreExecutionFunctions === null) {
236             thymol.thPreExecutionFunctions = [];
237         }
238         if (typeof thymol.thPostExecutionFunctions === "undefined" || thymol.thPostExecutionFunctions === null) {
239             thymol.thPostExecutionFunctions = [];
240         }
241         $.ajaxSetup({
242             async: false,
243             isLocal: true,
244             dataType: "text"
245         });
246         if (!(typeof thVars === "undefined")) {
247             for (i = 0, iLimit = thVars.length; i < iLimit; i++) {
248                 this.applicationContext.createVariable(thVars[i][0], thVars[i][1]);
249             }
250         }
251         executeDeferred();
252         (function() {
253             var htmlTagAttrs = $("html")[0].attributes, tp = null, tu, nsspec;
254             $([ thymol.thURL, thymol.thAltURL ]).each(function() {
255                 tu = this;
256                 $(htmlTagAttrs).each(function() {
257                     if (this.value == tu) {
258                         nsspec = this.localName.split(":");
259                         if (nsspec.length > 0) {
260                             tp = nsspec[nsspec.length - 1];
261                             return false;
262                         }
263                     }
264                 });
265                 if (tp) {
266                     thymol.updatePrefix(tp);
267                     return false;
268                 }
269             });
270         })();
271         var defaultScriptUrl = "";
272         if (!!thymol.thRequest) {
273             thymol.thWindow.location.search = thymol.thRequest;
274         }
275         (function(app, req) {
276             var e, f, a = /\+/g, r = /([^&=]+)=?([^&]*)/g, d = function(s) {
277                 return decodeURIComponent(s.replace(a, " "));
278             }, q = thymol.thWindow.location.search.substring(1), surl, scriptUrl = defaultScriptUrl;
279             $("script").each(function() {
280                 surl = this.src;
281                 if (surl.indexOf(thymol.thScriptName) >= 0) {
282                     scriptUrl = d(surl);
283                     return false;
284                 }
285             });
286             while (e = r.exec(scriptUrl)) {
287                 f = e[1].split("?");
288                 switch (f[1]) {
289                   case "thPrefix":
290                     thymol.prefix = e[2];
291                     break;
292
293                   case "thDataPrefix":
294                     thymol.dataPrefix = e[2];
295                     break;
296
297                   case "thMessagePath":
298                     thymol.messagePath = e[2];
299                     break;
300
301                   case "thResourcePath":
302                     thymol.resourcePath = e[2];
303                     break;
304
305                   case "thMessagesBaseName":
306                     thymol.messagesBaseName = e[2];
307                     break;
308
309                   case "thRelativeRootPath":
310                     thymol.relativeRootPath = e[2];
311                     break;
312
313                   case "thExtendedMapping":
314                     thymol.extendedMapping = e[2];
315                     break;
316
317                   case "thTemplateSuffix":
318                     thymol.templateSuffix = e[2];
319                     break;
320
321                   case "thLocalMessages":
322                     thymol.localMessages = e[2];
323                     break;
324
325                   case "thDisableMessages":
326                     thymol.disableMessages = e[2];
327                     break;
328
329                   case "thIndexFile":
330                     thymol.indexFile = e[2];
331                     break;
332
333                   case "thProtocol":
334                     thymol.protocol = e[2];
335                     break;
336
337                   case "thDebug":
338                     thymol.debug = e[2];
339                     break;
340
341                   case "thRoot":
342                     thymol.root = e[2];
343                     break;
344
345                   case "thPath":
346                     thymol.path = e[2];
347                     break;
348
349                   case "thAllowNullText":
350                     thymol.allowNullText = e[2];
351                     break;
352
353                   case "thLocale":
354                     thymol.locale.value = e[2];
355                     break;
356
357                   case "thDefaultPrecision":
358                     thymol.thDefaultPrecision = e[2];
359                     break;
360
361                   case "thDefaultPrecedence":
362                     thymol.thDefaultPrecedence = e[2];
363                     break;
364
365                   default:
366                     app.createVariable(e[1], e[2]);
367                 }
368             }
369             while (e = r.exec(q)) {
370                 req.createVariable(d(e[1]), e[2], true);
371             }
372         })(this.applicationContext, this.requestContext);
373         thymol.thInclude = new thymol.ThAttr("include", null, 100, null, thymol.prefix);
374         thymol.thReplace = new thymol.ThAttr("replace", null, 100, null, thymol.prefix);
375         thymol.thSubstituteby = new thymol.ThAttr("substituteby", null, 100, null, thymol.prefix);
376         thymol.thFragment = new thymol.ThAttr("fragment", null, 2e4, null, thymol.prefix);
377         thymol.thRemove = null;
378         thymol.thBlock = new thymol.ThElement("block", function(element) {
379             var i, limit = element.childNodes.length;
380             for (i = 0; i < limit; i++) {
381                 if (element.childNodes[i].nodeType === 1) {
382                     element.childNodes[i].isBlockChild = true;
383                 }
384             }
385         }, thymol.prefix);
386         this.applicationContext.resolveJSONReferences();
387         thymol.setupAttrList();
388         preExecute(this.applicationContext);
389         this.thExpressionObjects["#vars"] = this.applicationContext;
390         this.thExpressionObjects["#root"] = this.applicationContext;
391         this.sessionContext.init();
392         this.sessionContext.resolveJSONReferences();
393         this.requestContext.resolveJSONReferences();
394         this.thExpressionObjects["#ctx"]["variables"] = this.applicationContext;
395         this.thExpressionObjects["#ctx"]["requestParameters"] = this.requestContext;
396         this.thExpressionObjects["#ctx"]["servletContext"] = this.applicationContext;
397         this.thExpressionObjects["#ctx"]["httpServletRequest"] = this.thExpressionObjects["#httpServletRequest"];
398         this.thExpressionObjects["#ctx"]["httpSession"] = this.thExpressionObjects["#httpSession"];
399         this.protocol = Thymol.prototype.override("thProtocol", this.protocol);
400         this.debug = Thymol.prototype.override("thDebug", this.debug);
401         this.root = Thymol.prototype.override("thRoot", this.root);
402         if ("" !== this.relativeRootPath) {
403             var rootURI = thymol.thDocument.location.href;
404             var quePos = rootURI.indexOf("?");
405             if (quePos >= 0) {
406                 rootURI = rootURI.substring(0, quePos);
407             }
408             var sepPos = rootURI.lastIndexOf("/");
409             if (sepPos >= 0) {
410                 rootURI = rootURI.substring(0, sepPos + 1);
411             }
412             var newThRoot = rootURI + this.thLocation + this.relativeRootPath;
413             this.thRoot = Thymol.prototype.getThParam("thRoot", false, true, newThRoot);
414         }
415         this.path = Thymol.prototype.override("thPath", this.path);
416         this.allowNullText = Thymol.prototype.override("thAllowNullText", this.allowNullText);
417         this.locale.value = Thymol.prototype.override("thLocale", this.locale.value);
418         if (!(typeof thMappings === "undefined")) {
419             this.mappings = [];
420             for (j = 0, jLimit = thMappings.length; j < jLimit; j++) {
421                 this.mappings.push([ thMappings[j][0], thMappings[j][1] ]);
422             }
423             this.mappings.sort(function(a, b) {
424                 return a[0].length > b[0].length ? -1 : 1;
425             });
426         }
427         this.messages = {};
428         setLocaleValue();
429         if (!(typeof thMessages === "undefined")) {
430             this.messages[""] = [];
431             for (j = 0, jLimit = thMessages.length; j < jLimit; j++) {
432                 this.messages[""][thMessages[j][0]] = thMessages[j][1];
433             }
434             for (var k in thMessages) {
435                 if (thMessages.hasOwnProperty(k)) {
436                     if (!k.match(numericExpr)) {
437                         this.messages[k] = [];
438                         for (j = 0, jLimit = thMessages[k].length; j < jLimit; j++) {
439                             this.messages[k][thMessages[k][j][0]] = thMessages[k][j][1];
440                         }
441                     }
442                 }
443             }
444         }
445         if (!(typeof thDisable === "undefined")) {
446             for (j = 0, jLimit = thDisable.length; j < jLimit; j++) {
447                 Thymol.prototype.doDisable(thDisable[j]);
448             }
449         }
450         thymol.thRemove = Thymol.prototype.getThAttrByName("remove");
451     }
452     function getLocations(thiz) {
453         thiz.templateName = "";
454         thiz.templatePath = "";
455         if (!!thymol.thDocument.location.href) {
456             var templateName = templatePath = thymol.thDocument.location.href;
457             thiz.templateName = templateName.substring(0, templateName.indexOf(".") == -1 ? templateName.length : templateName.lastIndexOf("."));
458             thiz.templatePath = templatePath.substring(0, templatePath.indexOf("/") == -1 ? 0 : templatePath.lastIndexOf("/") + 1);
459         }
460     }
461     function getCtx() {
462         return thymol.thExpressionObjects["#ctx"];
463     }
464     function configureModule(module) {
465         if (typeof thymol.thExpressionObjects === "undefined" || thymol.thExpressionObjects === null) {
466             thymol.thExpressionObjects = {};
467         }
468         thymol.thExpressionObjects[module.thExpressionObjectName] = module;
469     }
470     function configureAttributeProcessor(prefix, suffix, func, prec, dataAttr) {
471         var p = prefix + ":";
472         if (p !== null) {
473             if (thymol.thThymeleafPrefixList.indexOf(p) < 0) {
474                 thymol.thThymeleafPrefixList.push(p);
475             }
476         } else {
477             thymol.thUsingNullPrefix = true;
478         }
479         p = new thymol.ThAttr(suffix, func, prec, thymol.thThymeleafPrefixList, prefix, dataAttr);
480     }
481     function configureElementProcessor(prefix, suffix, func) {
482         var p = new thymol.ThElement(suffix, func, prefix);
483     }
484     function configurePreExecution(func) {
485         if (typeof thymol.thPreExecutionFunctions === "undefined" || thymol.thPreExecutionFunctions === null) {
486             thymol.thPreExecutionFunctions = [];
487         }
488         thymol.thPreExecutionFunctions.push(func);
489     }
490     function configurePostExecution(func) {
491         if (typeof thymol.thPostExecutionFunctions === "undefined" || thymol.thPostExecutionFunctions === null) {
492             thymol.thPostExecutionFunctions = [];
493         }
494         thymol.thPostExecutionFunctions.push(func);
495     }
496     function executeDeferred() {
497         if (typeof thymolDeferredFunctions !== "undefined" && thymolDeferredFunctions !== null) {
498             while (thymolDeferredFunctions.length > 0) {
499                 var func = thymolDeferredFunctions.pop();
500                 func();
501             }
502         }
503     }
504     function preExecute(context) {
505         while (thymol.thPreExecutionFunctions.length > 0) {
506             var func = thymol.thPreExecutionFunctions.pop();
507             func();
508             context.resolveJSONReferences();
509         }
510     }
511     function postExecute() {
512         while (thymol.thPostExecutionFunctions.length > 0) {
513             var func = thymol.thPostExecutionFunctions.pop();
514             func();
515         }
516     }
517     function preProcess(expr, element) {
518         var result = expr, fp, lp;
519         do {
520             fp = result.indexOf("__");
521             if (fp >= 0) {
522                 lp = -1;
523                 if (result.length > 4) {
524                     lp = result.lastIndexOf("__");
525                 }
526                 if (lp <= 0) {
527                     throw new thymol.ThError("Mismatched pre-processing indicators", element);
528                 }
529                 var head = result.substring(0, fp);
530                 var centre = result.substring(fp + 2, lp);
531                 centre = this.getParsedExpr(centre, element);
532                 var tail = result.substring(lp + 2);
533                 result = head + centre + tail;
534                 fp = result.indexOf("__");
535             }
536         } while (fp >= 0);
537         result = result.replace(/\\_\\_/g, "__");
538         return result;
539     }
540     function substituteParam(argValue, mode, element) {
541         var result = argValue, varName = argValue, subs = null, msg, expo;
542         if (result) {
543             if (mode === 4) {
544                 msg = thymol.getMessage(varName);
545                 if (msg) {
546                     subs = msg;
547                 }
548             } else if (mode === 6) {
549                 subs = argValue;
550             } else {
551                 var token = thymol.booleanAndNullTokens[result];
552                 if (!(typeof token === "undefined")) {
553                     if (token === null) {
554                         subs = null;
555                     } else {
556                         subs = token.value;
557                     }
558                 } else {
559                     if (varName.charAt(0) === "#") {
560                         if ("#object" === varName) {
561                             if (element.thObjectVar) {
562                                 subs = element.thObjectVar;
563                             }
564                         } else {
565                             expo = thymol.thExpressionObjects[varName];
566                             if (typeof expo !== "undefined" && expo !== null) {
567                                 subs = expo;
568                             }
569                         }
570                     }
571                     if ((typeof subs === "undefined" || subs == null) && element.thObjectVar) {
572                         subs = element.thObjectVar[varName];
573                     }
574                     if ((typeof subs === "undefined" || subs == null) && element.thLocalVars) {
575                         subs = element.thLocalVars[varName];
576                     }
577                     if (typeof subs === "undefined" || subs == null) {
578                         subs = thymol.ThUtils.getParameter(varName);
579                     }
580                     if (typeof subs === "undefined" || subs == null) {
581                         if ("param" === varName) {
582                             subs = thymol.requestContext;
583                         }
584                         if ("session" === varName) {
585                             subs = thymol.sessionContext;
586                         }
587                         if ("application" === varName) {
588                             subs = thymol.applicationContext;
589                         }
590                     }
591                     if (mode === 2 && (typeof subs === "undefined" || subs == null)) {
592                         subs = argValue;
593                     }
594                 }
595             }
596             result = subs;
597             if (subs instanceof thymol.ThParam) {
598                 result = subs.value;
599             }
600         }
601         return result;
602     }
603     function getStandardURL(initial) {
604         var result = initial.trim(), mapped, head;
605         mapped = thymol.getMapped(result, thymol.extendedMapping);
606         if (mapped) {
607             result = mapped;
608         }
609         if ("/" === result && !!thymol.indexFile) {
610             result += thymol.indexFile;
611         }
612         if (!/.*:\/\/.*/.test(result)) {
613             if (/^~?\/.*$/.test(result)) {
614                 if (/^~.*$/.test(result)) {
615                     result = result.substring(1);
616                 }
617                 if (!/^\/\/.*$/.test(result)) {
618                     if (thymol.useFullURLPath) {
619                         head = thymol.root + thymol.resourcePath;
620                         if (head != "") {
621                             if (head.charAt(head.length - 1) !== "/") {
622                                 head = head + "/";
623                             }
624                             if (result.charAt(0) === "/") {
625                                 result = head + result.substring(1);
626                             } else {
627                                 result = head + result;
628                             }
629                         }
630                     } else {
631                         result = thymol.resourcePath + result;
632                     }
633                 }
634             }
635         }
636         return result;
637     }
638     function getExpression(argValue, element) {
639         var result = argValue, subst = false, initial, shortCut, args, negate, token, lsp;
640         if (typeof argValue === "string") {
641             initial = argValue.trim();
642             result = initial;
643             if (result) {
644                 shortCut = thymol.ThUtils.getParameter(result);
645                 if (!shortCut) {
646                     args = result.match(varExpr3);
647                     if (args) {
648                         if (args[1] && args[1].length > 0) {
649                             shortCut = thymol.ThUtils.getParameter(args[1]);
650                         }
651                     }
652                 }
653                 if (shortCut) {
654                     if (shortCut instanceof thymol.ThParam) {
655                         result = shortCut.value;
656                     } else {
657                         result = shortCut;
658                     }
659                     if (typeof result === "string" && result.match(numericExpr)) {
660                         result = parseInt(result);
661                     }
662                 } else {
663                     initial = thymol.ThUtils.unParenthesise(result);
664                     negate = false;
665                     if (initial.charAt(0) == "!") {
666                         negate = true;
667                         initial = initial.substring(1, initial.length);
668                         initial = thymol.ThUtils.unParenthesise(initial);
669                     }
670                     if (literalTokenExpr.test(initial)) {
671                         token = thymol.booleanAndNullTokens[initial];
672                         if (!(typeof token === "undefined")) {
673                             result = token.value;
674                             subst = true;
675                         }
676                     }
677                     lsp = null;
678                     if (!subst) {
679                         lsp = initial.match(litSubstExpr);
680                         if (lsp && lsp.length > 0) {
681                             if (thymol.ThUtils.charOcurrences(lsp[1], "'") < 2) {
682                                 initial = Thymol.prototype.doLiteralSubstExpr(initial, lsp[1]);
683                             }
684                         }
685                         result = "";
686                         if (initial != "") {
687                             initial = thymol.ThUtils.unParenthesise(initial);
688                             initial = thymol.preProcess(initial, element);
689                             result = thymol.getParsedExpr(initial, element, true);
690                         }
691                     }
692                     if (result == initial && typeof result == typeof initial) {
693                         result = null;
694                     } else if (typeof result === "string") {
695                         if (!lsp) {
696                             result = result.replace(/[\\][\\]/g, "\\");
697                         }
698                         result = result.replace(/&#39;/g, "'").replace(/&apos;/gi, "'");
699                     }
700                     if (negate) {
701                         if (typeof result === "boolean") {
702                             result = !result;
703                         } else if (typeof result === "number") {
704                             result = result == 0;
705                         } else if (typeof result === "string") {
706                             result = !thymol.ThUtils.testLiteralFalse(result);
707                         }
708                     }
709                 }
710             }
711         }
712         return result;
713     }
714     function getMapped(uri, extended) {
715         var mapped = null, i, iLimit, key;
716         if (uri && typeof uri === "string") {
717             if (thymol.mappings) {
718                 for (i = 0, iLimit = thymol.mappings.length; i < iLimit; i++) {
719                     key = thymol.mappings[i][0];
720                     if (uri == key) {
721                         mapped = thymol.mappings[i][1];
722                         break;
723                     } else if (extended) {
724                         if (uri.indexOf(key) == 0) {
725                             mapped = uri.substring(key.length);
726                             mapped = thymol.mappings[i][1] + mapped;
727                             break;
728                         }
729                     }
730                 }
731             }
732         }
733         return mapped;
734     }
735     function substitute(initial, element, lenient) {
736         var argValue = initial, result, args, token, re, subs, saved;
737         if (typeof argValue === "string") {
738             argValue = argValue.trim();
739         }
740         result = argValue;
741         args = "";
742         while (args != null) {
743             args = argValue.match(/.*([$\*#@]{(!?[^}]*)}).*/);
744             if (args != null && args.length > 0) {
745                 if (args.length == 3) {
746                     token = args[1];
747                     token = token.replace(/[$]/g, "[$]").replace(/[*]/g, "[*]").replace(/[\']/g, "[']").replace(/[+]/g, "[+]").replace(/[\(]/g, "[(]").replace(/[\)]/g, "[)]");
748                     re = new RegExp(token);
749                     subs = this.getExpression(args[2], element);
750                     if (subs != args[2]) {
751                         result = result.replace(re, subs, "g");
752                         if (result == "null") {
753                             result = null;
754                         }
755                     } else {
756                         subs = "";
757                         if (thymol.debug && !lenient) {
758                             thymol.thWindow.alert('thymol variable substitution failed: "' + initial + '"');
759                         }
760                     }
761                     saved = argValue;
762                     argValue = argValue.replace(re, subs, "g");
763                     if (saved == argValue) {
764                         argValue = "";
765                     }
766                 }
767             }
768         }
769         return result;
770     }
771     function getWith(element, content) {
772         var argValue = content.trim(), argCount = 0;
773         if (argValue) {
774             do {
775                 var argsExpr = thymol.ThParser.parse(argValue, true, false);
776                 var identifier = argsExpr.tokens.shift();
777                 if (identifier.type_ === 3) {
778                     var result = argsExpr.evaluate(element);
779                     var varName = identifier.index_;
780                     if (!!varName) {
781                         argCount++;
782                         if (!element.thLocalVars) {
783                             element.thLocalVars = {};
784                         }
785                         element.thLocalVars[varName] = result;
786                     }
787                     argValue = argValue.substring(argsExpr.position);
788                 } else {
789                     break;
790                 }
791             } while (argValue.length > 0);
792         }
793         return argCount;
794     }
795     function getParsedExpr(initial, element, preprocessed) {
796         var expr, result = initial;
797         expr = thymol.ThParser.parse(result, false, preprocessed);
798         expr = expr.simplify();
799         result = expr.evaluate(element);
800         if (typeof result === "number") {
801             result = thymol.ThUtils.getToPrecision(result, expr.precision);
802         }
803         return result;
804     }
805     function getBooleanValue(param) {
806         var flag = false, val, args;
807         if (param != null) {
808             if (typeof param === "boolean") {
809                 flag = param;
810             } else if (typeof param === "number") {
811                 flag = param != 0;
812             } else {
813                 val = param;
814                 if (Object.prototype.toString.call(val) === "[object Array]") {
815                     if (val.length === 1) {
816                         val = val[0];
817                     } else {
818                         val = true;
819                     }
820                 }
821                 if (typeof val === "boolean") {
822                     flag = val;
823                 } else if (typeof val === "number") {
824                     flag = val != 0;
825                 } else if (typeof val === "string") {
826                     args = val.match(nonURLExpr);
827                     if (args) {
828                         val = args[1];
829                         flag = this.testParam(val);
830                     } else {
831                         flag = !thymol.ThUtils.testLiteralFalse(val);
832                     }
833                 } else if (val instanceof thymol.ThParam) {
834                     flag = val.getBooleanValue();
835                 } else {
836                     flag = typeof val !== "undefined" && val !== null;
837                 }
838             }
839         }
840         return flag;
841     }
842     function isFragmentChild(element) {
843         var result = false, parent = element.parentElement;
844         while (parent) {
845             if (parent.getAttribute(thymol.thFragment.name) || parent.getAttribute(thymol.thFragment.synonym)) {
846                 result = true;
847                 break;
848             }
849             parent = parent.parentElement;
850         }
851         return result;
852     }
853     function setLocale(locValue) {
854         thymol.locale.value = locValue;
855         setLocaleValue();
856     }
857     function getLocale() {
858         return thymol.locale.value;
859     }
860     function getLanguage() {
861         if (!thymol.locale.value) {
862             if (typeof navigator !== "undefined" && !!navigator) {
863                 var userLang = navigator.language || navigator.userLanguage || navigator.browserLanguage || navigator.systemLanguage;
864                 if (!!userLang) {
865                     thymol.locale.value = userLang.replace(/\-/g, "_");
866                 }
867             }
868         }
869     }
870     function setLocaleValue() {
871         if (!thymol.locale.value) {
872             thymol.locale.value = thymol.thDefaultLocale;
873         }
874         var sepPos;
875         var locale = thymol.locale.value.replace(/\-/g, "_");
876         var level = thymol.locale.value;
877         var levels = [];
878         var part, parts = [];
879         do {
880             levels.push(level);
881             sepPos = locale.lastIndexOf("_");
882             if (sepPos >= 0) {
883                 part = locale.substring(sepPos + 1);
884                 parts.push(part);
885                 locale = locale.substring(0, sepPos);
886                 level = level.substring(0, sepPos);
887             }
888         } while (sepPos >= 0);
889         thymol.locale.language = level;
890         if (!!parts) {
891             parts.reverse();
892             for (var i = 0, iLimit = parts.length; i < iLimit; i++) {
893                 if (i === 0) {
894                     thymol.locale.country = parts[i];
895                 } else if (i === 1) {
896                     thymol.locale.variant = parts[i];
897                 }
898             }
899         }
900         thymol.locale.levels = levels;
901         thymol.thExpressionObjects["#ctx"]["locale"] = thymol.locale;
902         thymol.thExpressionObjects["#locale"] = thymol.locale;
903     }
904     function getMessage(varName, parameters, returnStringAlways) {
905         if (thymol.disableMessages) {
906             return undefined;
907         }
908         var msgKey = null;
909         var locale;
910         if (!!thymol.locale.levels) {
911             var prefix = "$";
912             var ident, section, jLower = thymol.localMessages ? 0 : 1;
913             for (var j = jLower; j < 2; j++) {
914                 for (var i = 0, iLimit = thymol.locale.levels.length; i < iLimit + 1; i++) {
915                     ident = prefix;
916                     if (i < iLimit) {
917                         locale = thymol.locale.levels[i];
918                     } else {
919                         locale = "";
920                     }
921                     ident = ident + locale;
922                     section = thymol.messages[ident];
923                     if (!section) {
924                         if (j < 1) {
925                             section = getLocalMessages(locale);
926                         } else {
927                             section = getDefaultMessages(locale);
928                         }
929                     }
930                     if (!!section) {
931                         thymol.messages[ident] = section;
932                         msgKey = section[varName];
933                         if (!!msgKey) {
934                             break;
935                         }
936                     }
937                 }
938                 if (!!msgKey) {
939                     break;
940                 }
941                 prefix += "$";
942             }
943         }
944         if (!msgKey) {
945             for (var i = 0, iLimit = thymol.locale.levels.length; i <= iLimit; i++) {
946                 if (i < iLimit) {
947                     locale = thymol.locale.levels[i];
948                 } else {
949                     locale = "";
950                 }
951                 if (!!thymol.messages[locale]) {
952                     msgKey = thymol.messages[locale][varName];
953                     if (!!msgKey) {
954                         break;
955                     }
956                 }
957             }
958         }
959         if (!!msgKey) {
960             if (typeof parameters === "undefined") {
961                 return msgKey;
962             } else {
963                 return thymol.ThUtils.renderMessage(msgKey, parameters);
964             }
965         } else if (returnStringAlways !== undefined && returnStringAlways) {
966             return "??" + varName + "_" + thymol.locale.value + "??";
967         }
968         return null;
969     }
970     function getProperties(propFile) {
971         var props = null;
972         var messages = [];
973         $.get(propFile, function(textContent, status) {
974             var err = null;
975             try {
976                 if ("success" == status) {
977                     props = textContent;
978                 } else if (thymol.debug) {
979                     thymol.thWindow.alert("read failed: " + propFile);
980                 }
981             } catch (err) {
982                 if (thymol.debug) {
983                     thymol.thWindow.alert("properties file read failed: " + propFile + " error: " + err);
984                 }
985             }
986         }, "text");
987         if (props !== null) {
988             var splits = props.split("\n");
989             if (splits.length > 0) {
990                 for (var i = 0, iLimit = splits.length; i < iLimit; i++) {
991                     var line = splits[i].trim();
992                     if (line.charAt(0) !== "#") {
993                         var p = line.split("=");
994                         if (p.length > 1) {
995                             messages[p[0].trim()] = thymol.ThUtils.unicodeUnescape(p[1].trim());
996                         }
997                     }
998                 }
999             }
1000         }
1001         return messages;
1002     }
1003     function getLocalMessages(locale) {
1004         var messages = [];
1005         if (!!thymol.thDocument.location.href) {
1006             var propsFile = thymol.templateName;
1007             if (!!locale && locale !== "") {
1008                 propsFile += "_" + locale;
1009             }
1010             propsFile += ".properties";
1011             messages = getProperties(propsFile);
1012         }
1013         return messages;
1014     }
1015     function getDefaultMessages(locale) {
1016         var messages = null;
1017         var propsPath = "";
1018         if (thymol.useAbsolutePath) {
1019             propsPath += thymol.protocol + thymol.root + thymol.path;
1020         }
1021         propsPath += thymol.messagePath;
1022         if (propsPath !== "") {
1023             propsPath += "/";
1024         }
1025         var propsFile = propsPath + thymol.messagesBaseName;
1026         if (!!locale && locale !== "") {
1027             propsFile += "_" + locale;
1028         }
1029         propsFile += ".properties";
1030         messages = getProperties(propsFile);
1031         return messages;
1032     }
1033     Thymol.prototype = {
1034         process: function(rootNode) {
1035             var n = rootNode;
1036             try {
1037                 while (n.thDoc) {
1038                     this.getChildren(n);
1039                     if (n.firstChild && n.firstChild.thDoc && !n.visited) {
1040                         n.visited = true;
1041                         n = n.firstChild;
1042                     } else {
1043                         if (n.element != n.thDoc) {
1044                             this.doReplace(n.isNode, n.element, n.thDoc);
1045                             if (!n.isNode) {
1046                                 n.thDoc = n.element;
1047                             }
1048                         }
1049                         if (n.nextSibling && n.nextSibling.thDoc) {
1050                             n = n.nextSibling;
1051                         } else {
1052                             if (n == rootNode) {
1053                                 break;
1054                             }
1055                             n = n.parentDoc;
1056                         }
1057                     }
1058                 }
1059                 this.processChildren(rootNode);
1060             } catch (err) {
1061                 if (thymol.debug) {
1062                     if (err instanceof thymol.ThError) {
1063                         if (!err.suppress) {
1064                             thymol.thWindow.alert(err);
1065                         }
1066                     } else {
1067                         thymol.thWindow.alert(err);
1068                     }
1069                 }
1070             }
1071         },
1072         getChildren: function(rootNode) {
1073             var count = 0, last = null, changed = false, child, froot, fstar, fchildren, i, iLimit, j, jLimit, element, matches, theAttr;
1074             if (!rootNode.visited) {
1075                 this.processComments(rootNode);
1076                 var rnd = this.getContentRoot(rootNode);
1077                 froot = $(rnd);
1078                 fstar = $(froot).add(froot.find("*"));
1079                 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));
1080                 for (i = 0, iLimit = fchildren.length; i < iLimit; i++) {
1081                     element = fchildren[i], matches = [];
1082                     for (j = 0, jLimit = element.attributes.length; j < jLimit; j++) {
1083                         theAttr = element.attributes[j];
1084                         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) {
1085                             matches.push(theAttr);
1086                         }
1087                     }
1088                     for (j = 0, jLimit = matches.length; j < jLimit; j++) {
1089                         child = this.processImport(element, rootNode, matches[j]);
1090                         if (child != null) {
1091                             changed = true;
1092                             if (count == 0) {
1093                                 rootNode.firstChild = child;
1094                             } else {
1095                                 last.nextSibling = child;
1096                             }
1097                             last = child;
1098                             count++;
1099                         }
1100                     }
1101                 }
1102             }
1103             return changed;
1104         },
1105         processChildren: function(rootNode) {
1106             var i, iLimit, j, jLimit, k, kLimit;
1107             var elements = rootNode.thDoc.getElementsByTagName("*");
1108             for (k = 0, kLimit = elements.length; k < kLimit; k++) {
1109                 var element = elements[k];
1110                 for (j = 0, jLimit = thymol.thThymeleafElementsList.length; j < jLimit; j++) {
1111                     if (element.localName == thymol.thThymeleafElementsList[j].name || element.localName == thymol.thThymeleafElementsList[j].synonym) {
1112                         var updated = thymol.thThymeleafElementsList[j].process(element);
1113                         if (updated) {
1114                             elements = rootNode.thDoc.getElementsByTagName("*");
1115                             k--;
1116                             kLimit = elements.length;
1117                         }
1118                         break;
1119                     }
1120                 }
1121                 var allAttributes = element.attributes;
1122                 if (allAttributes && allAttributes.length > 0) {
1123                     var attributes = [], aii = 0;
1124                     if (!thymol.thUsingNullPrefix) {
1125                         for (i = 0, iLimit = allAttributes.length; i < iLimit; i++) {
1126                             var ai = allAttributes[i];
1127                             if (ai) {
1128                                 for (j = 0, jLimit = thymol.thThymeleafPrefixList.length; j < jLimit; j++) {
1129                                     var attrName = ai.name.toString();
1130                                     if (attrName.length > thymol.thThymeleafPrefixList[j].length) {
1131                                         attrName = attrName.substring(0, thymol.thThymeleafPrefixList[j].length);
1132                                         if (attrName === thymol.thThymeleafPrefixList[j]) {
1133                                             ai.order = i;
1134                                             attributes[aii++] = ai;
1135                                         }
1136                                     }
1137                                 }
1138                             }
1139                         }
1140                     } else {
1141                         attributes = allAttributes;
1142                     }
1143                     if (attributes.length > 0) {
1144                         attributes.sort(function(a, b) {
1145                             return b.order - a.order;
1146                         });
1147                         var matchedAttributes = [];
1148                         for (i = 0, iLimit = attributes.length; i < iLimit; i++) {
1149                             var splits = attributes[i].name.toString().split(":");
1150                             if (splits && splits.length > 0) {
1151                                 var prefix = "", name;
1152                                 if (splits.length > 1) {
1153                                     prefix = splits[0];
1154                                     name = splits[1];
1155                                 } else {
1156                                     name = splits[0];
1157                                     var hpos = name.lastIndexOf("-");
1158                                     if (hpos >= 0) {
1159                                         prefix = name.substring(0, hpos + 1);
1160                                     }
1161                                 }
1162                                 var attrList = thymol.thThymeleafPrefixList[prefix];
1163                                 if (splits.length > 1) {
1164                                     prefix += ":";
1165                                 }
1166                                 if (attrList) {
1167                                     for (j = 0, jLimit = attrList.length; j < jLimit; j++) {
1168                                         var matched = false;
1169                                         if (name === attrList[j].suffix || name === attrList[j].synonym) {
1170                                             matched = true;
1171                                         } else if (attrList[j].regex !== null) {
1172                                             var fqn = prefix + name;
1173                                             matched = attrList[j].regex.test(fqn);
1174                                         }
1175                                         if (matched) {
1176                                             var matchedAttribute = {};
1177                                             matchedAttribute.attr = attrList[j];
1178                                             matchedAttribute.elementAttr = attributes[i];
1179                                             matchedAttributes.push(matchedAttribute);
1180                                             break;
1181                                         }
1182                                     }
1183                                 }
1184                             }
1185                         }
1186                         if (matchedAttributes.length > 0) {
1187                             matchedAttributes.sort(function(a, b) {
1188                                 return a.attr.precedence - b.attr.precedence;
1189                             });
1190                             var updated = false;
1191                             for (i = 0, iLimit = matchedAttributes.length; i < iLimit; i++) {
1192                                 var exp = thymol.ThUtils.processElement(matchedAttributes[i].attr.process, element, matchedAttributes[i].elementAttr, matchedAttributes[i].attr, 1);
1193                                 updated = exp || updated;
1194                             }
1195                             if (updated) {
1196                                 elements = rootNode.thDoc.getElementsByTagName("*");
1197                                 k--;
1198                                 kLimit = elements.length;
1199                             }
1200                         }
1201                     }
1202                 }
1203             }
1204             elements = rootNode.thDoc.getElementsByTagName("*");
1205             var kc = 0;
1206             for (k = 0, kLimit = elements.length; k < kLimit; k++) {
1207                 var element = elements[kc];
1208                 var elName = element.nodeName.toLowerCase();
1209                 if (elName == thymol.thBlock.name || elName == thymol.thBlock.synonym) {
1210                     thymol.ThUtils.removeTag(element);
1211                     elements = rootNode.thDoc.getElementsByTagName("*");
1212                 } else {
1213                     kc++;
1214                 }
1215             }
1216         },
1217         override: function(paramName, paramValue) {
1218             var param = paramValue, thv;
1219             thv = thymol.thWindow[paramName];
1220             if (typeof thv === "undefined") {
1221                 thv = thymol.applicationContext.javascriptify(paramName);
1222             }
1223             if (thv) {
1224                 if (thv instanceof thymol.ThParam) {
1225                     param = thv.value;
1226                 } else {
1227                     param = thv;
1228                 }
1229             }
1230             thv = thymol.applicationContext[paramName];
1231             if (thv) {
1232                 if (thv instanceof thymol.ThParam) {
1233                     param = thv.value;
1234                 } else {
1235                     param = thv;
1236                 }
1237             }
1238             thv = thymol.requestContext[paramName];
1239             if (thv) {
1240                 if (thv instanceof thymol.ThParam) {
1241                     param = thv.value;
1242                 } else {
1243                     param = thv;
1244                 }
1245             }
1246             return param;
1247         },
1248         doDisable: function(attrName) {
1249             var tha = this.getThAttrByName(attrName);
1250             if (tha !== null) {
1251                 tha.disable();
1252             } else {
1253                 if (thymol.debug) {
1254                     thymol.thWindow.alert('cannot disable unknown attribute "' + attrName + '"');
1255                 }
1256             }
1257         },
1258         getThAttrByName: function(name) {
1259             var attrList = thymol.thThymeleafPrefixList[thymol.prefix];
1260             attrList.push(thymol.thInclude);
1261             attrList.push(thymol.thReplace);
1262             attrList.push(thymol.thSubstituteby);
1263             attrList.push(thymol.thFragment);
1264             var i, iLimit = attrList.length;
1265             for (i = 0; i < iLimit; i++) {
1266                 if (name === attrList[i].suffix) {
1267                     return attrList[i];
1268                 }
1269             }
1270             return null;
1271         },
1272         getContents: function(rootNode) {
1273             var rnd = this.getContentRoot(rootNode);
1274             var froot = $(rnd);
1275             var fstar = froot.find("*");
1276             return fstar;
1277         },
1278         getContentRoot: function(rn) {
1279             var rnd = rn.thDoc;
1280             if (rnd.nodeName !== "#document") {
1281                 rnd = rnd.childNodes;
1282             }
1283             return rnd;
1284         },
1285         processComments: function(rootNode) {
1286             var comments = null, fstar, changed, i, iLimit, startComment, parent, startValue, pointer, nextPointer;
1287             do {
1288                 fstar = this.getContents(rootNode);
1289                 comments = fstar.contents().getComments();
1290                 changed = false;
1291                 for (i = 0, iLimit = comments.length; i < iLimit; i++) {
1292                     startComment = comments[i];
1293                     parent = startComment.parentNode;
1294                     startValue = startComment.nodeValue.trim();
1295                     if (startParserLevelCommentExpr.test(startValue)) {
1296                         pointer = startComment;
1297                         while (pointer != null) {
1298                             if (endParserLevelCommentExpr.test(pointer.nodeValue)) {
1299                                 changed = parent.removeChild(pointer) != null;
1300                                 break;
1301                             }
1302                             nextPointer = pointer.nextSibling;
1303                             changed = parent.removeChild(pointer) != null;
1304                             pointer = nextPointer;
1305                         }
1306                     } else if (startParserLevelCommentExpr2.test(startValue) && endParserLevelCommentExpr2.test(startValue)) {
1307                         parent.removeChild(startComment);
1308                         changed = true;
1309                     }
1310                 }
1311             } while (changed);
1312             this.processPrototypeOnlyComments(rootNode);
1313         },
1314         processPrototypeOnlyComments: function(rootNode) {
1315             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;
1316             do {
1317                 fstar = this.getContents(rootNode);
1318                 comments = fstar.contents().getComments();
1319                 changed = false;
1320                 indexOfLast = comments.length - 1;
1321                 for (i = 0, iLimit = comments.length; i < iLimit; i++) {
1322                     startComment = comments[i];
1323                     parent = startComment.parentNode;
1324                     if (parent != null) {
1325                         startValue = startComment.nodeValue.trim();
1326                         deletions = [];
1327                         deletions.push(startComment);
1328                         startValue = startValue.replace(/\n/g, "");
1329                         res = startValue.match(prototypeOnlyCommentEscpExpr);
1330                         if (res) {
1331                             fullText = startValue;
1332                             if (parent.localName == "table" || parent.localName == "tbody") {
1333                                 if (startValue.indexOf(thymol.thBlock.name) >= 0 || startValue.indexOf(thymol.thBlock.synonym) >= 0) {
1334                                     if (startValue.indexOf(thymol.thBlock.endName) < 0 || startValue.indexOf(thymol.thBlock.endSynonym) < 0) {
1335                                         fullText = fullText.replace(res[0], res[1]);
1336                                         innerNodes = [];
1337                                         done = false;
1338                                         next = startComment;
1339                                         do {
1340                                             next = next.nextSibling;
1341                                             if (next != null) {
1342                                                 deletions.push(next);
1343                                                 if (i < indexOfLast) {
1344                                                     if (next == comments[i + 1]) {
1345                                                         commentText = next.nodeValue;
1346                                                         if (commentText.indexOf(thymol.thBlock.endName) >= 0 || commentText.indexOf(thymol.thBlock.endSynonym) >= 0) {
1347                                                             res2 = commentText.match(prototypeOnlyCommentEscpExpr);
1348                                                             if (res2) {
1349                                                                 commentText = commentText.replace(res2[0], res2[1]);
1350                                                                 fullText = fullText + commentText;
1351                                                             }
1352                                                             done = true;
1353                                                         }
1354                                                     } else {
1355                                                         innerNodes.push(next);
1356                                                     }
1357                                                 }
1358                                             } else {
1359                                                 done = true;
1360                                             }
1361                                         } while (!done);
1362                                         blockElement = null;
1363                                         blockDoc = new thymol.thDomParser().parseFromString(fullText, "text/html");
1364                                         blockDocBody = $(blockDoc).find("body")[0];
1365                                         for (j = 0, jLimit = blockDocBody.childNodes.length; j < jLimit; j++) {
1366                                             if (blockDocBody.childNodes[j].localName == thymol.thBlock.name || blockDocBody.childNodes[j].localName == thymol.thBlock.synonym) {
1367                                                 blockElement = blockDocBody.childNodes[j];
1368                                                 for (k = 0, kLimit = innerNodes.length; k < kLimit; k++) {
1369                                                     newNode = blockDoc.importNode(innerNodes[k], true);
1370                                                     blockElement.appendChild(newNode);
1371                                                 }
1372                                             }
1373                                         }
1374                                         if (blockElement != null) {
1375                                             blockBase = new ThNode(blockDoc, false, null, null, null, blockDoc.nodeName, "::", false, blockDoc);
1376                                             this.processChildren(blockBase);
1377                                             changed = this.insertUncommented(blockBase.thDoc, deletions, parent);
1378                                         } else {
1379                                             parent.removeChild(startComment);
1380                                             changed = true;
1381                                         }
1382                                     } else {
1383                                         parent.removeChild(startComment);
1384                                         changed = true;
1385                                     }
1386                                 }
1387                             } else {
1388                                 startValue = startValue.substring(3, startValue.length - 3);
1389                                 newDoc = new thymol.thDomParser().parseFromString(startValue, "text/html");
1390                                 changed = this.insertUncommented(newDoc, deletions, parent);
1391                             }
1392                         }
1393                     }
1394                 }
1395             } while (changed);
1396         },
1397         insertUncommented: function(doc, deletions, parent) {
1398             var docBody = $(doc).find("body")[0], i, iLimit, newNode;
1399             for (i = 0, iLimit = docBody.childNodes.length; i < iLimit; i++) {
1400                 if (parent.ownerDocument === doc) {
1401                     newNode = docBody.childNodes[i].cloneNode(true);
1402                 } else {
1403                     newNode = parent.ownerDocument.importNode(docBody.childNodes[i], true);
1404                     newNode.parentNode = parent;
1405                 }
1406                 parent.insertBefore(newNode, deletions[0]);
1407             }
1408             for (i = 0, iLimit = deletions.length; i < iLimit; i++) {
1409                 parent.removeChild(deletions[i]);
1410             }
1411             return true;
1412         },
1413         getList: function(element, content) {
1414             var argValue = content.trim(), argsCount = 0, argsList = [], assigs, i, iLimit, val;
1415             if (argValue) {
1416                 assigs = argValue.split(",");
1417                 for (i = 0, iLimit = assigs.length; i < iLimit; i++) {
1418                     val = thymol.getExpression(assigs[i], element);
1419                     argsList[i] = val;
1420                 }
1421                 if (!element.thLocalVars) {
1422                     element.thLocalVars = {};
1423                 }
1424                 element.thLocalVars["..."] = argsList;
1425                 argsCount = argsList.length;
1426             }
1427             return argsCount;
1428         },
1429         testParam: function(param) {
1430             var initial = param, result = false, theParam = null, negate = false;
1431             if (typeof initial === "boolean") {
1432                 result = initial;
1433             } else {
1434                 theParam = null;
1435                 negate = false;
1436                 if (typeof initial === "object" && initial instanceof thymol.ThParam) {
1437                     theParam = initial;
1438                 } else {
1439                     initial = initial.valueOf();
1440                     if (initial.charAt(0) == "!") {
1441                         negate = true;
1442                         initial = initial.substring(1);
1443                     }
1444                 }
1445                 theParam = thymol.applicationContext[initial];
1446                 if (theParam != null) {
1447                     result = theParam.getBooleanValue();
1448                 }
1449                 if (negate) {
1450                     result = !result;
1451                 }
1452             }
1453             return result ? true : false;
1454         },
1455         processImport: function(element, rootNode, attr) {
1456             var importNode = null, filePart, fragmentPart, names, parts, fragmentArgsList, isNode, fragment, fileName, content, importError;
1457             filePart = null;
1458             if (attr.value.indexOf("::") < 0) {
1459                 filePart = attr.value;
1460                 fragmentPart = "::";
1461             } else {
1462                 names = attr.value.split("::");
1463                 filePart = names[0].trim();
1464                 fragmentPart = names[1].trim();
1465             }
1466             if ("this" === filePart) {
1467                 filePart = "";
1468             } else {
1469                 filePart = this.getFilePath(filePart, element);
1470             }
1471             if (filePart != null) {
1472                 parts = filePart.match(varParExpr);
1473                 fragmentArgsList = null;
1474                 if (parts) {
1475                     if (parts.length > 1) {
1476                         filePart = parts[1].trim();
1477                     }
1478                     if (parts.length > 2) {
1479                         fragmentArgsList = parts[2].trim();
1480                     }
1481                 }
1482                 if (filePart != "" || !isFragmentChild(element)) {
1483                     isNode = thymol.thReplace.name == attr.localName || thymol.thReplace.synonym == attr.localName || thymol.thSubstituteby.name == attr.localName || thymol.thSubstituteby.synonym == attr.localName;
1484                     if (thymol.thCache[filePart] != null && thymol.thCache[filePart][fragmentPart] != null) {
1485                         isNode = isNode || fragmentPart == "::";
1486                         importNode = new ThNode(thymol.thCache[filePart][fragmentPart], false, rootNode, null, null, filePart, fragmentPart, isNode, element);
1487                     } else {
1488                         fragment = null;
1489                         importError = null;
1490                         if (filePart != "") {
1491                             fileName = filePart + thymol.templateSuffix;
1492                             $.get(fileName, function(textContent, status) {
1493                                 try {
1494                                     if ("success" == status) {
1495                                         content = new thymol.thDomParser().parseFromString(textContent, "text/html");
1496                                         fragment = Thymol.prototype.getImportNode(element, filePart, fragmentPart, fragmentArgsList, content);
1497                                     } else if (thymol.debug) {
1498                                         thymol.thWindow.alert("thymol.processImport file read failed: " + filePart + " fragment: " + fragmentPart);
1499                                     }
1500                                 } catch (err) {
1501                                     importError = err;
1502                                 }
1503                             }, "text");
1504                         } else {
1505                             fragment = this.getImportNode(element, filePart, fragmentPart, fragmentArgsList, thymol.thDocument);
1506                         }
1507                         if (fragment == null) {
1508                             if (importError !== null) {
1509                                 throw importError;
1510                             }
1511                             if (thymol.debug) {
1512                                 thymol.thWindow.alert("thymol.processImport fragment import failed: " + filePart + " fragment: " + fragmentPart);
1513                             }
1514                         } else {
1515                             importNode = new ThNode(fragment, false, rootNode, null, null, filePart, fragmentPart, isNode, element);
1516                         }
1517                     }
1518                 }
1519             }
1520             element.removeAttribute(attr.name);
1521             return importNode;
1522         },
1523         getImportNode: function(element, filePart, fragmentArg, fragmentArgsList, content) {
1524             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;
1525             fragmentName = fragmentName.replace(/text\(\)/g, textFuncSynonym);
1526             parts = fragmentName.match(varParExpr);
1527             if (parts == null && fragmentArgsList != null) {
1528                 parts = [];
1529                 parts[1] = fragmentName;
1530                 parts[2] = fragmentArgsList;
1531             }
1532             argsCount = 0;
1533             if (parts) {
1534                 if (parts.length > 1) {
1535                     fragmentName = parts[1].trim();
1536                     if (parts.length > 2) {
1537                         if (parts[2].indexOf("=") > 0) {
1538                             argsCount = thymol.getWith(element, parts[2]);
1539                         } else {
1540                             argsCount = this.getList(element, parts[2]);
1541                         }
1542                     }
1543                 }
1544             }
1545             if (thymol.thCache[filePart] == null) {
1546                 thymol.thCache[filePart] = new Object();
1547             }
1548             matched = false;
1549             fragment = null;
1550             if (fragmentName == "::") {
1551                 htmlContent = $("html", content)[0];
1552                 result = htmlContent;
1553                 matched = true;
1554             } else {
1555                 fragArray = $(thymol.thFragment.escpName, content);
1556                 for (i = 0, iLimit = fragArray.length; i < iLimit; i++) {
1557                     fragment = fragArray[i];
1558                     for (j = 0, jLimit = fragment.attributes.length; j < jLimit; j++) {
1559                         clean = fragment.attributes[j];
1560                         clean = clean.value.replace(/\s/g, "");
1561                         bare = null;
1562                         vlParts = clean.match(varParExpr);
1563                         if (vlParts) {
1564                             if (vlParts.length > 1) {
1565                                 bare = vlParts[1].trim();
1566                             }
1567                         }
1568                         if (fragmentName == bare && argsCount > 0) {
1569                             if (vlParts.length > 2) {
1570                                 vlArgs = vlParts[2].trim().split(",");
1571                                 if (vlArgs) {
1572                                     if (vlArgs.length == argsCount) {
1573                                         argsList = element.thLocalVars["..."];
1574                                         if (argsList != null) {
1575                                             for (k = 0; k < argsCount; k++) {
1576                                                 varName = vlArgs[k].trim();
1577                                                 element.thLocalVars[varName] = argsList[k];
1578                                             }
1579                                             element.thLocalVars["..."] = null;
1580                                         }
1581                                         matched = true;
1582                                         break;
1583                                     } else if (vlArgs.length > argsCount) {
1584                                         break;
1585                                     }
1586                                 }
1587                             }
1588                         }
1589                         if (fragmentName == clean || fragmentPart == clean || fragmentName == bare) {
1590                             matched = true;
1591                             break;
1592                         }
1593                     }
1594                     if (matched) {
1595                         result = fragment;
1596                         break;
1597                     }
1598                 }
1599             }
1600             if (!matched) {
1601                 fragment = this.getDOMSelection(fragmentName, content);
1602                 if (fragment) {
1603                     matched = true;
1604                     result = fragment;
1605                 } else {
1606                     if (!element.isBlockChild) {
1607                         throw new thymol.ThError('getImportNode cannot match fragment: "' + fragmentName + '"', element);
1608                     }
1609                 }
1610             }
1611             thymol.thCache[filePart][fragmentPart] = result;
1612             if (matched) {
1613                 newElement = result.cloneNode(true);
1614                 if (newElement.nodeType == 1) {
1615                     newElement.removeAttribute(thymol.thFragment.name);
1616                     newElement.removeAttribute(thymol.thFragment.synonym);
1617                 }
1618                 result = newElement;
1619                 result.thLocalVars = element.thLocalVars;
1620             }
1621             return result;
1622         },
1623         getDOMSelection: function(initial, content) {
1624             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;
1625             if (spec != innr && innr.charAt(innr.length - 1) == "]") {
1626                 spec = innr;
1627             }
1628             while (spec != "") {
1629                 parts = spec.match(domSelectExpr);
1630                 if (parts != null && parts.length > 1) {
1631                     for (i = 1, iLimit = parts.length; i < iLimit; i++) {
1632                         if (parts[i] != null) {
1633                             token = parts[i];
1634                             indx = null;
1635                             innr = thymol.ThUtils.unBracket(token);
1636                             if (token != innr) {
1637                                 if (innr.match(numericExpr)) {
1638                                     indx = innr;
1639                                 }
1640                             }
1641                             saved = spec;
1642                             spec = spec.replace(token, "");
1643                             if (saved == spec) {
1644                                 spec = "";
1645                             }
1646                             if (indx) {
1647                                 token = query[query.length - 1];
1648                                 indxed = new String(token);
1649                                 indxed.indx = indx;
1650                                 query[query.length - 1] = indxed;
1651                             } else {
1652                                 query.push(token.trim());
1653                             }
1654                             break;
1655                         }
1656                     }
1657                 } else {
1658                     break;
1659                 }
1660             }
1661             start = 0;
1662             if (query.length > 0 && query[0] != "" && query[0].charAt(0) == "/") {
1663                 scope = query[0];
1664                 start = 1;
1665             }
1666             selection = [];
1667             selection.push(content);
1668             descend = false;
1669             for (i = start, iLimit = query.length; i < iLimit; i++) {
1670                 subQuery = query[i];
1671                 innr = thymol.ThUtils.unBracket(subQuery);
1672                 if (subQuery != innr) {
1673                     innr = innr.replace(/[']/g, '"');
1674                     subQuery = "";
1675                     exprFrags = innr.split(/\s{1}\s*((?:and)|(?:or))\s{1}\s*/);
1676                     for (j = 0, jLimit = exprFrags.length; j < jLimit; j++) {
1677                         if (exprFrags[j] != "and" && exprFrags[j] != "or") {
1678                             classSpecs = exprFrags[j].match(/[@]?\s*(?:class)\s*(\W?[=])\s*[\"]((?:\w*[\-_]*)*)[\"]/);
1679                             if (classSpecs && classSpecs.length > 0) {
1680                                 if (classSpecs[1] == "=") {
1681                                     subQuery = subQuery + "[class~='" + classSpecs[2] + "']";
1682                                 }
1683                                 if (classSpecs[1] == "^=") {
1684                                     subQuery = subQuery + "[class^='" + classSpecs[2] + "'],[class*=' " + classSpecs[2] + "']";
1685                                 }
1686                             } else {
1687                                 subQuery = subQuery + "[" + exprFrags[j] + "]";
1688                             }
1689                         } else if (exprFrags[j] == "or") {
1690                             subQuery = subQuery + ",";
1691                         }
1692                     }
1693                 }
1694                 qTerms = subQuery.split("/");
1695                 for (j = 0, jLimit = qTerms.length; j < jLimit; j++) {
1696                     if (qTerms[j] != "") {
1697                         qTerms[j] = qTerms[j].replace(/[@]/g, "");
1698                         if (subQuery.indx != null) {
1699                             qTerms[j] = qTerms[j] + ":eq(" + subQuery.indx + ")";
1700                         }
1701                         subSelect = [];
1702                         for (k = 0, kLimit = selection.length; k < kLimit; k++) {
1703                             partial = null;
1704                             if (qTerms[j] == textFuncSynonym) {
1705                                 partial = $(selection[k]).contents().filter(function() {
1706                                     return this.nodeType === 3;
1707                                 });
1708                             } else if (descend) {
1709                                 partial = $(selection[k]).children(qTerms[j]);
1710                             } else if (j == 0) {
1711                                 if (scope == "/") {
1712                                     html = $("html", selection[k]);
1713                                     if (html.length > 0) {
1714                                         selection[k] = html;
1715                                     }
1716                                     partial = $(selection[k]).children("body").children(qTerms[j]);
1717                                     scope = "";
1718                                 } else {
1719                                     if (i == 0 || scope == "//") {
1720                                         partial = $(selection[k]).find(qTerms[j]);
1721                                         scope = "";
1722                                     } else {
1723                                         partial = $(selection[k]).filter(qTerms[j]);
1724                                     }
1725                                 }
1726                             } else {
1727                                 partial = $(selection[k]).children(qTerms[j]);
1728                             }
1729                             if (partial != null) {
1730                                 for (m = 0, mLimit = partial.length; m < mLimit; m++) {
1731                                     subSelect.push(partial[m]);
1732                                 }
1733                             }
1734                         }
1735                         selection = subSelect;
1736                     }
1737                 }
1738                 descend = qTerms[qTerms.length - 1] == "";
1739             }
1740             result = selection;
1741             if (result != null && !(result.length === undefined)) {
1742                 if (result.length > 1) {
1743                     newNode = thymol.thDocument.createDocumentFragment();
1744                     for (i = 0, iLimit = result.length; i < iLimit; i++) {
1745                         var newChild = thymol.thDocument.importNode(result[i], true);
1746                         newNode.appendChild(newChild);
1747                     }
1748                     result = newNode;
1749                 } else {
1750                     result = result[0];
1751                 }
1752             }
1753             return result;
1754         },
1755         getFilePath: function(part, element) {
1756             var result = thymol.substitute(part, element), mapped = null, slashpos;
1757             if (result) {
1758                 if (thymol.mappings) {
1759                     mapped = thymol.getMapped(result, false);
1760                 }
1761             }
1762             if (mapped) {
1763                 result = mapped;
1764             } else {
1765                 var dotFirst = result.charAt(0) === ".";
1766                 if (result && (thymol.useAbsolutePath || !dotFirst)) {
1767                     slashpos = result.indexOf("/");
1768                     if (thymol.useAbsolutePath || slashpos >= 0) {
1769                         if (slashpos == 0 && !thymol.useAbsolutePath) {
1770                             result = result.substring(1);
1771                         }
1772                         var proto = "";
1773                         if (thymol.useAbsolutePath) {
1774                             proto = thymol.protocol;
1775                         }
1776                         if (thymol.useAbsolutePath && !!thymol.absolutePath) {
1777                             result = proto + thymol.absolutePath + result;
1778                         } else {
1779                             if (dotFirst) {
1780                                 result = thymol.templatePath + result;
1781                             } else {
1782                                 result = proto + thymol.root + thymol.path + result;
1783                             }
1784                         }
1785                     }
1786                 }
1787             }
1788             return result;
1789         },
1790         doLiteralSubstExpr: function(param, primary) {
1791             var result = param.trim(), term, subst, lsp;
1792             if (thymol.ThUtils.isLiteralSubst(result)) {
1793                 result = this.decodeLiteralSubst(result);
1794             } else {
1795                 term = primary;
1796                 while (term != null) {
1797                     if (thymol.ThUtils.isLiteralSubst(term)) {
1798                         subst = this.decodeLiteralSubst(term);
1799                         result = result.replace(term, subst);
1800                         lsp = result.match(litSubstExpr);
1801                         if (lsp && lsp.length > 0) {
1802                             term = lsp[1];
1803                         } else {
1804                             break;
1805                         }
1806                     } else {
1807                         break;
1808                     }
1809                 }
1810             }
1811             return result;
1812         },
1813         decodeLiteralSubst: function(param) {
1814             var result = param, parts, rep, i, iLimit;
1815             result = result.trim();
1816             result = result.substring(1, result.length - 1);
1817             result = result.replace(/[\']/g, "&#39;");
1818             parts = result.split(varRefExpr);
1819             if (parts && parts.length > 0) {
1820                 rep = "";
1821                 for (i = 0, iLimit = parts.length; i < iLimit; i++) {
1822                     if (parts[i] != "") {
1823                         if (!parts[i].match(varRefExpr)) {
1824                             parts[i] = "'" + parts[i] + "'";
1825                         }
1826                         if (rep == "") {
1827                             rep = parts[i];
1828                         } else {
1829                             rep = rep + "+" + parts[i];
1830                         }
1831                     }
1832                 }
1833                 result = rep;
1834             }
1835             return result;
1836         },
1837         doReplace: function(isNode, element, content) {
1838             if (isNode) {
1839                 var parent = element.parentNode;
1840                 if (content.nodeName.toLowerCase() == "html") {
1841                     this.doInsertion(element, content, function(e, n) {
1842                         if (n.nodeType == 1) {
1843                             n.removeAttribute(thymol.thFragment.name);
1844                             n.removeAttribute(thymol.thFragment.synonym);
1845                         }
1846                         e.parentNode.insertBefore(n, e);
1847                     });
1848                     parent.removeChild(element);
1849                 } else {
1850                     var node = this.doClone(content, parent.ownerDocument);
1851                     if (node.nodeType == 1) {
1852                         node.removeAttribute(thymol.thFragment.name);
1853                         node.removeAttribute(thymol.thFragment.synonym);
1854                     }
1855                     parent.replaceChild(node, element);
1856                     node.parentNode = parent;
1857                 }
1858             } else {
1859                 try {
1860                     while (element.firstChild != null) {
1861                         element.removeChild(element.firstChild);
1862                         if (element.firstChild == null) {
1863                             break;
1864                         }
1865                     }
1866                     this.doInsertion(element, content, function(e, n) {
1867                         if (n.nodeType == 1) {
1868                             n.removeAttribute(thymol.thFragment.name);
1869                             n.removeAttribute(thymol.thFragment.synonym);
1870                         }
1871                         e.appendChild(n);
1872                     });
1873                 } catch (err) {
1874                     element.innerHTML = content.innerHTML;
1875                 }
1876             }
1877         },
1878         doClone: function(old, targetDoc) {
1879             var node, cNodes, i, iNode, aNode;
1880             if (!!old.parentNode && old.parentNode.ownerDocument === targetDoc) {
1881                 node = old.cloneNode(false);
1882             } else {
1883                 node = targetDoc.importNode(old, false);
1884             }
1885             if (node !== null) {
1886                 if (node.nodeType == 1) {
1887                     if (old.thLocalVars !== null) {
1888                         node.thLocalVars = old.thLocalVars;
1889                     }
1890                 }
1891                 if (old.childNodes !== null) {
1892                     cNodes = old.childNodes.length;
1893                     if (cNodes > 0) {
1894                         for (i = 0; i < cNodes; i++) {
1895                             iNode = old.childNodes[i];
1896                             if (iNode !== null) {
1897                                 aNode = this.doClone(iNode, targetDoc);
1898                                 if (aNode !== null) {
1899                                     node.appendChild(aNode);
1900                                 }
1901                             }
1902                         }
1903                     }
1904                 }
1905             }
1906             return node;
1907         },
1908         doInsertion: function(element, content, func) {
1909             var topLevel = true, parent = element.parentElement, i, iLimit, iNode, elementName, j, jLimit, jNode, cJNode, cINode;
1910             if (parent != null) {
1911                 topLevel = element.parentElement.nodeName.toLowerCase() == "html";
1912             }
1913             for (i = 0, iLimit = content.childNodes.length; i < iLimit; i++) {
1914                 iNode = content.childNodes[i];
1915                 if (iNode) {
1916                     if (!topLevel) {
1917                         elementName = iNode.nodeName.toLowerCase();
1918                         if (elementName != "head") {
1919                             if (elementName == "body") {
1920                                 for (j = 0, jLimit = iNode.childNodes.length; j < jLimit; j++) {
1921                                     jNode = iNode.childNodes[j];
1922                                     if (jNode) {
1923                                         cJNode = this.doClone(jNode, parent.ownerDocument);
1924                                         func(element, cJNode);
1925                                     }
1926                                 }
1927                             } else {
1928                                 cINode = this.doClone(iNode, parent.ownerDocument);
1929                                 func(element, cINode);
1930                             }
1931                         }
1932                     } else {
1933                         cINode = this.doClone(iNode, parent.ownerDocument);
1934                         func(element, cINode);
1935                     }
1936                 }
1937             }
1938         },
1939         getThParam: function(paramName, isBoolean, isPath, defaultValue) {
1940             var localValue = defaultValue, globalValue = thymol.thWindow[paramName], theParam = thymol.ThUtils.getParameter(paramName);
1941             if (typeof globalValue === "undefined") {
1942                 globalValue = thymol.applicationContext.javascriptify(paramName);
1943             }
1944             if (!!theParam) {
1945                 if (theParam instanceof ThParam) {
1946                     if (theParam.globalValue !== globalValue) {
1947                         theParam.globalValue = globalValue;
1948                         theParam.value = globalValue;
1949                         localValue = globalValue;
1950                     }
1951                 }
1952                 if (isBoolean) {
1953                     localValue = theParam.getBooleanValue();
1954                 }
1955             } else {
1956                 if (!(typeof globalValue === "undefined")) {
1957                     if (globalValue != null) {
1958                         if (isBoolean) {
1959                             localValue = globalValue == true;
1960                         } else {
1961                             localValue = globalValue;
1962                         }
1963                     }
1964                 }
1965             }
1966             if (!isBoolean && isPath && localValue.length > 0 && localValue.charAt(localValue.length - 1) != "/") {
1967                 localValue = localValue + "/";
1968             }
1969             thymol.applicationContext.createVariable(paramName, localValue);
1970             return localValue;
1971         }
1972     };
1973     function addDialect(spec) {
1974         var i, iLimit, prec = thymol.thDefaultPrecedence;
1975         if (spec !== null && typeof spec !== "undefined") {
1976             if (spec.attributeProcessors !== null && typeof spec.attributeProcessors !== "undefined") {
1977                 for (i = 0, iLimit = spec.attributeProcessors.length; i < iLimit; i++) {
1978                     if (spec.attributeProcessors[i].precedence !== null && typeof spec.attributeProcessors[i].precedence !== "undefined") {
1979                         prec = spec.attributeProcessors[i].precedence;
1980                     } else {
1981                         prec = thymol.thDefaultPrecedence;
1982                     }
1983                     configureAttributeProcessor(spec.prefix, spec.attributeProcessors[i].name, spec.attributeProcessors[i].processor, prec, null);
1984                 }
1985             }
1986             if (spec.elementProcessors !== null && typeof spec.elementProcessors !== "undefined") {
1987                 for (i = 0, iLimit = spec.elementProcessors.length; i < iLimit; i++) {
1988                     configureElementProcessor(spec.prefix, spec.elementProcessors[i].name, spec.elementProcessors[i].processor);
1989                 }
1990             }
1991             if (spec.objects !== null && typeof spec.objects !== "undefined") {
1992                 for (i = 0, iLimit = spec.objects.length; i < iLimit; i++) {
1993                     if (spec.objects[i].name !== null && typeof spec.objects[i].name !== "undefined") {
1994                         spec.objects[i].object.thExpressionObjectName = spec.objects[i].name;
1995                         configureModule(spec.objects[i].object);
1996                     } else {
1997                         configureModule(spec.objects[i]);
1998                     }
1999                 }
2000             }
2001         }
2002     }
2003     function ThNode(thDocParam, visitedParam, parentDocParam, firstChildParam, nextSiblingParam, fileNameParam, fragNameParam, isNodeParam, elementParam) {
2004         this.thDoc = thDocParam;
2005         this.visited = visitedParam;
2006         this.parentDoc = parentDocParam;
2007         this.firstChild = firstChildParam;
2008         this.nextSibling = nextSiblingParam;
2009         this.fileName = fileNameParam;
2010         this.fragName = fragNameParam;
2011         this.isNode = isNodeParam;
2012         this.element = elementParam;
2013     }
2014     function ThError(message, element, source) {
2015         this.name = "ThError";
2016         this.message = message || "Default Message";
2017         if (element !== null && typeof element !== "undefined" && element.isBlockChild) {
2018             this.suppress = true;
2019         } else {
2020             this.element = element || {};
2021             this.suppress = false;
2022         }
2023         if (!!source) {
2024             if (!!source.stack) {
2025                 this.stack = source.stack;
2026             }
2027         }
2028     }
2029     ThError.prototype = new Error();
2030     ThError.prototype.constructor = ThError;
2031     function ThParam(valueArg) {
2032         this.value = valueArg;
2033         this.globalValue;
2034         this["class"] = new thymol.ThClass("Thymol.ThParam");
2035         this.getBooleanValue = function() {
2036             return !thymol.ThUtils.testLiteralFalse(this.value);
2037         };
2038         this.toString = function() {
2039             return this.value;
2040         };
2041         this.getNumericValue = function() {
2042             return Number(this.value);
2043         };
2044     }
2045     function ThAttr(suffix, func, prec, list, pref, dataAttr) {
2046         var prefix = "", dataPrefix = null, escpPrefix = "";
2047         if (typeof pref !== "undefined" && pref !== null) {
2048             prefix = pref + ":";
2049             if (thymol.thThymeleafPrefixList.indexOf(prefix) < 0) {
2050                 thymol.thThymeleafPrefixList.push(prefix);
2051             }
2052             escpPrefix = pref + "\\:";
2053             if (typeof dataAttr === "undefined" || dataAttr === null) {
2054                 dataPrefix = thymol.dataPrefix + "-" + pref + "-";
2055                 if (thymol.thThymeleafPrefixList.indexOf(dataPrefix) < 0) {
2056                     thymol.thThymeleafPrefixList.push(dataPrefix);
2057                 }
2058             } else {
2059                 dataPrefix = dataAttr;
2060             }
2061         }
2062         this.suffix = suffix;
2063         this.name = prefix + suffix;
2064         this.regex = null;
2065         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) {
2066             if ("*" === suffix) {
2067                 suffix = ".*";
2068             }
2069             suffix = prefix + suffix;
2070             this.regex = new RegExp(suffix);
2071         }
2072         this.escpName = "[" + escpPrefix + suffix + "]";
2073         if (dataPrefix !== null) {
2074             this.synonym = dataPrefix + suffix;
2075             this.escpSynonym = "[" + this.synonym + "]";
2076         } else {
2077             this.synonym = null;
2078             this.escpSynonym = null;
2079         }
2080         if (typeof prec !== "undefined" && prec !== null) {
2081             this.precedence = prec;
2082         } else {
2083             this.precedence = thymol.thDefaultPrecedence;
2084         }
2085         if (!!list) {
2086             var attrList = list[pref];
2087             if (!attrList) {
2088                 attrList = [];
2089                 list[pref] = attrList;
2090                 if (dataPrefix !== null) {
2091                     list[dataPrefix] = attrList;
2092                 }
2093             }
2094             attrList.push(this);
2095         }
2096         this.process = function() {
2097             thymol.thWindow.alert('unsupported processing function for attribute "' + this.name + '"');
2098         };
2099         if (!(typeof func === "undefined")) {
2100             this.process = func;
2101         }
2102         this.disable = function() {
2103             this.name = null;
2104             this.escpName = null;
2105             this.escpSynonym = null;
2106             this.process = function() {};
2107         };
2108     }
2109     function ThElement(suffix, func, pref) {
2110         var tha = new thymol.ThAttr(suffix, null, 0, null, pref);
2111         this.name = tha.name;
2112         this.synonym = tha.synonym;
2113         this.endName = "/" + tha.name;
2114         this.endSynonym = "/" + tha.synonym;
2115         this.process = function() {
2116             thymol.thWindow.alert('unsupported processing function for element "' + this.name + '"');
2117         };
2118         if (!(typeof func === "undefined")) {
2119             this.process = func;
2120         }
2121         this.disable = function() {
2122             this.name = null;
2123             this.synonym = null;
2124             this.endName = null;
2125             this.endSynonym = null;
2126             this.process = null;
2127         };
2128         thymol.thThymeleafElementsList.push(this);
2129     }
2130     function ThSet() {
2131         this.that = this;
2132         this.setSize = 0;
2133         this.isContent = function(k) {
2134             return this.hasOwnProperty(k) && typeof this[k] !== "function" && k !== "that" && k !== "setSize";
2135         };
2136         this.add = function(k) {
2137             var contained = typeof this[k] !== "undefined";
2138             this[k] = k;
2139             if (contained !== (typeof this[k] !== "undefined")) {
2140                 this.setSize++;
2141             }
2142         };
2143         this.addAll = function(other) {
2144             var k = null, value;
2145             for (k in other) {
2146                 if (other.hasOwnProperty(k)) {
2147                     value = other[k];
2148                     if (typeof value !== "function") {
2149                         add(value);
2150                     }
2151                 }
2152             }
2153         };
2154         this.clear = function() {
2155             for (var k in this) {
2156                 if (this.hasOwnProperty(k)) {
2157                     delete this[k];
2158                 }
2159             }
2160             setSize = 0;
2161         };
2162         this.contains = function(k) {
2163             return typeof this[k] !== "undefined";
2164         };
2165         this.containsAll = function(keys) {
2166             var keySet = keys, k = null;
2167             if (typeof keys === "Array" || Object.prototype.toString.call(keys) === "[object Array]") {
2168                 keySet = ThSet.prototype.fromArray(keys);
2169             }
2170             for (k in keySet) {
2171                 if (keySet.hasOwnProperty(k)) {
2172                     if (typeof this[k] === "undefined") {
2173                         return false;
2174                     }
2175                 }
2176             }
2177             return true;
2178         };
2179         this.isEmpty = function() {
2180             return this.setSize === 0;
2181         };
2182         this.size = function() {
2183             return this.setSize;
2184         };
2185         this.remove = function(k) {
2186             var contained = typeof this[k] !== "undefined";
2187             delete this[k];
2188             if (contained !== (typeof this[k] !== "undefined")) {
2189                 this.setSize--;
2190             }
2191         };
2192         this.toArray = function() {
2193             return getArray(this);
2194         };
2195         this.toString = function() {
2196             var array = getArray();
2197             return array.toString();
2198         };
2199         function getArray(obj) {
2200             var array = [], k = null, value;
2201             for (k in obj) {
2202                 if (obj.hasOwnProperty(k) && k !== "that" && k !== "setSize") {
2203                     value = obj[k];
2204                     if (typeof value !== "function") {
2205                         array.push(value);
2206                     }
2207                 }
2208             }
2209             return array;
2210         }
2211     }
2212     ThSet.prototype.fromArray = function(array) {
2213         var set = new thymol.ThSet(), i, iLimit;
2214         for (i = 0, iLimit = array.length; i < iLimit; i++) {
2215             set.add(array[i]);
2216         }
2217         return set;
2218     };
2219     function ThMap() {
2220         ThSet.apply(this);
2221         this.containsKey = function(k) {
2222             return this.contains(k);
2223         };
2224         this.containsValue = function(target) {
2225             var k = null, value;
2226             for (k in this.that) {
2227                 if (this.that.hasOwnProperty(k) && k !== "that") {
2228                     value = this.that[k];
2229                     if (value === target) {
2230                         return true;
2231                     }
2232                 }
2233             }
2234             return false;
2235         };
2236         this.entrySet = function() {
2237             return this.that;
2238         };
2239         this.get = function(k) {
2240             return this.that[k];
2241         };
2242         this.keySet = function() {
2243             return this.that;
2244         };
2245         this.put = function(k, v) {
2246             var contained = typeof this[k] !== "undefined";
2247             this.that[k] = v;
2248             if (contained !== (typeof this[k] !== "undefined")) {
2249                 this.setSize++;
2250             }
2251         };
2252         this.putAll = function(t) {
2253             for (var k in t) {
2254                 put(k, t[k]);
2255             }
2256         };
2257         this.values = function() {
2258             return this.that;
2259         };
2260     }
2261     ThMap.prototype = new ThSet();
2262     ThMap.prototype.constructor = ThMap;
2263     function ThObject(dolly) {
2264         for (prop in dolly) {
2265             if (dolly.hasOwnProperty(prop)) {
2266                 if (prop) {
2267                     if (!this[prop]) {
2268                         this[prop] = dolly[prop];
2269                     }
2270                 }
2271             }
2272         }
2273         this["class"] = new thymol.ThClass("Thymol.ThObject");
2274         this.toNonThObject = function() {
2275             var plain = {};
2276             for (prop in this) {
2277                 if (this.hasOwnProperty(prop)) {
2278                     if (prop) {
2279                         if (!plain[prop]) {
2280                             if (prop !== "toNonThObject") {
2281                                 if (prop !== "class" || prop === "class" && this[prop] !== null && this[prop].name !== "Thymol.ThObject") {
2282                                     plain[prop] = this[prop];
2283                                 }
2284                             }
2285                         }
2286                     }
2287                 }
2288             }
2289             return plain;
2290         };
2291     }
2292     function ThVarsAccessor(storeArg, storeNameArg) {
2293         this.store = storeArg;
2294         this.arrayName = storeNameArg;
2295         this.length = function() {
2296             return this.store.length;
2297         };
2298         this.get = function(name) {
2299             return this.store[name];
2300         };
2301         this.set = function(name, value) {
2302             this.store[name] = value;
2303         };
2304     }
2305     function ThClass(nValue) {
2306         this.name = nValue;
2307     }
2308     return {
2309         Thymol: Thymol,
2310         ThError: ThError,
2311         ThParam: ThParam,
2312         ThAttr: ThAttr,
2313         ThElement: ThElement,
2314         ThSet: ThSet,
2315         ThMap: ThMap,
2316         ThObject: ThObject,
2317         ThVarsAccessor: ThVarsAccessor,
2318         ThClass: ThClass,
2319         thDomParser: thymol.thDomParser,
2320         thDocument: thymol.thDocument,
2321         thWindow: thymol.thWindow,
2322         thTop: thymol.thTop,
2323         thRequest: thymol.thRequest,
2324         thVersion: thymol.thVersion,
2325         thReleaseDate: thymol.thReleaseDate,
2326         thURL: thymol.thURL,
2327         thAltURL: thymol.thAltURL,
2328         thInclude: thymol.thInclude,
2329         thReplace: thymol.thReplace,
2330         thSubstituteby: thymol.thSubstituteby,
2331         thFragment: thymol.thFragment,
2332         thRemove: thymol.thRemove,
2333         thBlock: thymol.thBlock,
2334         thScriptName: thymol.thScriptName,
2335         thDefaultPrefix: thymol.thDefaultPrefix,
2336         thDefaultDataPrefix: thymol.thDefaultDataPrefix,
2337         thDefaultPrecision: thymol.thDefaultPrecision,
2338         thDefaultProtocol: thymol.thDefaultProtocol,
2339         thDefaultLocale: thymol.thDefaultLocale,
2340         thDefaultPrecedence: thymol.thDefaultPrecedence,
2341         thDefaultMessagePath: thymol.thDefaultMessagePath,
2342         thDefaultResourcePath: thymol.thDefaultResourcePath,
2343         thDefaultMessagesBaseName: thymol.thDefaultMessagesBaseName,
2344         thDefaultRelativeRootPath: thymol.thDefaultRelativeRootPath,
2345         thDefaultExtendedMapping: thymol.thDefaultExtendedMapping,
2346         thDefaultLocalMessages: thymol.thDefaultLocalMessages,
2347         thDefaultDisableMessages: thymol.thDefaultDisableMessages,
2348         thDefaultTemplateSuffix: thymol.thDefaultTemplateSuffix,
2349         thThymeleafPrefixList: thymol.thThymeleafPrefixList,
2350         thThymeleafElementsList: thymol.thThymeleafElementsList,
2351         thLocation: thymol.thLocation,
2352         messagePath: thymol.messagePath,
2353         resourcePath: thymol.resourcePath,
2354         relativeRootPath: thymol.relativeRootPath,
2355         messagesBaseName: thymol.messagesBaseName,
2356         extendedMapping: thymol.extendedMapping,
2357         scriptPath: thymol.scriptPath,
2358         absolutePath: thymol.absolutePath,
2359         useAbsolutePath: thymol.useAbsolutePath,
2360         useFullURLPath: thymol.useFullURLPath,
2361         localMessages: thymol.localMessages,
2362         indexFile: thymol.indexFile,
2363         disableMessages: thymol.disableMessages,
2364         templateSuffix: thymol.templateSuffix,
2365         prefix: thymol.prefix,
2366         dataPrefix: thymol.dataPrefix,
2367         templateName: thymol.templateName,
2368         templatePath: thymol.templatePath,
2369         objects: thymol.objects,
2370         jqSetup: jqSetup,
2371         isClientSide: isClientSide,
2372         execute: execute,
2373         updatePrefix: updatePrefix,
2374         init: init,
2375         ready: ready,
2376         addDialect: addDialect,
2377         isFragmentChild: isFragmentChild,
2378         preProcess: preProcess,
2379         substitute: substitute,
2380         substituteParam: substituteParam,
2381         configureModule: configureModule,
2382         configureAttributeProcessor: configureAttributeProcessor,
2383         configureElementProcessor: configureElementProcessor,
2384         configurePreExecution: configurePreExecution,
2385         configurePostExecution: configurePostExecution,
2386         getStandardURL: getStandardURL,
2387         getMessage: getMessage,
2388         getExpression: getExpression,
2389         getWith: getWith,
2390         getParsedExpr: getParsedExpr,
2391         getLocale: getLocale,
2392         getMapped: getMapped,
2393         getBooleanValue: getBooleanValue,
2394         setLocale: setLocale
2395     };
2396 }();
2397
2398 thymol.makeContext = function(contextNameParam, varAccessorParam) {
2399     var jsonDeclSpec = "(?:\\W*([\\'][A-Za-z]+(?:\\w|[$])*[\\'])\\s*[:])?\\s*([#][A-Za-z]+(?:\\w|[$])*)(?:\\W|[^$])*", jsonDeclExpr = new RegExp(jsonDeclSpec), context = new Array();
2400     context.contextName = contextNameParam;
2401     context.varAccessor = varAccessorParam;
2402     context.varStore = [];
2403     context.varNamePrefix = "";
2404     if (typeof varAccessorParam === "undefined") {
2405         context.varAccessor = new thymol.ThVarsAccessor(context.varStore, "varStore");
2406     }
2407     context.varNamePrefix = context.varAccessor.arrayName + "[";
2408     context.getJSONView = function(param, rootVal) {
2409         var pType = typeof param, view = "", objType;
2410         if (pType === "string") {
2411             view = view + "'" + param + "'";
2412         } else if (pType === "number" || pType === "boolean") {
2413             view = view + param;
2414         } else if (pType === "object") {
2415             if (param instanceof Object) {
2416                 objType = Object.prototype.toString.call(param);
2417                 if ("[object Array]" === objType) {
2418                     view = this.getJSONViewArray(param, false);
2419                 } else if ("[object Object]" === objType) {
2420                     view = this.getJSONViewObject(param, false);
2421                 }
2422                 view = "#" + view;
2423             }
2424         }
2425         return view;
2426     };
2427     context.init = function() {
2428         var persisted = thymol.thTop.name, paramRow, paramName, params, i, iLimit, paramValue;
2429         if (persisted && persisted !== "") {
2430             params = this.javascriptify(persisted);
2431             if (params && params.length > 0) {
2432                 for (i = 0, iLimit = params.length; i < iLimit; i++) {
2433                     paramRow = params[i];
2434                     if (paramRow) {
2435                         paramName = paramRow[0];
2436                         if (paramName) {
2437                             paramValue = paramRow[1];
2438                             this.createVariable(paramName, paramValue);
2439                         }
2440                     }
2441                 }
2442             }
2443         }
2444     };
2445     context.getJSONViewObject = function(param, rootVal) {
2446         var isRoot = true, key = null, view = "{", value, identifier, definition, suffix, instanceNamePrefix, isTaken, i, iLimit, instanceValue;
2447         if (typeof rootVal === "boolean") {
2448             isRoot = rootVal;
2449         }
2450         for (key in param) {
2451             if (key) {
2452                 value = param[key];
2453                 if (typeof value !== "function") {
2454                     if (view != "{") {
2455                         view = view + ",";
2456                     }
2457                     identifier = this.getJSONView(key, false);
2458                     definition = this.getJSONView(value, false);
2459                     view = view + identifier + ":";
2460                     if (!isRoot && typeof value === "object") {
2461                         suffix = 1;
2462                         instanceNamePrefix = key + "$";
2463                         instanceName = null;
2464                         isTaken = false;
2465                         do {
2466                             instanceName = instanceNamePrefix + suffix++;
2467                             instanceValue = context[instanceName];
2468                             if (instanceValue === null || typeof instanceValue === "undefined") {
2469                                 isTaken = false;
2470                                 for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
2471                                     if (instanceName === varStore[i][0]) {
2472                                         isTaken = true;
2473                                         break;
2474                                     }
2475                                 }
2476                                 if (!isTaken) {
2477                                     this.addAttribute(instanceName, definition);
2478                                 }
2479                             }
2480                         } while (isTaken);
2481                         if (instanceName !== null) {
2482                             view = view + "#" + instanceName;
2483                         }
2484                     } else {
2485                         view = view + definition;
2486                     }
2487                 }
2488             }
2489         }
2490         view = view + "}";
2491         return view;
2492     };
2493     context.getJSONViewArray = function(param, rootVal) {
2494         var view = "[", i;
2495         for (i = 0; i < param.length; i++) {
2496             view = view + this.getJSONView(param[i], false);
2497             if (i < param.length - 1) {
2498                 view = view + ",";
2499             }
2500         }
2501         view = view + "]";
2502         return view;
2503     };
2504     context.getAttribute = function(name) {
2505         return context[name];
2506     };
2507     context.addAttribute = function(name, value) {
2508         var entry = [];
2509         entry[0] = name;
2510         entry[1] = value;
2511         varStore.push(entry);
2512     };
2513     context.serialise = function() {
2514         varStore = [];
2515         var serialised = "[", key = null, value, cn, view, name, i, iLimit;
2516         for (key in context) {
2517             if (key) {
2518                 value = context[key];
2519                 if (value != null && typeof value === "object") {
2520                     cn = Object.prototype.toString.call(value);
2521                     if ("[object Array]" !== cn && !(value instanceof thymol.ThClass) && !(value instanceof thymol.ThVarsAccessor)) {
2522                         if (serialised !== "[") {
2523                             serialised = serialised + ",";
2524                         }
2525                         view = this.getJSONView(value, true);
2526                         serialised = serialised + "[";
2527                         serialised = serialised + '"' + key + '"';
2528                         serialised = serialised + ",";
2529                         serialised = serialised + '"' + view + '"';
2530                         serialised = serialised + "]";
2531                     }
2532                 }
2533             }
2534         }
2535         for (i = 0, iLimit = varStore.length; i < iLimit; i++) {
2536             name = varStore[i][0];
2537             view = varStore[i][1];
2538             serialised = serialised + ",[";
2539             serialised = serialised + '"' + name + '"';
2540             serialised = serialised + ",";
2541             serialised = serialised + '"' + view + '"';
2542             serialised = serialised + "]";
2543         }
2544         serialised = serialised + "]";
2545         return serialised;
2546     };
2547     context.javascriptify = function(fn) {
2548         try {
2549             return new Function("return " + fn)();
2550         } catch (err) {
2551             return undefined;
2552         }
2553     };
2554     context.createVariable = function(name, valParam, isReq) {
2555         var value = valParam, param, tt, literalBoolean, strValue, initial, existing, newArray;
2556         param = value;
2557         if (!(value instanceof thymol.ThParam)) {
2558             tt = typeof valParam;
2559             if (tt !== "function" && tt !== "object") {
2560                 if (tt === "string") {
2561                     try {
2562                         value = isReq ? decodeURIComponent(value) : decodeURI(value);
2563                     } catch (err) {}
2564                 }
2565                 if (tt === "boolean" || tt === "number") {
2566                     param = new thymol.ThParam(value);
2567                 } else if (value || value === "") {
2568                     literalBoolean = thymol.ThUtils.testLiteralFalse(value);
2569                     if (literalBoolean) {
2570                         param = false;
2571                     } else {
2572                         strValue = new String(value);
2573                         initial = strValue.trim();
2574                         if (initial.charAt(0) === "#") {
2575                             initial = initial.substring(1);
2576                             try {
2577                                 param = this.createJSONVariable(initial);
2578                             } catch (err) {
2579                                 if (err instanceof ReferenceError) {}
2580                                 if (err instanceof EvalError) {}
2581                                 if (param == null || isReq) {
2582                                     param = new thymol.ThParam(value);
2583                                 }
2584                             }
2585                         } else {
2586                             param = new thymol.ThParam(strValue.toString());
2587                         }
2588                     }
2589                 }
2590             }
2591         }
2592         if (isReq) {
2593             existing = context[name];
2594             if (typeof existing !== "undefined" && existing !== null) {
2595                 if (Object.prototype.toString.call(existing) === "[object Array]") {
2596                     existing.push(param);
2597                 } else {
2598                     if (thymol.debug) {
2599                         thymol.thWindow.alert('request parameters should be of type string array "' + name + '"');
2600                     }
2601                 }
2602             } else {
2603                 newArray = new Array();
2604                 newArray["class"] = {};
2605                 newArray["class"]["name"] = "[Thymol.ThParam]";
2606                 newArray.push(param);
2607                 context[name] = newArray;
2608             }
2609         } else {
2610             context[name] = param;
2611         }
2612         return param;
2613     };
2614     context.createJSONVariable = function(initial) {
2615         var current = initial.trim(), parts = " ", substIndex, token, re, vName, obj, result;
2616         substIndex = this.varAccessor.length() + 1;
2617         while (parts) {
2618             parts = current.match(jsonDeclExpr);
2619             if (parts && parts.length > 2) {
2620                 token = parts[2];
2621                 token = token.replace(/[\']/g, "[']").replace(/[$]/g, "[$]");
2622                 re = new RegExp(token);
2623                 vName = this.varNamePrefix + substIndex + "]";
2624                 obj = new Object();
2625                 obj.name = parts[2].substring(1);
2626                 this.varAccessor.set(substIndex, obj);
2627                 substIndex = substIndex + 1;
2628                 current = current.replace(re, "'" + vName + "'", "g");
2629             }
2630         }
2631         current = current.replace(/[\']/g, '"');
2632         result = $.parseJSON(current);
2633         if ("[object Array]" !== Object.prototype.toString.call(result)) {
2634             result = new thymol.ThObject(result);
2635         }
2636         return result;
2637     };
2638     context.resolveJSONReferences = function() {
2639         var key = null, param, prop = null, val, ref, subst, isReq = "request" === this.contextName;
2640         for (key in context) {
2641             if (key) {
2642                 param = context[key];
2643                 if (param != null && typeof param === "object") {
2644                     if (!(param instanceof thymol.ThVarsAccessor) && !(param instanceof thymol.ThClass)) {
2645                         if (!(param instanceof thymol.ThParam)) {
2646                             if (isReq && Object.prototype.toString.call(param) === "[object Array]") {
2647                                 for (var i = 0, iLimit = param.length; i < iLimit; i++) {
2648                                     var pi = param[i];
2649                                     if (!!pi && typeof pi.value === "string" && pi.value.charAt(0) == "#") {
2650                                         var pv = thymol.ThUtils.getParameter(pi.value.substring(1));
2651                                         param[i] = pv;
2652                                     }
2653                                 }
2654                             } else {
2655                                 for (prop in param) {
2656                                     if (prop) {
2657                                         val = param[prop];
2658                                         if (typeof val === "string") {
2659                                             if (val.indexOf(this.varNamePrefix) == 0) {
2660                                                 subst = null;
2661                                                 if (prop.match(/\d*/)) {
2662                                                     ref = val.substring(this.varNamePrefix.length, val.length - 1);
2663                                                     ref = this.varAccessor.get(ref);
2664                                                     subst = context[ref.name];
2665                                                 } else {
2666                                                     subst = context[prop];
2667                                                 }
2668                                                 param[prop] = subst;
2669                                             }
2670                                         }
2671                                     }
2672                                 }
2673                             }
2674                         } else if (typeof param.value === "string" && param.value.charAt(0) == "#") {
2675                             subst = context[param.value.substring(1)];
2676                             context[key] = subst;
2677                         }
2678                     }
2679                 }
2680             }
2681         }
2682     };
2683     return context;
2684 };
2685
2686 thymol.ThUtils = function() {
2687     function mergeVars(thiz, other) {
2688         var current = thiz, prop = null;
2689         if (!current) {
2690             current = {};
2691         }
2692         for (prop in other) {
2693             if (other.hasOwnProperty(prop)) {
2694                 if (prop) {
2695                     if (!current[prop]) {
2696                         current[prop] = other[prop];
2697                     }
2698                 }
2699             }
2700         }
2701         return current;
2702     }
2703     function processElement(func, element, arg, obj) {
2704         var result = null, parent = element.parentElement;
2705         if (!thymol.isFragmentChild(element)) {
2706             if (!element.thObjectVar) {
2707                 parent = element.parentElement;
2708                 while (parent) {
2709                     if (parent.thObjectVar) {
2710                         element.thObjectVar = parent.thObjectVar;
2711                         break;
2712                     }
2713                     parent = parent.parentElement;
2714                 }
2715             }
2716             parent = element.parentElement;
2717             while (parent) {
2718                 if (parent.thLocalVars) {
2719                     element.thLocalVars = mergeVars(element.thLocalVars, parent.thLocalVars);
2720                     break;
2721                 }
2722                 parent = parent.parentElement;
2723             }
2724             result = func(element, arg, obj);
2725         }
2726         return result;
2727     }
2728     function unQuote(param) {
2729         var par = param, pared;
2730         if (par) {
2731             if (typeof par === "string") {
2732                 par = par.trim();
2733                 if (par.charAt(0) == '"') {
2734                     if (par.charAt(par.length - 1) == '"') {
2735                         pared = par.substring(1, par.length - 1);
2736                         if (pairParity(pared, '"', '"') == 0) {
2737                             par = pared;
2738                         }
2739                     }
2740                 } else if (par.charAt(0) == "'") {
2741                     if (par.charAt(par.length - 1) == "'") {
2742                         pared = par.substring(1, par.length - 1);
2743                         if (pairParity(pared, "'", "'") == 0) {
2744                             par = pared;
2745                         }
2746                     }
2747                 }
2748             }
2749         }
2750         return par;
2751     }
2752     function unParenthesise(param) {
2753         var par = param, pared;
2754         if (par) {
2755             if (typeof par === "string") {
2756                 par = par.trim();
2757                 if (par.charAt(0) == "(") {
2758                     if (par.charAt(par.length - 1) == ")") {
2759                         pared = par.substring(1, par.length - 1).trim();
2760                         if (pairParity(pared, "(", ")") == 0) {
2761                             par = pared;
2762                         }
2763                     }
2764                 }
2765             }
2766         }
2767         return par;
2768     }
2769     function pairParity(str, left, right) {
2770         var i, ch, strLength = str.length, parity = 0;
2771         for (i = 0; i < strLength; i++) {
2772             ch = str.charAt(i);
2773             if (ch == left) {
2774                 parity++;
2775             } else if (ch == right) {
2776                 parity--;
2777                 if (parity < 0) {
2778                     break;
2779                 }
2780             }
2781         }
2782         return parity;
2783     }
2784     function unBracket(param) {
2785         var par = param, pared;
2786         if (typeof par === "string") {
2787             par = par.trim();
2788         }
2789         if (par) {
2790             if (par.charAt(0) == "[") {
2791                 if (par.charAt(par.length - 1) == "]") {
2792                     pared = par.substring(1, par.length - 1);
2793                     if (pairParity(pared, "[", "]") == 0) {
2794                         par = pared;
2795                     }
2796                 }
2797             }
2798         }
2799         return par;
2800     }
2801     function getToPrecision(n, p) {
2802         if (typeof p === "undefined") {
2803             return n;
2804         }
2805         var up = thymol.thDefaultPrecision, ndp = 0, s, sl, dp, v;
2806         if (p > up) {
2807             up = p;
2808         } else {
2809             s = n.toString();
2810             sl = s.length;
2811             dp = s.indexOf(".");
2812             if (dp >= 0) {
2813                 ndp = sl - 1 - dp;
2814             }
2815             if (ndp > up) {
2816                 v = n.toPrecision(ndp + 1);
2817                 v = truncateDecimals(v);
2818                 s = v.toString();
2819                 sl = s.length;
2820                 if (dp >= 0) {
2821                     ndp = sl - 1 - dp;
2822                 }
2823             }
2824             if (p > ndp) {
2825                 up = p;
2826             } else if (ndp < up) {
2827                 up = ndp;
2828             }
2829         }
2830         v = parseFloat(n);
2831         v = v.toFixed(up);
2832         if (p === 0) {
2833             v = Number(v);
2834         }
2835         return v;
2836     }
2837     function truncateDecimals(valp) {
2838         var val = valp, iLimit = valp.length - 1, i;
2839         for (i = iLimit; i >= 0; i--) {
2840             if (val.charAt(i) === "0") {
2841                 val = val.substr(0, i);
2842             } else {
2843                 break;
2844             }
2845         }
2846         return val;
2847     }
2848     function getDecimalDigits(val) {
2849         var digits = 0, s, dp;
2850         s = val.toString();
2851         dp = s.indexOf(".") + 1;
2852         if (dp > 0) {
2853             digits = s.length - dp;
2854         }
2855         return digits;
2856     }
2857     function testLiteralFalse(initial) {
2858         var result = false, val;
2859         if (typeof initial === "string") {
2860             val = initial.toLowerCase();
2861             result = val == "false" || val == "off" || val == "no";
2862         } else if (typeof initial === "boolean") {
2863             result = !initial;
2864         }
2865         return result;
2866     }
2867     function renderMessage(msg, values) {
2868         var result = msg, i, iLimit;
2869         if (Object.prototype.toString.call(values) == "[object Array]") {
2870             for (i = 0, iLimit = values.length; i < iLimit; i++) {
2871                 result = renderMessageArg(result, i, values[i]);
2872             }
2873         } else {
2874             result = renderMessageArg(msg, 0, values);
2875         }
2876         return result;
2877     }
2878     function renderMessageArg(msg, index, value) {
2879         var result = msg, splits, i, iLimit, iUpper;
2880         splits = msg.split("{" + index + "}");
2881         if (splits.length > 0) {
2882             result = "";
2883             for (i = 0, iLimit = splits.length, iUpper = iLimit - 1; i < iLimit; i++) {
2884                 result += splits[i];
2885                 if (i < iUpper) {
2886                     result += value;
2887                 }
2888             }
2889         }
2890         return result;
2891     }
2892     function getParameter(name) {
2893         var result, tor;
2894         result = thymol.requestContext[name];
2895         tor = typeof result;
2896         if (tor === "undefined") {
2897             result = thymol.sessionContext[name];
2898             if (typeof result === "undefined") {
2899                 result = thymol.applicationContext[name];
2900             }
2901         } else if (tor === "object") {
2902             if (Object.prototype.toString.call(result) === "[object Array]") {
2903                 if (result.length === 1) {
2904                     result = result[0];
2905                 }
2906             }
2907         }
2908         return result;
2909     }
2910     function charOcurrences(str, chr) {
2911         var count = 0, i = 0, iLimit = str.length;
2912         for (;i < iLimit; i++) {
2913             if (str.charAt(i) === chr) {
2914                 count++;
2915             }
2916         }
2917         return count;
2918     }
2919     function isLiteral(val) {
2920         var first, last;
2921         if (typeof val === "string") {
2922             first = val.charAt(0);
2923             last = val.charAt(val.length - 1);
2924             if (first == "'" && last == "'") {
2925                 return true;
2926             }
2927             if (first == '"' && last == '"') {
2928                 return true;
2929             }
2930         }
2931         return false;
2932     }
2933     function isLiteralSubst(param) {
2934         var result = false, par = param;
2935         if (typeof par === "string") {
2936             par = par.trim();
2937         }
2938         if (par) {
2939             if (par.charAt(0) == "|") {
2940                 if (par.charAt(par.length - 1) == "|") {
2941                     result = true;
2942                 }
2943             }
2944         }
2945         return result;
2946     }
2947     function loadScript(file) {
2948         var script = thymol.Thymol.prototype.getFilePath(file);
2949         var status = "";
2950         var jqxhr = $.ajax({
2951             type: "GET",
2952             url: script,
2953             dataType: "script",
2954             cache: true,
2955             async: false
2956         }).done(function() {
2957             status = "success";
2958         }).fail(function() {
2959             status = "error";
2960         });
2961     }
2962     function unescape(text) {
2963         var result = text, i, iLimit, iUpper, c, cc;
2964         if (text !== null && typeof text !== "undefined") {
2965             result = "";
2966             iLimit = text.length;
2967             iUpper = iLimit - 3;
2968             for (i = 0; i < iLimit; i++) {
2969                 c = text.charAt(i);
2970                 if (i < iUpper) {
2971                     if (c === "&") {
2972                         cc = text.charAt(i + 1).toLowerCase();
2973                         if ((cc === "g" || cc === "l") && text.charAt(i + 2).toLowerCase() === "t" && text.charAt(i + 3) === ";") {
2974                             i += 3;
2975                             if (cc === "g") {
2976                                 c = ">";
2977                             } else {
2978                                 c = "<";
2979                             }
2980                         } else if (i < iUpper - 1 && cc === "a" && text.charAt(i + 2).toLowerCase() === "m" && text.charAt(i + 3).toLowerCase() === "p" && text.charAt(i + 4) === ";") {
2981                             i += 4;
2982                         } else if (i < iUpper - 2) {
2983                             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) === ";") {
2984                                 i += 5;
2985                                 c = '"';
2986                             } 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) === ";") {
2987                                 i += 5;
2988                                 c = "'";
2989                             }
2990                         }
2991                     }
2992                 }
2993                 result += c;
2994             }
2995         }
2996         return result;
2997     }
2998     function unicodeUnescape(initial) {
2999         var result = initial.replace(/\\u([\da-f]{4})/gi, function(match, grp) {
3000             return String.fromCharCode(parseInt(grp, 16));
3001         });
3002         result = unescape(result);
3003         return result;
3004     }
3005     function removeTag(element) {
3006         var parent = element.parentNode, i, iLimit, savedObject = element.thObjectVar, savedLocals = element.thLocalVars;
3007         if (!!parent) {
3008             for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
3009                 var newNode = element.childNodes[i].cloneNode(true);
3010                 if (newNode.nodeType === 1) {
3011                     if (!!savedObject) {
3012                         newNode.thObjectVar = savedObject;
3013                     }
3014                     if (!!savedLocals) {
3015                         newNode.thLocalVars = savedLocals;
3016                     }
3017                 }
3018                 parent.insertBefore(newNode, element);
3019             }
3020             parent.removeChild(element);
3021         }
3022     }
3023     function getRequestEncoded(initial) {
3024         var result = initial;
3025         result = encodeURIComponent(result);
3026         result = result.replace(/%20/g, "+");
3027         result = result.replace(/%26/g, "&");
3028         result = result.replace(/%3A/g, ":");
3029         result = result.replace(/!/g, "%21");
3030         result = result.replace(/'/g, "%27");
3031         result = result.replace(/\(/g, "%28");
3032         result = result.replace(/\)/g, "%29");
3033         result = result.replace(/\*/g, "%2A");
3034         result = result.replace(/~/g, "%7E");
3035         return result;
3036     }
3037     return {
3038         getParameter: getParameter,
3039         processElement: processElement,
3040         unQuote: unQuote,
3041         unParenthesise: unParenthesise,
3042         unBracket: unBracket,
3043         getToPrecision: getToPrecision,
3044         getDecimalDigits: getDecimalDigits,
3045         testLiteralFalse: testLiteralFalse,
3046         renderMessage: renderMessage,
3047         charOcurrences: charOcurrences,
3048         isLiteral: isLiteral,
3049         isLiteralSubst: isLiteralSubst,
3050         loadScript: loadScript,
3051         unescape: unescape,
3052         unicodeUnescape: unicodeUnescape,
3053         removeTag: removeTag,
3054         getRequestEncoded: getRequestEncoded
3055     };
3056 }();
3057
3058 thymol.ThParser = function(scope) {
3059     function object(o) {
3060         function F() {}
3061         F.prototype = o;
3062         return new F();
3063     }
3064     function NullReturn(varName) {
3065         this.varName = varName;
3066     }
3067     var TNUMBER = 0;
3068     var TOP1 = 1;
3069     var TOP2 = 2;
3070     var TVAR = 3;
3071     var TFUNCALL = 4;
3072     var MSGSUBST = 5;
3073     var ARGLIST = 6;
3074     function Token(type_p, index_p, prio_p, number_p, mode_p, meta_p) {
3075         this.type_ = type_p;
3076         this.index_ = index_p || 0;
3077         this.prio_ = prio_p || 0;
3078         this.number_ = number_p !== undefined && number_p !== null ? number_p : 0;
3079         this.mode_ = mode_p !== undefined && mode_p !== null ? mode_p : 0;
3080         this.meta_ = meta_p;
3081         this.toString = function() {
3082             switch (this.type_) {
3083               case TNUMBER:
3084                 return this.number_;
3085
3086               case TOP1:
3087               case TOP2:
3088               case TVAR:
3089                 return this.index_;
3090
3091               case TFUNCALL:
3092               case MSGSUBST:
3093               case ARGLIST:
3094                 return "CALL";
3095
3096               default:
3097                 return "Invalid Token";
3098             }
3099         };
3100     }
3101     function Expression(tokens, ops1, ops2, functions, precision, position) {
3102         this.tokens = tokens;
3103         this.ops1 = ops1;
3104         this.ops2 = ops2;
3105         this.functions = functions;
3106         this.precision = precision;
3107         this.position = position;
3108     }
3109     Expression.prototype = {
3110         simplify: function(valuesParam) {
3111             var values = valuesParam || {};
3112             var nstack = [];
3113             var newexpression = [];
3114             var n1;
3115             var n2;
3116             var f;
3117             var L = this.tokens.length;
3118             var item;
3119             var i = 0;
3120             for (i = 0; i < L; i++) {
3121                 item = this.tokens[i];
3122                 var type_ = item.type_;
3123                 if (type_ === TNUMBER) {
3124                     nstack.push(item);
3125                 } else if (type_ === TVAR && !(item.index_ in new Object()) && item.index_ in values) {
3126                     item = new Token(TNUMBER, 0, 0, values[item.index_]);
3127                     nstack.push(item);
3128                 } else if (type_ === TOP2 && nstack.length > 1) {
3129                     f = this.ops2[item.index_];
3130                     if (!!f) {
3131                         n2 = nstack.pop();
3132                         n1 = nstack.pop();
3133                         item = new Token(TNUMBER, 0, 0, f(n1.number_, n2.number_));
3134                     }
3135                     nstack.push(item);
3136                 } else if (type_ === TOP1 && nstack.length > 0) {
3137                     if ("{" == item.index_) {
3138                         if (item.mode_ == 2) {
3139                             nstack.push(item);
3140                         }
3141                     } else {
3142                         n1 = nstack.pop();
3143                         f = this.ops1[item.index_];
3144                         item = new Token(TNUMBER, 0, 0, f(n1.number_));
3145                         nstack.push(item);
3146                     }
3147                 } else {
3148                     while (nstack.length > 0) {
3149                         newexpression.push(nstack.shift());
3150                     }
3151                     newexpression.push(item);
3152                 }
3153             }
3154             while (nstack.length > 0) {
3155                 newexpression.push(nstack.shift());
3156             }
3157             var res = new Expression(newexpression, object(this.ops1), object(this.ops2), object(this.functions), this.precision);
3158             return res;
3159         },
3160         evaluate: function(element) {
3161             var nstack = [];
3162             var n1;
3163             var n2;
3164             var f;
3165             var res = null;
3166             var L = this.tokens.length;
3167             var item;
3168             var i = 0;
3169             var result;
3170             for (i = 0; i < L; i++) {
3171                 item = this.tokens[i];
3172                 if (i === 0 && thymol.disableMessages && item.mode_ === 4) {
3173                     var nullReturn = new thymol.ThClass();
3174                     nullReturn.abort = true;
3175                     return nullReturn;
3176                 }
3177                 var type_ = item.type_;
3178                 if (type_ === TNUMBER) {
3179                     nstack.push(item.number_);
3180                     if (i == L - 1) {
3181                         break;
3182                     }
3183                 } else if (type_ === TOP2) {
3184                     n2 = nstack.pop();
3185                     if (typeof n2 === "undefined" || n2 instanceof NullReturn) {
3186                         n2 = null;
3187                     }
3188                     n1 = nstack.pop();
3189                     if (typeof n1 === "undefined" || n1 instanceof NullReturn) {
3190                         n1 = null;
3191                     }
3192                     f = this.ops2[item.index_];
3193                     var pathMatch = false;
3194                     try {
3195                         if (item.mode_ === 6) {
3196                             if (f === dot) {
3197                                 res = n1 + "[" + n2 + "]";
3198                             } else if (f === append) {
3199                                 if (!!item.meta_) {
3200                                     if (!!item.meta_.paths) {
3201                                         var values = item.meta_.paths[n1];
3202                                         if (!!values) {
3203                                             values.push(n2);
3204                                             pathMatch = true;
3205                                             res = null;
3206                                         }
3207                                     }
3208                                 }
3209                                 if (!pathMatch) {
3210                                     if (!item.meta_) {
3211                                         item.meta_ = {};
3212                                     }
3213                                     if (!item.meta_.params) {
3214                                         item.meta_.params = [];
3215                                     }
3216                                     var values = item.meta_.params[n1];
3217                                     if (!values) {
3218                                         values = [];
3219                                         item.meta_.params[n1] = values;
3220                                     }
3221                                     values.push(n2);
3222                                     pathMatch = true;
3223                                 }
3224                             } else {
3225                                 res = n2;
3226                                 nstack.push(n1);
3227                             }
3228                         } else {
3229                             if (f === dot && "class" === n2 && !!n1 && !n1["class"]) {
3230                                 var tn2 = typeof n2;
3231                                 if (tn2 === "object" && n2 instanceof thymol.ThParam) {
3232                                     res = f(n1, n2);
3233                                 } else {
3234                                     res = new thymol.ThClass("JavaScript:" + tn2);
3235                                 }
3236                             } else {
3237                                 res = f(n1, n2);
3238                                 if (typeof res === "function") {
3239                                     if (L - 1 > i) {
3240                                         next = this.tokens[i + 1];
3241                                         if (next.type_ === TNUMBER && Object.prototype.toString.call(next.number_) == "[object Array]" && next.number_.length == 0) {
3242                                             i += 1;
3243                                             nstack.push(res);
3244                                             n1.isDirect = true;
3245                                             res = n1;
3246                                         }
3247                                     }
3248                                 }
3249                             }
3250                             if (f !== append) {
3251                                 if (Object.prototype.toString.call(res) == "[object Array]") {
3252                                     res.arrayResult = true;
3253                                 }
3254                             }
3255                         }
3256                     } catch (err) {
3257                         if (!element.isBlockChild) {
3258                             var aValue = n1 == null ? "null" : n1;
3259                             var bValue = n2 == null ? "null" : n2;
3260                             var message = "while evaluating expression: " + this.tokens[i - 2].index_ + ": " + aValue + ", " + this.tokens[i - 1].index_ + ": " + bValue;
3261                             throw new thymol.ThError(message, element, err);
3262                         }
3263                     }
3264                     if (!pathMatch) {
3265                         nstack.push(res);
3266                     }
3267                 } else if (type_ === TVAR) {
3268                     var next = null, pushed = nstack.length;
3269                     if (item.index_ != null) {
3270                         if (L - 1 > i) {
3271                             next = this.tokens[i + 1];
3272                             if (next.type_ === TOP2 && next.index_ === ".") {
3273                                 nstack.push(item.index_);
3274                             }
3275                         }
3276                         if (pushed === nstack.length) {
3277                             var val = thymol.substituteParam(item.index_, item.mode_, element);
3278                             if (Object.prototype.toString.call(val) == "[object Array]") {
3279                                 val.arrayResult = true;
3280                             }
3281                             this.updatePrecision(val);
3282                             if (val === null) {
3283                                 val = new NullReturn(item.index_);
3284                             }
3285                             nstack.push(val);
3286                         }
3287                     } else if (pushed === nstack.length && item.index_ in this.functions) {
3288                         nstack.push(this.functions[item.index_]);
3289                     } else {
3290                         if (!element.isBlockChild) {
3291                             throw new thymol.ThError("Exception undefined variable: " + item.index_, element);
3292                         }
3293                     }
3294                 } else if (type_ === TOP1) {
3295                     n1 = nstack.pop();
3296                     if (typeof n1 === "undefined" || n1 instanceof NullReturn) {
3297                         if (item.mode_ === 2) {
3298                             n1 = "";
3299                         } else {
3300                             n1 = null;
3301                         }
3302                     }
3303                     res = n1;
3304                     if ("{" === item.index_) {
3305                         var prev = this.tokens[i - 1];
3306                         if (prev.mode_ == 7) {
3307                             if (thymol.conversionService) {
3308                                 n1 = thymol.conversionService(n1);
3309                                 res = n1;
3310                             }
3311                         }
3312                         if (typeof n1 === "string") {
3313                             if (item.mode_ === 2) {
3314                                 res = thymol.getStandardURL(n1);
3315                             } else {
3316                                 var subst = thymol.substituteParam(n1, item.mode_, element);
3317                                 if (subst != null) {
3318                                     this.updatePrecision(subst);
3319                                     res = subst;
3320                                 }
3321                             }
3322                         }
3323                     } else {
3324                         f = this.ops1[item.index_];
3325                         try {
3326                             res = f(n1);
3327                         } catch (err) {
3328                             if (!element.isBlockChild) {
3329                                 var aValue = n1 == null ? "null" : n1;
3330                                 var message = "while evaluating expression: " + this.tokens[i - 2].index_ + ": " + aValue;
3331                                 throw new thymol.ThError(message, element, err);
3332                             }
3333                         }
3334                     }
3335                     if (Object.prototype.toString.call(res) == "[object Array]") {
3336                         res.arrayResult = true;
3337                     }
3338                     nstack.push(res);
3339                 } else if (type_ === TFUNCALL || type_ === MSGSUBST || type_ === ARGLIST) {
3340                     n1 = nstack.pop();
3341                     f = nstack.pop();
3342                     if (type_ === MSGSUBST) {
3343                         if (f instanceof NullReturn) {
3344                             res = "??" + f.varName + "_" + thymol.locale.value + "??";
3345                         } else {
3346                             res = thymol.ThUtils.renderMessage(f, n1);
3347                         }
3348                         nstack.push(res);
3349                     } else if (type_ === ARGLIST) {
3350                         var pathMatch = false;
3351                         n2 = nstack.pop();
3352                         if (typeof n2 === "undefined") {
3353                             n2 = f;
3354                             f = n1;
3355                             n1 = "";
3356                         }
3357                         if (!!item.meta_) {
3358                             if (!!item.meta_.paths) {
3359                                 var values = item.meta_.paths[f];
3360                                 if (!!values) {
3361                                     values.push(n1);
3362                                     pathMatch = true;
3363                                 }
3364                                 for (var j in item.meta_.paths) {
3365                                     if (item.meta_.paths.hasOwnProperty(j)) {
3366                                         var values = item.meta_.paths[j];
3367                                         var isReq = n2.indexOf("?") >= 0;
3368                                         if (!!values && values.length > 0) {
3369                                             var pathVar = "{" + j + "}";
3370                                             var repReg = new RegExp(pathVar, "g");
3371                                             var rep = "";
3372                                             values.reverse();
3373                                             for (var k = 0, kLimit = values.length; k < kLimit; k++) {
3374                                                 if (rep.length > 0) {
3375                                                     rep = rep + ",";
3376                                                 }
3377                                                 if (isReq) {
3378                                                     rep = rep + thymol.ThUtils.getRequestEncoded(values[k]);
3379                                                 } else {
3380                                                     rep = rep + encodeURIComponent(values[k]);
3381                                                 }
3382                                             }
3383                                             n2 = n2.replace(repReg, rep);
3384                                         }
3385                                     }
3386                                 }
3387                             }
3388                         }
3389                         if (pathMatch) {
3390                             res = n2;
3391                         } else {
3392                             if (typeof f === "undefined" || f instanceof NullReturn) {
3393                                 f = "";
3394                             } else {
3395                                 f = f.toString();
3396                             }
3397                             f = thymol.ThUtils.getRequestEncoded(f);
3398                             f = "?" + f;
3399                             n1 = n1.toString();
3400                             if (f != "?" && n1 != "") {
3401                                 f = f + "=";
3402                             }
3403                             if (n1 != "") {
3404                                 n1 = thymol.ThUtils.getRequestEncoded(n1);
3405                                 f = f + n1;
3406                             }
3407                             if (typeof n2 === "undefined" || n2 instanceof NullReturn) {
3408                                 n2 = "";
3409                             } else {
3410                                 n2 = n2.toString();
3411                             }
3412                             res = n2 + f;
3413                         }
3414                         if (!!item.meta_) {
3415                             var separator = res.indexOf("?") >= 0 ? "&" : "?";
3416                             for (var j in item.meta_.params) {
3417                                 if (item.meta_.params.hasOwnProperty(j)) {
3418                                     var values = item.meta_.params[j];
3419                                     if (!!values && values.length > 0) {
3420                                         for (var k = 0, kLimit = values.length; k < kLimit; k++) {
3421                                             res = res + separator + thymol.ThUtils.getRequestEncoded(j) + "=" + thymol.ThUtils.getRequestEncoded(values[k]);
3422                                             if (k == 0) {
3423                                                 separator = "&";
3424                                             }
3425                                         }
3426                                     }
3427                                 }
3428                             }
3429                             if (!!item.meta_.urlFragment) {
3430                                 res = res + item.meta_.urlFragment;
3431                             }
3432                         }
3433                         nstack.push(res);
3434                     } else if (f.apply && f.call) {
3435                         if (!!n1 && !!n1.isDirect) {
3436                             res = f.call(n1);
3437                         } else {
3438                             if (n1 instanceof NullReturn) {
3439                                 n1 = null;
3440                             }
3441                             if (n1 != null && (n1.arrayResult || Object.prototype.toString.call(n1) !== "[object Array]")) {
3442                                 res = f.call(element, n1);
3443                             } else {
3444                                 res = f.apply(element, n1);
3445                             }
3446                         }
3447                         if (res instanceof String) {
3448                             if (res.precision) {
3449                                 if (typeof this.precision === "undefined" || res.precision > this.precision) {
3450                                     this.precision = res.precision;
3451                                 }
3452                             }
3453                             res = res.toString();
3454                         } else if (Object.prototype.toString.call(res) == "[object Array]") {
3455                             res.arrayResult = true;
3456                         }
3457                         nstack.push(res);
3458                     } else {
3459                         if (!element.isBlockChild) {
3460                             throw new thymol.ThError(f + " is not a function", element);
3461                         }
3462                     }
3463                 } else {
3464                     if (!element.isBlockChild) {
3465                         throw new thymol.ThError("invalid expression item type: " + type_, element);
3466                     }
3467                 }
3468             }
3469             if (nstack.length > 1) {
3470                 if (!element.isBlockChild) {
3471                     throw new thymol.ThError("invalid Expression (parity)", element);
3472                 }
3473             }
3474             result = nstack[0];
3475             return result;
3476         },
3477         updatePrecision: function(val) {
3478             if (typeof val === "number") {
3479                 var p = thymol.ThUtils.getDecimalDigits(val);
3480                 if (typeof this.precision === "undefined" || p > this.precision) {
3481                     this.precision = p;
3482                 }
3483             }
3484         }
3485     };
3486     function add(a, b) {
3487         return a + b;
3488     }
3489     function assign(a) {
3490         return a;
3491     }
3492     function sub(a, b) {
3493         return a - b;
3494     }
3495     function mul(a, b) {
3496         return a * b;
3497     }
3498     function div(a, b) {
3499         return a / b;
3500     }
3501     function mod(a, b) {
3502         return a % b;
3503     }
3504     function concat(a, b) {
3505         return "" + a + b;
3506     }
3507     function neg(a) {
3508         return -a;
3509     }
3510     function not(a) {
3511         var v = thymol.getBooleanValue(a);
3512         return !v;
3513     }
3514     function random(a) {
3515         return Math.random() * (a || 1);
3516     }
3517     function fac(a) {
3518         var aa = Math.floor(a);
3519         var b = aa;
3520         while (aa > 1) {
3521             b = b * --aa;
3522         }
3523         return b;
3524     }
3525     function append(a, b) {
3526         if (a != null) {
3527             if (a.arrayResult === true || Object.prototype.toString.call(a) != "[object Array]") {
3528                 return [ a, b ];
3529             }
3530         } else {
3531             if (b != null) {
3532                 if (b.arrayResult === true || Object.prototype.toString.call(b) != "[object Array]") {
3533                     return [ a, b ];
3534                 }
3535                 return b;
3536             }
3537             return null;
3538         }
3539         var aa = a.slice();
3540         aa.push(b);
3541         return aa;
3542     }
3543     function equal(a, b) {
3544         return a == b;
3545     }
3546     function notEqual(a, b) {
3547         return a != b;
3548     }
3549     function gt(a, b) {
3550         return a > b;
3551     }
3552     function ge(a, b) {
3553         return a >= b;
3554     }
3555     function lt(a, b) {
3556         return a < b;
3557     }
3558     function le(a, b) {
3559         return a <= b;
3560     }
3561     function and(a, b) {
3562         return a && b;
3563     }
3564     function or(a, b) {
3565         return a || b;
3566     }
3567     function dot(a, b) {
3568         return a[b];
3569     }
3570     function binary(a, b) {
3571         return a ? b : null;
3572     }
3573     function elvis(a, b) {
3574         return a != null ? a : b;
3575     }
3576     function getStr(pos, expression, mode, partial, preprocessed) {
3577         var localMode = mode;
3578         var s = "";
3579         var c = expression.charAt(pos);
3580         var start = pos + 1;
3581         var end = expression.length;
3582         var stopChar = c;
3583         if (localMode === 4 || c === "#") {
3584             stopChar = "}";
3585             localMode = 4;
3586         }
3587         var i = start;
3588         var inCurly = false;
3589         var curlyPos = null;
3590         var urlFragPos = -1;
3591         var meta = null;
3592         if (localMode !== 4 && c !== "'" && c !== '"') {
3593             for (;i <= end; i++) {
3594                 if (c.toUpperCase() === c.toLowerCase()) {
3595                     if (c === "{") {
3596                         inCurly = true;
3597                         curlyPos = i;
3598                         if (meta === null) {
3599                             meta = {};
3600                             meta.paths = [];
3601                         }
3602                     } else if (mode === 2 && c === "#") {
3603                         urlFragPos = i;
3604                     }
3605                     if (i === pos || !inCurly && c === "}" || c !== "_" && c !== "?" && c !== ":" && (c < "0" || c > "9")) {
3606                         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 === "=") {
3607                             i = i - 1;
3608                             break;
3609                         }
3610                     }
3611                     if (inCurly && c === "}") {
3612                         inCurly = false;
3613                         if (meta === null) {
3614                             var message = 'bad path variable definition in expression: "' + expression + '" near column ' + pos;
3615                             throw new thymol.ThError(message, element);
3616                         }
3617                         var curlyVar = expression.substring(curlyPos, i - 1);
3618                         var values = [];
3619                         meta.paths[curlyVar] = values;
3620                     }
3621                 }
3622                 s += c;
3623                 c = expression.charAt(i);
3624             }
3625             if (urlFragPos >= 0) {
3626                 var urlFrag = expression.substring(urlFragPos - 1, i);
3627                 s = s.substring(0, s.length - urlFrag.length);
3628                 if (meta === null) {
3629                     meta = {};
3630                     meta.urlFragment = urlFrag;
3631                 }
3632             }
3633         } else {
3634             var quoted = false;
3635             var preprocessing = false;
3636             if (c === "'" || c === '"') {
3637                 quoted = true;
3638                 stopChar = c;
3639             }
3640             while (i <= end) {
3641                 if (c === stopChar && i > start && !preprocessing) {
3642                     if (localMode !== 4 || quoted) {
3643                         s += c;
3644                     } else {
3645                         i = i - 1;
3646                     }
3647                     break;
3648                 }
3649                 var nc = expression.charAt(i);
3650                 if (c === "_" && nc === "_" && !preprocessed) {
3651                     preprocessing = !preprocessing;
3652                 }
3653                 if (c === "\\") {
3654                     if (nc === "'" && s.charAt(s.length - 1) !== "\\") {
3655                         c = "&#39;";
3656                         if (i + 1 > end) {
3657                             break;
3658                         }
3659                         i = i + 1;
3660                         nc = expression.charAt(i);
3661                     }
3662                 }
3663                 if (!quoted) {
3664                     if (c === ".") {
3665                         var exp = thymol.thExpressionObjects[s];
3666                         if (typeof exp !== "undefined" && exp !== null) {
3667                             i -= 1;
3668                             break;
3669                         }
3670                     }
3671                     if (c === "(") {
3672                         i -= 1;
3673                         break;
3674                     }
3675                 }
3676                 s += c;
3677                 if (i + 1 > end) {
3678                     break;
3679                 }
3680                 i = i + 1;
3681                 c = nc;
3682             }
3683         }
3684         var str = new Object();
3685         str.str = s;
3686         str.pos = i;
3687         if (meta !== null) {
3688             str.meta = meta;
3689         }
3690         return str;
3691     }
3692     function ThParser() {
3693         this.precision;
3694         this.success = false;
3695         this.errormsg = "";
3696         this.expression = "";
3697         this.pos = 0;
3698         this.tokennumber = 0;
3699         this.tokenprio = 0;
3700         this.tokenindex = 0;
3701         this.tmpprio = 0;
3702         this.ops1 = {
3703             sin: Math.sin,
3704             cos: Math.cos,
3705             tan: Math.tan,
3706             asin: Math.asin,
3707             acos: Math.acos,
3708             atan: Math.atan,
3709             sqrt: Math.sqrt,
3710             log: Math.log,
3711             abs: Math.abs,
3712             ceil: Math.ceil,
3713             floor: Math.floor,
3714             round: Math.round,
3715             "-": neg,
3716             "!": not,
3717             not: not,
3718             exp: Math.exp,
3719             "=": assign
3720         };
3721         this.ops2 = {
3722             "?": binary,
3723             ":": elvis,
3724             "?:": elvis,
3725             "+": add,
3726             "-": sub,
3727             "*": mul,
3728             "/": div,
3729             "%": mod,
3730             "^": Math.pow,
3731             ",": append,
3732             "||": concat,
3733             "==": equal,
3734             eq: equal,
3735             "!=": notEqual,
3736             ne: notEqual,
3737             neq: notEqual,
3738             div: div,
3739             mod: mod,
3740             and: and,
3741             or: or,
3742             ">": gt,
3743             gt: gt,
3744             ">=": ge,
3745             "=>": ge,
3746             ge: ge,
3747             "<": lt,
3748             lt: lt,
3749             "<=": le,
3750             "=<": le,
3751             le: le,
3752             ".": dot,
3753             "[": dot
3754         };
3755         this.functions = {
3756             random: random,
3757             fac: fac,
3758             min: Math.min,
3759             max: Math.max,
3760             pow: Math.pow
3761         };
3762         this.consts = {
3763             E: Math.E,
3764             PI: Math.PI
3765         };
3766     }
3767     ThParser.parse = function(expr, partial, preprocessed) {
3768         return new thymol.ThParser().parse(expr, partial, preprocessed);
3769     };
3770     ThParser.evaluate = function(expr, partial, element) {
3771         return thymol.ThParser.parse(expr, partial, false).evaluate(element);
3772     };
3773     ThParser.Expression = Expression;
3774     ThParser.values = {
3775         sin: Math.sin,
3776         cos: Math.cos,
3777         tan: Math.tan,
3778         asin: Math.asin,
3779         acos: Math.acos,
3780         atan: Math.atan,
3781         sqrt: Math.sqrt,
3782         log: Math.log,
3783         abs: Math.abs,
3784         ceil: Math.ceil,
3785         floor: Math.floor,
3786         round: Math.round,
3787         random: random,
3788         fac: fac,
3789         exp: Math.exp,
3790         min: Math.min,
3791         max: Math.max,
3792         pow: Math.pow,
3793         E: Math.E,
3794         PI: Math.PI
3795     };
3796     var PRIMARY = 1 << 0;
3797     var OPERATOR = 1 << 1;
3798     var FUNCTION = 1 << 2;
3799     var LPAREN = 1 << 3;
3800     var RPAREN = 1 << 4;
3801     var COMMA = 1 << 5;
3802     var SIGN = 1 << 6;
3803     var CALL = 1 << 7;
3804     var NULLARY_CALL = 1 << 8;
3805     var LBRACK = 1 << 9;
3806     var RBRACK = 1 << 10;
3807     var LVARBRK = 1 << 11;
3808     var RVARBRK = 1 << 11;
3809     var OPTION = 1 << 12;
3810     var ASSIGN = 1 << 13;
3811     ThParser.prototype = {
3812         parse: function(expr, partial, preprocessed) {
3813             this.errormsg = "";
3814             this.success = true;
3815             var operstack = [];
3816             var tokenstack = [];
3817             var modestack = [];
3818             this.tmpprio = 0;
3819             var expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | OPERATOR | SIGN | OPTION;
3820             var noperators = 0;
3821             this.expression = expr;
3822             this.pos = 0;
3823             this.mode = 0;
3824             while (this.pos < this.expression.length) {
3825                 if (this.isWhite()) {} else if (this.isOperator()) {
3826                     if (this.isSign() && expected & SIGN) {
3827                         if (this.isNegativeSign()) {
3828                             this.tokenprio = 6;
3829                             this.tokenindex = "-";
3830                             noperators++;
3831                             this.addfunc(tokenstack, operstack, TOP1);
3832                         }
3833                         expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
3834                     } else if (this.isAssign() && expected & ASSIGN) {
3835                         noperators++;
3836                         expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
3837                     } else if (this.isComment()) {} else {
3838                         if (this.tokenindex == "!") {
3839                             if ((expected & SIGN) === 0) {
3840                                 this.error_parsing(this.pos, "unexpected sign");
3841                             }
3842                             noperators += 1;
3843                             this.addfunc(tokenstack, operstack, TOP1);
3844                         } else {
3845                             if ((expected & OPERATOR) === 0) {
3846                                 this.error_parsing(this.pos, "unexpected operator");
3847                             }
3848                             noperators += 2;
3849                             this.addfunc(tokenstack, operstack, TOP2);
3850                         }
3851                         if (this.expression.charAt(this.pos - 1) === "[") {
3852                             this.tmpprio += 20;
3853                         }
3854                         expected = PRIMARY | OPERATOR | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
3855                     }
3856                 } else if (this.isNumber()) {
3857                     if ((expected & PRIMARY) === 0) {
3858                         this.error_parsing(this.pos, "unexpected number");
3859                     }
3860                     var token = new Token(TNUMBER, 0, 0, this.tokennumber);
3861                     tokenstack.push(token);
3862                     expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA;
3863                 } else if (this.isLeftParenth()) {
3864                     if ((expected & LPAREN) === 0) {
3865                         this.error_parsing(this.pos, 'unexpected "("');
3866                     }
3867                     modestack.push(this.mode);
3868                     if (expected & CALL) {
3869                         noperators += 2;
3870                         this.tokenprio = -2;
3871                         this.tokenindex = -1;
3872                         this.tmpprio += 2;
3873                         var ft = TFUNCALL;
3874                         if (this.mode === 4) {
3875                             ft = MSGSUBST;
3876                             this.mode = 5;
3877                         } else if (this.mode === 2) {
3878                             ft = ARGLIST;
3879                             this.mode = 6;
3880                             var url = tokenstack[tokenstack.length - 1];
3881                             if (!url.meta_) {
3882                                 url.meta_ = {};
3883                             }
3884                             this.meta = url.meta_;
3885                         } else {
3886                             this.mode = 5;
3887                         }
3888                         this.addfunc(tokenstack, operstack, ft);
3889                         this.tmpprio -= 2;
3890                     }
3891                     if (this.mode === 5 || this.mode === 6) {
3892                         this.tmpprio += 10;
3893                     }
3894                     expected = PRIMARY | OPERATOR | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION | NULLARY_CALL;
3895                 } else if (this.isRightParenth()) {
3896                     if (expected & NULLARY_CALL) {
3897                         var token = new Token(TNUMBER, 0, 0, []);
3898                         tokenstack.push(token);
3899                     } else if ((expected & RPAREN) === 0) {
3900                         this.error_parsing(this.pos, 'unexpected ")"');
3901                     }
3902                     if (this.mode === 5 || this.mode === 6) {
3903                         this.tmpprio -= 10;
3904                     }
3905                     this.mode = modestack.pop();
3906                     expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
3907                 } else if (this.isRightBracket()) {
3908                     if ((expected & RBRACK) === 0) {
3909                         this.error_parsing(this.pos, 'unexpected "]"');
3910                     }
3911                     expected = OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
3912                 } else if (this.isLeftVarBrk(modestack)) {
3913                     if ((expected & LVARBRK) === 0) {
3914                         this.error_parsing(this.pos, 'unexpected "{"');
3915                     }
3916                     noperators += 1;
3917                     this.addfunc(tokenstack, operstack, TOP1);
3918                     expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
3919                 } else if (this.isRightVarBrk()) {
3920                     if ((expected & RVARBRK) === 0) {
3921                         this.error_parsing(this.pos, 'unexpected "}"');
3922                     }
3923                     this.mode = modestack.pop();
3924                     expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | LVARBRK | CALL | OPTION;
3925                 } else if (this.isLeftCurly()) {
3926                     if (this.mode == 1 || this.mode == 2 || this.mode == 3 || this.mode == 4) {
3927                         modestack.push(this.mode);
3928                         this.mode = 7;
3929                     } else {
3930                         this.error_parsing(this.pos, 'unexpected "{"');
3931                     }
3932                 } else if (this.isRightCurly()) {
3933                     if (this.mode == 7) {
3934                         this.mode = modestack.pop();
3935                     } else {
3936                         this.error_parsing(this.pos, 'unexpected "}"');
3937                     }
3938                 } else if (this.isComma()) {
3939                     if ((expected & COMMA) === 0) {
3940                         this.error_parsing(this.pos, 'unexpected ","');
3941                     }
3942                     if (!!partial) {
3943                         break;
3944                     }
3945                     if (this.mode === 5 || this.mode === 6) {
3946                         this.tmpprio -= 10;
3947                     }
3948                     this.tmpprio += 2;
3949                     this.addfunc(tokenstack, operstack, TOP2);
3950                     this.tmpprio -= 2;
3951                     if (this.mode === 5 || this.mode === 6) {
3952                         this.tmpprio += 10;
3953                     }
3954                     noperators += 2;
3955                     expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | SIGN | OPTION;
3956                 } else if (this.isConst()) {
3957                     if ((expected & PRIMARY) === 0) {
3958                         this.error_parsing(this.pos, "unexpected constant");
3959                     }
3960                     var consttoken = new Token(TNUMBER, 0, 0, this.tokennumber);
3961                     tokenstack.push(consttoken);
3962                     expected = OPERATOR | RPAREN | RVARBRK | RBRACK | COMMA;
3963                 } else {
3964                     var str = getStr(this.pos, this.expression, this.mode, partial, preprocessed);
3965                     if (this.isOpX(str, this.ops2) && (this.mode !== 2 && "/" !== str)) {
3966                         if ("and" === str.str || "or" === str.str) {
3967                             this.tokenprio = 3;
3968                         }
3969                         if ((expected & OPERATOR) === 0) {
3970                             this.error_parsing(this.pos, "unexpected binary operator");
3971                         }
3972                         this.addfunc(tokenstack, operstack, TOP2);
3973                         noperators += 2;
3974                         expected = PRIMARY | LPAREN | LVARBRK | FUNCTION | OPERATOR | SIGN | OPTION;
3975                     } else if (this.isOpX(str, this.ops1)) {
3976                         if ((expected & OPERATOR) === 0) {
3977                             this.error_parsing(this.pos, "unexpected unary operator");
3978                         }
3979                         this.addfunc(tokenstack, operstack, TOP1);
3980                         noperators++;
3981                         expected = PRIMARY | LPAREN | LVARBRK | FUNCTION;
3982                     } else if (this.isLiteralValue(str)) {
3983                         if ((expected & PRIMARY) === 0) {
3984                             this.error_parsing(this.pos, "unexpected literal value");
3985                         }
3986                         var token = new Token(TNUMBER, 0, 0, this.tokennumber);
3987                         tokenstack.push(token);
3988                         expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | RVARBRK | LBRACK | CALL | OPTION;
3989                         if (this.mode === 6) {
3990                             expected = expected | ASSIGN;
3991                         }
3992                     } else if (this.isVar(str)) {
3993                         if ((expected & PRIMARY) === 0) {
3994                             this.error_parsing(this.pos, "unexpected variable");
3995                         }
3996                         var vartoken = new Token(TVAR, this.tokenindex, 0, 0, this.mode, str.meta);
3997                         tokenstack.push(vartoken);
3998                         expected = FUNCTION | OPERATOR | RPAREN | RBRACK | RVARBRK | COMMA | LPAREN | RVARBRK | LBRACK | CALL | OPTION | ASSIGN;
3999                     } else {
4000                         if (this.errormsg === "") {
4001                             this.error_parsing(this.pos, "unknown character");
4002                         } else {
4003                             this.error_parsing(this.pos, this.errormsg);
4004                         }
4005                     }
4006                 }
4007             }
4008             if (this.tmpprio < 0 || this.tmpprio >= 10) {
4009                 this.error_parsing(this.pos, 'unmatched "() or []"');
4010             }
4011             while (operstack.length > 0) {
4012                 var tmp = operstack.pop();
4013                 tokenstack.push(tmp);
4014             }
4015             if (noperators + 1 !== tokenstack.length) {
4016                 this.error_parsing(this.pos, "parity");
4017             }
4018             var res = new Expression(tokenstack, object(this.ops1), object(this.ops2), object(this.functions), this.precision, this.pos);
4019             return res;
4020         },
4021         evaluate: function(expr, element) {
4022             return this.parse(expr).evaluate(element);
4023         },
4024         error_parsing: function(column, msg) {
4025             this.success = false;
4026             this.errormsg = "parse error [column " + column + "]: " + msg;
4027             throw new Error(this.errormsg);
4028         },
4029         addfunc: function(tokenstack, operstack, type_) {
4030             var operator = new Token(type_, this.tokenindex, this.tokenprio + this.tmpprio, 0, this.mode, this.meta);
4031             while (operstack.length > 0) {
4032                 if (operator.prio_ <= operstack[operstack.length - 1].prio_) {
4033                     tokenstack.push(operstack.pop());
4034                 } else {
4035                     break;
4036                 }
4037             }
4038             operstack.push(operator);
4039         },
4040         isNumber: function() {
4041             var r = false;
4042             var str = "";
4043             var prec = -1;
4044             while (this.pos < this.expression.length) {
4045                 var code = this.expression.charCodeAt(this.pos);
4046                 if (code >= 48 && code <= 57 || code === 46) {
4047                     str += this.expression.charAt(this.pos);
4048                     if (prec >= 0 || code === 46) {
4049                         prec++;
4050                     }
4051                     this.pos++;
4052                     r = true;
4053                 } else {
4054                     break;
4055                 }
4056             }
4057             if (r) {
4058                 if (prec >= 0 && (typeof this.precision === "undefined" || prec > this.precision)) {
4059                     this.precision = prec;
4060                 }
4061                 this.tokennumber = parseFloat(str);
4062             }
4063             return r;
4064         },
4065         isConst: function() {
4066             var str;
4067             for (var i in this.consts) {
4068                 if (true) {
4069                     var L = i.length;
4070                     str = this.expression.substr(this.pos, L);
4071                     if (i === str) {
4072                         this.tokennumber = this.consts[i];
4073                         this.pos += L;
4074                         return true;
4075                     }
4076                 }
4077             }
4078             return false;
4079         },
4080         isOperator: function() {
4081             var ch = this.expression.charAt(this.pos);
4082             if (ch === "+") {
4083                 this.tokenprio = 0;
4084                 this.tokenindex = "+";
4085             } else if (ch === "-") {
4086                 this.tokenprio = 0;
4087                 this.tokenindex = "-";
4088             } else if (ch === "|") {
4089                 if (this.expression.charAt(this.pos + 1) === "|") {
4090                     this.pos++;
4091                     this.tokenprio = 0;
4092                     this.tokenindex = "||";
4093                 } else {
4094                     return false;
4095                 }
4096             } else if (ch === "*") {
4097                 if (this.expression.charAt(this.pos + 1) === "{") {
4098                     return false;
4099                 }
4100                 this.tokenprio = 1;
4101                 this.tokenindex = "*";
4102             } else if (ch === "/" && this.mode != 2 && this.pos > 0) {
4103                 this.tokenprio = 2;
4104                 this.tokenindex = "/";
4105             } else if (ch === "%") {
4106                 this.tokenprio = 2;
4107                 this.tokenindex = "%";
4108             } else if (ch === "^") {
4109                 this.tokenprio = 3;
4110                 this.tokenindex = "^";
4111             } else if (ch === "=" || ch === "!") {
4112                 if (this.expression.charAt(this.pos + 1) === "=") {
4113                     if (ch === "=") {
4114                         this.tokenindex = "==";
4115                     } else if (ch === "!") {
4116                         this.tokenindex = "!=";
4117                     } else {
4118                         return false;
4119                     }
4120                     this.pos++;
4121                     this.tokenprio = 6;
4122                 } else if (ch === "!") {
4123                     this.tokenprio = 7;
4124                     this.tokenindex = "!";
4125                 } else if (ch === "=") {
4126                     this.tokenindex = "=";
4127                 } else {
4128                     return false;
4129                 }
4130             } else if (ch === "<") {
4131                 if (this.expression.charAt(this.pos + 1) === "=") {
4132                     this.tokenindex = "<=";
4133                     this.pos++;
4134                 } else {
4135                     this.tokenindex = "<";
4136                 }
4137                 this.tokenprio = 4;
4138             } else if (ch === ">") {
4139                 if (this.expression.charAt(this.pos + 1) === "=") {
4140                     this.tokenindex = ">=";
4141                     this.pos++;
4142                 } else {
4143                     this.tokenindex = ">";
4144                 }
4145                 this.tokenprio = 4;
4146             } else if (ch === "." || ch === "[") {
4147                 this.tokenprio = 10;
4148                 this.tokenindex = ".";
4149             } else {
4150                 return false;
4151             }
4152             this.pos++;
4153             return true;
4154         },
4155         isRightBracket: function() {
4156             var code = this.expression.charCodeAt(this.pos);
4157             if (code === 93) {
4158                 this.pos++;
4159                 this.tmpprio -= 20;
4160                 return true;
4161             }
4162             return false;
4163         },
4164         isSign: function() {
4165             var code = this.expression.charCodeAt(this.pos - 1);
4166             if (code === 45 || code === 43) {
4167                 return true;
4168             }
4169             return false;
4170         },
4171         isAssign: function() {
4172             var code = this.expression.charCodeAt(this.pos - 1);
4173             if (code === 61) {
4174                 var cha = this.expression.charAt(this.pos - 2);
4175                 if (cha === "!" || cha === ">" || cha === "<" || cha === "=") {
4176                     return false;
4177                 }
4178                 cha = this.expression.charAt(this.pos);
4179                 if (cha === ">" || cha === "<" || cha === "=") {
4180                     return false;
4181                 }
4182                 return true;
4183             }
4184             return false;
4185         },
4186         isPositiveSign: function() {
4187             var code = this.expression.charCodeAt(this.pos - 1);
4188             if (code === 43) {
4189                 return true;
4190             }
4191             return false;
4192         },
4193         isNegativeSign: function() {
4194             var code = this.expression.charCodeAt(this.pos - 1);
4195             if (code === 45) {
4196                 return true;
4197             }
4198             return false;
4199         },
4200         isLeftParenth: function() {
4201             var code = this.expression.charCodeAt(this.pos);
4202             if (code === 40) {
4203                 this.pos++;
4204                 this.tmpprio += 10;
4205                 return true;
4206             }
4207             return false;
4208         },
4209         isRightParenth: function() {
4210             var code = this.expression.charCodeAt(this.pos);
4211             if (code === 41) {
4212                 this.pos++;
4213                 this.tmpprio -= 10;
4214                 return true;
4215             }
4216             return false;
4217         },
4218         isLeftCurly: function() {
4219             var code = this.expression.charCodeAt(this.pos);
4220             if (code === 123) {
4221                 this.pos++;
4222                 this.tmpprio += 10;
4223                 return true;
4224             }
4225             return false;
4226         },
4227         isRightCurly: function() {
4228             var code = this.expression.charCodeAt(this.pos);
4229             if (code === 125) {
4230                 this.pos++;
4231                 this.tmpprio -= 10;
4232                 return true;
4233             }
4234             return false;
4235         },
4236         isComma: function() {
4237             var code = this.expression.charCodeAt(this.pos);
4238             if (code === 44) {
4239                 this.pos++;
4240                 this.tokenprio = -1;
4241                 this.tokenindex = ",";
4242                 return true;
4243             }
4244             return false;
4245         },
4246         isWhite: function() {
4247             var code = this.expression.charCodeAt(this.pos);
4248             if (code === 32 || code === 9 || code === 10 || code === 13) {
4249                 this.pos++;
4250                 return true;
4251             }
4252             return false;
4253         },
4254         isLeftVarBrk: function(modestack) {
4255             var pp = this.pos, ch = this.expression.charAt(pp);
4256             if (ch === "$" || ch === "@" || ch === "*" || ch === "#") {
4257                 pp++;
4258                 var ch2 = this.expression.charAt(pp);
4259                 if (ch2 === "{") {
4260                     pp++;
4261                     this.tmpprio += 10;
4262                     this.tokenprio = -4;
4263                     var oldMode = this.mode;
4264                     modestack.push(oldMode);
4265                     if (ch === "$") {
4266                         this.mode = 1;
4267                     } else if (ch === "@") {
4268                         this.mode = 2;
4269                     } else if (ch === "*") {
4270                         this.mode = 3;
4271                     } else if (ch === "#") {
4272                         this.mode = 4;
4273                     }
4274                     this.tokenindex = "{";
4275                     this.pos = pp;
4276                     return true;
4277                 }
4278             }
4279             return false;
4280         },
4281         isRightVarBrk: function() {
4282             var code = this.expression.charCodeAt(this.pos);
4283             if (code === 125) {
4284                 this.pos++;
4285                 this.tmpprio -= 10;
4286                 return true;
4287             }
4288             return false;
4289         },
4290         isOpX: function(str, group) {
4291             if (str.str.length > 0) {
4292                 if (str.str in new Object()) {
4293                     return false;
4294                 }
4295                 if (str.str in group) {
4296                     this.tokenindex = str.str;
4297                     this.tokenprio = 5;
4298                     this.pos = str.pos;
4299                     return true;
4300                 }
4301             }
4302             return false;
4303         },
4304         isLiteralValue: function(str) {
4305             if (typeof str.str === "string") {
4306                 var first = str.str.charAt(0);
4307                 var last = str.str.charAt(str.str.length - 1);
4308                 if (first == "'" && last == "'" || first == '"' && last == '"') {
4309                     this.tokennumber = str.str.substring(1, str.str.length - 1);
4310                     this.pos = str.pos;
4311                     return true;
4312                 }
4313             }
4314             return false;
4315         },
4316         isVar: function(str) {
4317             if (str.str.length > 0) {
4318                 this.tokenindex = str.str;
4319                 this.tokenprio = 4;
4320                 this.pos = str.pos;
4321                 return true;
4322             }
4323             return false;
4324         },
4325         isComment: function() {
4326             var code = this.expression.charCodeAt(this.pos - 1);
4327             if (code === 47 && this.expression.charCodeAt(this.pos) === 42) {
4328                 this.pos = this.expression.indexOf("*/", this.pos) + 2;
4329                 if (this.pos === 1) {
4330                     this.pos = this.expression.length;
4331                 }
4332                 return true;
4333             }
4334             return false;
4335         }
4336     };
4337     return ThParser;
4338 }();
4339
4340 (function() {
4341     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" ];
4342     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" ];
4343     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" ];
4344     var literalTokenExpr = /^[a-zA-Z0-9\[\]\.\-_]*$/;
4345     var numericExpr = /^[+\-]?[0-9]*?[.]?[0-9]*?$/;
4346     var nonURLExpr = /[\$\*#]{1}\{(?:!?[^}]*)\}/;
4347     var varExpr = /[\$\*#@]{1}\{(!?[^}]*)\}/;
4348     var textInlineCommentExpr = /\[\[(.*)\]\]/;
4349     var javascriptInlineCommentExpr = /\/\*\[\[(.*)\]\]\*\//;
4350     var javascriptInlineRemainderExpr = /\s*(?:['][^']*['])*(?:["][^"]*["])*(?:[\(][^\(\)]*[\)])*(?:[\{][^\{\}]*[\}])*(?:[\[][^\[\]]*[\]])*((?:[;,\(\)\[\]:\{\}](?=(?:\s*\/\/.*?(?:\n|$)))(?:\s*\/\/.*?(?:\n|$)))|(?:\s*\/\/.*?(?:\n|$))|(?:[;,\(\)\[\]:\{\}](?=(?:\s*(?:\n|$)))(?:\s*(?:\n|$)))|(?:\s*(?:\n|$)))/;
4351     var thCase;
4352     thymol.getThAttribute = function(part, element) {
4353         var result = thymol.ThUtils.unParenthesise(part);
4354         result = thymol.doExpression(result, element);
4355         if (Object.prototype.toString.call(result) === "[object Array]") {
4356             if (result.length === 1) {
4357                 result = result[0];
4358             }
4359         }
4360         if (result instanceof thymol.ThParam) {
4361             result = result.value;
4362         }
4363         return result;
4364     };
4365     thymol.doExpression = function(part, element) {
4366         var result = thymol.ThUtils.unParenthesise(part), expr, unq, token, mapped;
4367         expr = null;
4368         unq = thymol.ThUtils.unQuote(result);
4369         if (unq != result) {
4370             result = thymol.preProcess(unq, element);
4371         } else {
4372             if (literalTokenExpr.test(result)) {
4373                 token = thymol.booleanAndNullTokens[result];
4374                 if (!(typeof token === "undefined")) {
4375                     result = token;
4376                 } else {
4377                     if (result.match(numericExpr)) {
4378                         result = thymol.ThUtils.getToPrecision(result, thymol.ThUtils.getDecimalDigits(result));
4379                     } else {
4380                         expr = thymol.getExpression(result, element);
4381                         if (expr !== undefined && expr !== null && !(expr != expr)) {
4382                             result = expr;
4383                         }
4384                     }
4385                 }
4386             } else {
4387                 expr = thymol.getExpression(result, element);
4388                 if (expr !== null && !(expr != expr)) {
4389                     result = expr;
4390                 } else {
4391                     result = null;
4392                 }
4393             }
4394         }
4395         return result;
4396     };
4397     thymol.processText = function(element, thUrlAttr, thAttr) {
4398         var url = thymol.getThAttribute(thUrlAttr.value, element), updated = false, text, newTextNode, i, iLimit, iUpper;
4399         if (url == null) {
4400             if (!thymol.allowNullText) {
4401                 if (thymol.debug) {
4402                     thymol.thWindow.alert("thymol.processText cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
4403                 }
4404                 return updated;
4405             }
4406             url = "";
4407         } else {
4408             if (url instanceof thymol.ThParam || url instanceof thymol.ThObject) {
4409                 if (url.value) {
4410                     url = url.value;
4411                 }
4412             } else if (url instanceof thymol.ThClass && url.abort) {
4413                 element.removeAttribute(thUrlAttr.name);
4414                 return true;
4415             }
4416         }
4417         try {
4418             while (element.firstChild != null) {
4419                 element.removeChild(element.firstChild);
4420                 updated = true;
4421                 if (element.firstChild == null) {
4422                     break;
4423                 }
4424             }
4425             if ("text" == thAttr.suffix) {
4426                 if (Object.prototype.toString.call(url) === "[object Array]") {
4427                     text = "[";
4428                     for (i = 0, iLimit = url.length, iUpper = url.length - 1; i < iLimit; i++) {
4429                         text += url[i].toString();
4430                         if (i < iUpper) {
4431                             text += ", ";
4432                         }
4433                     }
4434                     text += "]";
4435                 } else {
4436                     text = url.toString();
4437                 }
4438                 text = thymol.ThUtils.unescape(text);
4439                 newTextNode = element.ownerDocument.createTextNode(text);
4440                 element.appendChild(newTextNode);
4441                 updated = true;
4442             }
4443             if ("utext" == thAttr.suffix) {
4444                 element.innerHTML = url;
4445             }
4446             element.removeAttribute(thUrlAttr.name);
4447         } catch (err) {
4448             if (thymol.debug) {
4449                 thymol.thWindow.alert("text replace error");
4450             }
4451         }
4452         return updated;
4453     };
4454     thymol.processSpecAttrMod = function(element, thUrlAttr, thAttrObj) {
4455         var url = thymol.getThAttribute(thUrlAttr.value, element);
4456         if (!url || !(url instanceof thymol.ThClass) || !url.abort) {
4457             element.setAttribute(thAttrObj.suffix, url);
4458         }
4459         element.removeAttribute(thUrlAttr.name);
4460     };
4461     thymol.processAttr = function(element, thUrlAttr, thAttrObj) {
4462         var argValue = thUrlAttr.value.trim(), argsExpr, expr, identifier, attrName = null, ep, lp, url, tt;
4463         if (argValue) {
4464             do {
4465                 argsExpr = thymol.ThParser.parse(argValue, true, false);
4466                 identifier = argsExpr.tokens.shift();
4467                 if (identifier.type_ === 3) {
4468                     attrName = identifier.index_;
4469                     if (!!attrName) {
4470                         ep = argValue.indexOf("=");
4471                         if (ep >= 0) {
4472                             lp = argsExpr.position - 1;
4473                             if (argsExpr.position === argValue.length) {
4474                                 lp = argValue.position;
4475                             }
4476                             expr = argValue.substring(ep + 1, lp).trim();
4477                             if (fixedValBoolAttrList.indexOf(attrName) >= 0) {
4478                                 thymol.doFixedValBoolAttr(expr, element, attrName);
4479                             } else {
4480                                 url = thymol.getThAttribute(expr, element);
4481                                 tt = typeof url;
4482                                 if (thAttrObj.suffix == "attrappend" || thAttrObj.suffix == "attrprepend") {
4483                                     if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
4484                                         existing = element.getAttribute(attrName);
4485                                         if (existing) {
4486                                             if (thAttrObj.suffix == "attrappend") {
4487                                                 url = existing + url;
4488                                             } else if (thAttrObj.suffix == "attrprepend") {
4489                                                 url = url + existing;
4490                                             }
4491                                         }
4492                                     }
4493                                 }
4494                                 if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
4495                                     element.setAttribute(attrName, url);
4496                                 }
4497                             }
4498                         }
4499                     }
4500                     argValue = argValue.substring(argsExpr.position);
4501                 } else {
4502                     break;
4503                 }
4504             } while (argValue.length > 0);
4505         }
4506         element.removeAttribute(thUrlAttr.name);
4507     };
4508     thymol.processCSSAttr = function(element, thUrlAttr, thAttrObj) {
4509         var parts = thUrlAttr.value.split(","), i, iLimit, expr, attrName, url, tt, existing;
4510         for (i = 0, iLimit = parts.length; i < iLimit; i++) {
4511             expr = parts[i];
4512             attrName = thAttrObj.suffix == "classappend" ? "class" : "style";
4513             if (!!attrName) {
4514                 if (!!expr) {
4515                     url = thymol.getThAttribute(expr, element);
4516                     tt = typeof url;
4517                     if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
4518                         existing = element.getAttribute(attrName);
4519                         if (existing) {
4520                             url = existing + " " + url;
4521                         }
4522                     }
4523                     if (url !== null && (tt === "number" || tt === "string" && url.length > 0)) {
4524                         element.setAttribute(attrName, url);
4525                     }
4526                 }
4527             }
4528         }
4529         element.removeAttribute(thUrlAttr.name);
4530     };
4531     thymol.processFixedValBoolAttr = function(element, thUrlAttr, thAttrObj) {
4532         var val = thymol.doFixedValBoolAttr(thUrlAttr.value, element, thAttrObj.suffix);
4533         if (val != null) {
4534             element.removeAttribute(thUrlAttr.name);
4535         } else {
4536             if (thymol.debug) {
4537                 thymol.thWindow.alert("thymol.processFixedValBoolAttr cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
4538             }
4539         }
4540     };
4541     thymol.doFixedValBoolAttr = function(valParam, element, attr) {
4542         var val = thymol.getBoolean(valParam, element);
4543         if (val) {
4544             element.setAttribute(attr, attr);
4545         }
4546         return val;
4547     };
4548     thymol.processPairedAttr = function(element, thUrlAttr, thAttrObj) {
4549         var url = thymol.getThAttribute(thUrlAttr.value, element);
4550         if (url != "") {
4551             if (thAttrObj.suffix === "alt-title") {
4552                 element.setAttribute("alt", url);
4553                 element.setAttribute("title", url);
4554             }
4555             if (thAttrObj.suffix === "lang-xmllang") {
4556                 element.setAttribute("lang", url);
4557                 element.setAttribute("xml:lang", url);
4558             }
4559             element.removeAttribute(thUrlAttr.name);
4560         } else {
4561             if (thymol.debug) {
4562                 thymol.thWindow.alert("thymol.processPairedAttr cannot process: " + thUrlAttr.name + '="' + thUrlAttr.value + '"\n' + element.innerHTML);
4563             }
4564         }
4565     };
4566     thymol.processConditional = function(element, attr, thAttrObj) {
4567         var removed = false;
4568         if (attr.value) {
4569             removed = thymol.doIfOrUnless(element, attr.value, thAttrObj.suffix === "if");
4570         }
4571         element.removeAttribute(attr.name);
4572         return removed;
4573     };
4574     thymol.doIfOrUnless = function(element, value, isIf) {
4575         var processed = false, flag;
4576         if (value) {
4577             flag = thymol.getBoolean(value, element);
4578             processed = true;
4579             if (!flag) {
4580                 if (isIf) {
4581                     element.parentNode.removeChild(element);
4582                     return true;
4583                 }
4584             } else {
4585                 if (!isIf) {
4586                     element.parentNode.removeChild(element);
4587                     return true;
4588                 }
4589             }
4590         }
4591         if (!processed && thymol.debug) {
4592             thymol.thWindow.alert("thymol.processConditional cannot process conditional: " + value + "\n" + element.innerHTML);
4593         }
4594         return false;
4595     };
4596     thymol.processEach = function(element, thUrlAttr, junk) {
4597         var elementsUpdated = false, initial = thUrlAttr.value.trim(), colonPos, varName, varNames, statVarName, expr, root, node, i, iLimit, tho, stat, count, newNode, next;
4598         colonPos = initial.indexOf(":");
4599         if (colonPos > 0) {
4600             varName = initial.substring(0, colonPos);
4601             if (varName) {
4602                 varName = varName.trim();
4603                 varNames = varName.split(",");
4604                 varName = varNames[0].trim();
4605                 if (varNames.length > 1) {
4606                     statVarName = varNames[1].trim();
4607                 } else {
4608                     statVarName = varName + "Stat";
4609                 }
4610                 expr = initial.substr(colonPos + 1);
4611                 if (expr) {
4612                     expr = expr.trim();
4613                     expr = thymol.getExpression(expr, element);
4614                     if (expr instanceof thymol.ThSet) {
4615                         expr = expr.toArray();
4616                     }
4617                     root = element.parentNode;
4618                     if (expr && expr instanceof Object && expr.length > 0) {
4619                         node = element;
4620                         iLimit = expr.length;
4621                         element.removeAttribute(thUrlAttr.name);
4622                         for (i = 0; i < iLimit; i++) {
4623                             tho = expr[i];
4624                             stat = new Object();
4625                             stat.current = tho;
4626                             stat.size = expr.length;
4627                             stat.index = i;
4628                             count = i + 1;
4629                             stat.count = count;
4630                             if (i == 0) {
4631                                 stat.first = true;
4632                             } else {
4633                                 stat.first = false;
4634                             }
4635                             if (i == expr.length - 1) {
4636                                 stat.last = true;
4637                             } else {
4638                                 stat.last = false;
4639                             }
4640                             if (i % 2) {
4641                                 stat.odd = true;
4642                                 stat.even = false;
4643                             } else {
4644                                 stat.odd = false;
4645                                 stat.even = true;
4646                             }
4647                             if (!node.thLocalVars) {
4648                                 node.thLocalVars = {};
4649                             }
4650                             node.thLocalVars[varName] = tho;
4651                             node.thLocalVars[statVarName] = stat;
4652                             if (count < expr.length) {
4653                                 newNode = element.cloneNode(true);
4654                                 if (node.nextElementSibling != null) {
4655                                     next = root.insertBefore(newNode, node.nextElementSibling);
4656                                 } else {
4657                                     next = root.appendChild(newNode);
4658                                 }
4659                                 node = next;
4660                                 elementsUpdated = true;
4661                             }
4662                         }
4663                     } else {
4664                         if (root !== null) {
4665                             if (!element.thLocalVars) {
4666                                 element.thLocalVars = {};
4667                             }
4668                             if (!element.thLocalVars[varName]) {
4669                                 element.thLocalVars[varName] = new Object();
4670                             }
4671                             if (!element.thLocalVars[statVarName]) {
4672                                 element.thLocalVars[statVarName] = new Object();
4673                             }
4674                             root.removeChild(element);
4675                             elementsUpdated = true;
4676                         }
4677                     }
4678                 }
4679             }
4680         }
4681         return elementsUpdated;
4682     };
4683     thymol.processObject = function(element, thUrlAttr) {
4684         var argValue = thUrlAttr.value.trim(), val;
4685         if (argValue) {
4686             val = thymol.getExpression(argValue, element);
4687             if (val) {
4688                 element.thObjectVar = val;
4689             }
4690         }
4691         element.removeAttribute(thUrlAttr.name);
4692     };
4693     thymol.processInline = function(element, thUrlAttr, thAttrObj) {
4694         var mode = thymol.getThAttribute(thUrlAttr.value, element);
4695         if (mode == "text") {
4696             thymol.doInlineText(element);
4697         } else if (mode == "javascript" || mode == "dart") {
4698             thymol.doInlineJavascript(element);
4699         } else {
4700             if (thymol.debug) {
4701                 thymol.thWindow.alert('thymol.processInline cannot process scripting mode: "' + mode + '" - it isn\'t supported by version "' + thymol.thVersion + '"\n');
4702             }
4703         }
4704         element.removeAttribute(thUrlAttr.name);
4705     };
4706     thymol.doInlineText = function(element) {
4707         var changed, value, i, iLimit, expr, term, result;
4708         for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
4709             do {
4710                 changed = false;
4711                 if (element.childNodes[i].nodeType == 1) {
4712                     thymol.doInlineText(element.childNodes[i]);
4713                 } else if (element.childNodes[i].nodeType == 3) {
4714                     value = element.childNodes[i].nodeValue;
4715                     if (value) {
4716                         expr = textInlineCommentExpr.exec(value);
4717                         if (expr) {
4718                             term = "";
4719                             if (expr.length > 1) {
4720                                 term = "[[" + expr[1] + "]]";
4721                             }
4722                             if (expr.length > 1) {
4723                                 result = thymol.getThAttribute(expr[1], element);
4724                                 result = value.replace(term, result);
4725                                 element.childNodes[i].nodeValue = result;
4726                                 changed = true;
4727                             }
4728                             expr = null;
4729                         }
4730                     }
4731                 }
4732             } while (changed);
4733         }
4734     };
4735     thymol.doInlineJavascript = function(element) {
4736         var changed, value, second, i, iLimit, expr, scraps, remainder, termIndx, term, secondIndx, result;
4737         for (i = 0, iLimit = element.childNodes.length; i < iLimit; i++) {
4738             do {
4739                 second = null;
4740                 changed = false;
4741                 value = element.childNodes[i].nodeValue;
4742                 if (value) {
4743                     expr = javascriptInlineCommentExpr.exec(value);
4744                     if (expr) {
4745                         termIndx = expr.index;
4746                         term = "";
4747                         if (expr.length > 1) {
4748                             term = "/*[[" + expr[1] + "]]*/";
4749                         }
4750                         termIndx = termIndx + term.length;
4751                         remainder = value.substring(termIndx);
4752                         scraps = javascriptInlineRemainderExpr.exec(remainder);
4753                         if (scraps) {
4754                             if (scraps.length > 1) {
4755                                 secondIndx = remainder.indexOf(scraps[1]);
4756                                 second = remainder.substring(secondIndx);
4757                                 value = value.substring(0, termIndx);
4758                                 value = value + second;
4759                             }
4760                         }
4761                         if (expr.length > 1) {
4762                             result = thymol.getExpression(expr[1], element);
4763                             if (result instanceof thymol.ThObject) {
4764                                 result = result.toNonThObject();
4765                             }
4766                             if (!thymol.ThUtils.isLiteral(result)) {
4767                                 result = thymol.getStringView(result);
4768                             }
4769                             result = value.replace(term, result);
4770                             element.childNodes[i].nodeValue = result;
4771                             changed = true;
4772                         }
4773                         expr = null;
4774                         scraps = null;
4775                     }
4776                 }
4777             } while (changed);
4778         }
4779     };
4780     thymol.getStringView = function(param) {
4781         var view = "", objType;
4782         if (typeof param === "string") {
4783             view = view + "'" + param + "'";
4784         } else if (typeof param === "number" || typeof param === "boolean") {
4785             view = view + param;
4786         } else if (typeof param === "object") {
4787             if (param instanceof Object) {
4788                 objType = Object.prototype.toString.call(param);
4789                 if ("[object Array]" == objType) {
4790                     view = thymol.getStringViewArray(param);
4791                 } else if ("[object Object]" == objType) {
4792                     view = thymol.getStringViewObject(param);
4793                 }
4794             }
4795         }
4796         return view;
4797     };
4798     thymol.getStringViewArray = function(param) {
4799         var view = "[", i, iLimit;
4800         for (i = 0, iLimit = param.length; i < iLimit; i++) {
4801             view = view + thymol.getStringView(param[i]);
4802             if (i < param.length - 1) {
4803                 view = view + ",";
4804             }
4805         }
4806         view = view + "]";
4807         return view;
4808     };
4809     thymol.getStringViewObject = function(param) {
4810         var view = "{", key = null;
4811         for (key in param) {
4812             if (key) {
4813                 if (view != "{") {
4814                     view = view + ",";
4815                 }
4816                 view = view + thymol.getStringView(key) + ":";
4817                 view = view + thymol.getStringView(param[key]);
4818             }
4819         }
4820         view = view + "}";
4821         return view;
4822     };
4823     thymol.processRemove = function(element, thUrlAttr) {
4824         var haveRemoved = false;
4825         var locals = element.thLocalVars, savedLocals = element.thLocalVars, arg, nodes, first;
4826         if (!locals) {
4827             locals = {};
4828         }
4829         if (!locals["tag"]) {
4830             locals["tag"] = "tag";
4831         }
4832         if (!locals["body"]) {
4833             locals["body"] = "body";
4834         }
4835         if (!locals["none"]) {
4836             locals["none"] = "none";
4837         }
4838         if (!locals["all"]) {
4839             locals["all"] = "all";
4840         }
4841         if (!locals["all-but-first"]) {
4842             locals["all-but-first"] = "all-but-first";
4843         }
4844         element.thLocalVars = locals;
4845         arg = thymol.getThAttribute(thUrlAttr.value, element);
4846         element.thLocalVars = savedLocals;
4847         element.removeAttribute(thUrlAttr.name);
4848         if ("all" == arg) {
4849             if (element.parentNode != null) {
4850                 element.parentNode.removeChild(element);
4851                 haveRemoved = true;
4852             }
4853         } else if ("body" == arg) {
4854             element.innerHTML = "";
4855             haveRemoved = true;
4856         } else if ("tag" == arg) {
4857             thymol.ThUtils.removeTag(element);
4858             haveRemoved = true;
4859         } else if ("all-but-first" == arg) {
4860             nodes = element.childNodes;
4861             first = true;
4862             $(nodes).each(function() {
4863                 if (this.nodeType == 1) {
4864                     if (!first) {
4865                         element.removeChild(this);
4866                         haveRemoved = true;
4867                     }
4868                     first = false;
4869                 }
4870             });
4871         } else if ("none" == arg || null == arg) {}
4872         return haveRemoved;
4873     };
4874     thymol.processSwitch = function(element, attr) {
4875         var val = thymol.ThUtils.unParenthesise(attr.value), updated = false, args, matched = false, thCaseSpecs, caseClause, remove, ccAttr;
4876         val = thymol.getThAttribute(val, element);
4877         if (typeof val === "string") {
4878             args = val.match(nonURLExpr);
4879             if (args) {
4880                 val = args[1];
4881             }
4882         }
4883         val = thymol.ThUtils.unQuote(val);
4884         thCaseSpecs = $(thCase.escpName, element);
4885         thCaseSpecs.each(function() {
4886             caseClause = this;
4887             remove = true;
4888             $(caseClause.attributes).each(function() {
4889                 ccAttr = this;
4890                 if (thCase.name == ccAttr.name || thCase.synonym == ccAttr.name) {
4891                     if (!matched) {
4892                         matched = thymol.processCase(element, ccAttr, val);
4893                         if (matched) {
4894                             remove = false;
4895                         }
4896                     }
4897                     caseClause.removeAttribute(ccAttr.name);
4898                 }
4899             });
4900             if (remove) {
4901                 element.removeChild(caseClause);
4902                 updated = true;
4903             }
4904         });
4905         return updated;
4906     };
4907     thymol.processCase = function(element, attr, param) {
4908         var val = thymol.substitute(attr.value, element);
4909         val = thymol.ThUtils.unQuote(val);
4910         if (val == "*" || param && param == val) {
4911             return true;
4912         }
4913         return false;
4914     };
4915     thymol.processWith = function(element, thUrlAttr) {
4916         thymol.getWith(element, thUrlAttr.value);
4917         element.removeAttribute(thUrlAttr.name);
4918     };
4919     thymol.processAssert = function(element, thUrlAttr) {
4920         var argValue = thUrlAttr.value.trim(), result = true, term = "", terms, i, iLimit, expr, val, flag;
4921         if (argValue) {
4922             terms = argValue.split(",");
4923             for (i = 0, iLimit = terms.length; i < iLimit; i++) {
4924                 term = terms[i];
4925                 expr = thymol.ThUtils.unParenthesise(term);
4926                 if (expr != null) {
4927                     val = thymol.getExpression(expr, element);
4928                     if (val) {
4929                         flag = thymol.getBoolean(val, element);
4930                         if (!flag) {
4931                             result = false;
4932                             break;
4933                         }
4934                     } else {
4935                         result = false;
4936                         break;
4937                     }
4938                 } else {
4939                     result = false;
4940                     break;
4941                 }
4942             }
4943         }
4944         if (!result) {
4945             if (argValue != term) {
4946                 argValue = " list is: " + argValue;
4947             } else {
4948                 argValue = "";
4949             }
4950             if (term != "") {
4951                 term = ' false term is: "' + term + '"';
4952             }
4953             if (thymol.debug) {
4954                 thymol.thWindow.alert("thymol.processAssert assertion failure -" + argValue + term + "\n");
4955             }
4956         }
4957         element.removeAttribute(thUrlAttr.name);
4958     };
4959     thymol.processFragment = function(element, thUrlAttr, thAttrObj) {
4960         element.removeAttribute(thUrlAttr.name);
4961     };
4962     thymol.getBoolean = function(param, element) {
4963         if (param == null) {
4964             return false;
4965         }
4966         if (typeof param === "boolean") {
4967             return param;
4968         } else if (typeof param === "number") {
4969             return param != 0;
4970         }
4971         var initial = thymol.ThUtils.unParenthesise(param), negate = false, val, args, flag;
4972         if (initial.charAt(0) == "!") {
4973             negate = true;
4974             initial = initial.substring(1, initial.length);
4975             initial = thymol.ThUtils.unParenthesise(initial);
4976         }
4977         val = thymol.getThAttribute(initial, element);
4978         if (val == null) {
4979             args = initial.match(varExpr);
4980             if (args) {
4981                 if (args[1].charAt(0) == "!") {
4982                     negate = !negate;
4983                 }
4984             }
4985         }
4986         flag = thymol.getBooleanValue(val);
4987         if (negate) {
4988             flag = !flag;
4989         }
4990         return flag;
4991     };
4992     thymol.appendToAttrList = function(func, prec, attrArray) {
4993         var j, jLimit = attrArray.length, tha = null;
4994         for (j = 0; j < jLimit; j++) {
4995             tha = new thymol.ThAttr(attrArray[j], func, prec, thymol.thThymeleafPrefixList, thymol.prefix);
4996         }
4997         j = tha;
4998     };
4999     thymol.setupAttrList = function() {
5000         thCase = new thymol.ThAttr("case", null, 275, thymol.thThymeleafPrefixList, thymol.prefix);
5001         thymol.addDialect({
5002             prefix: thymol.prefix,
5003             attributeProcessors: [ {
5004                 name: "each",
5005                 processor: thymol.processEach,
5006                 precedence: 200
5007             }, {
5008                 name: "switch",
5009                 processor: thymol.processSwitch,
5010                 precedence: 250
5011             }, {
5012                 name: "if",
5013                 processor: thymol.processConditional,
5014                 precedence: 300
5015             }, {
5016                 name: "unless",
5017                 processor: thymol.processConditional,
5018                 precedence: 400
5019             }, {
5020                 name: "object",
5021                 processor: thymol.processObject,
5022                 precedence: 500
5023             }, {
5024                 name: "with",
5025                 processor: thymol.processWith,
5026                 precedence: 600
5027             }, {
5028                 name: "attr",
5029                 processor: thymol.processAttr,
5030                 precedence: 700
5031             }, {
5032                 name: "attrprepend",
5033                 processor: thymol.processAttr,
5034                 precedence: 800
5035             }, {
5036                 name: "attrappend",
5037                 processor: thymol.processAttr,
5038                 precedence: 900
5039             }, {
5040                 name: "alt-title",
5041                 processor: thymol.processPairedAttr,
5042                 precedence: 990
5043             }, {
5044                 name: "lang-xmllang",
5045                 processor: thymol.processPairedAttr,
5046                 precedence: 990
5047             }, {
5048                 name: "inline",
5049                 processor: thymol.processInline,
5050                 precedence: 1e3
5051             }, {
5052                 name: "classappend",
5053                 processor: thymol.processCSSAttr,
5054                 precedence: 1100
5055             }, {
5056                 name: "styleappend",
5057                 processor: thymol.processCSSAttr,
5058                 precedence: 1100
5059             }, {
5060                 name: "text",
5061                 processor: thymol.processText,
5062                 precedence: 1300
5063             }, {
5064                 name: "utext",
5065                 processor: thymol.processText,
5066                 precedence: 1400
5067             }, {
5068                 name: "fragment",
5069                 processor: thymol.processFragment,
5070                 precedence: 1500
5071             }, {
5072                 name: "assert",
5073                 processor: thymol.processAssert,
5074                 precedence: 1550
5075             }, {
5076                 name: "remove",
5077                 processor: thymol.processRemove,
5078                 precedence: 1600
5079             } ]
5080         });
5081         thymol.appendToAttrList(thymol.processSpecAttrMod, 1e3, specAttrModList);
5082         thymol.appendToAttrList(thymol.processSpecAttrMod, 1e3, eventAttrList);
5083         thymol.appendToAttrList(thymol.processFixedValBoolAttr, 1e3, fixedValBoolAttrList);
5084     };
5085 })();
5086
5087 thymol.objects.thHttpSessionObject = function() {
5088     var thExpressionObjectName = "#httpSession";
5089     function getAttribute(name) {
5090         var result = thymol.sessionContext[name];
5091         return result;
5092     }
5093     function getParameter(name) {
5094         var result = thymol.sessionContext[name];
5095         return result;
5096     }
5097     function getServletContext() {
5098         var result = thymol.applicationContext;
5099         return result;
5100     }
5101     function getSessionContext() {
5102         var result = thymol.sessionContext;
5103         return result;
5104     }
5105     function getContextPath() {
5106         var result = "";
5107         return result;
5108     }
5109     function getRequestName() {
5110         var result = "";
5111         return result;
5112     }
5113     function getParameterValues(name) {
5114         var result = thymol.sessionContext[name];
5115         return result;
5116     }
5117     return {
5118         thExpressionObjectName: thExpressionObjectName,
5119         getAttribute: getAttribute,
5120         getParameter: getParameter,
5121         getServletContext: getServletContext,
5122         getSessionContext: getSessionContext,
5123         getContextPath: getContextPath,
5124         getRequestName: getRequestName,
5125         getParameterValues: getParameterValues
5126     };
5127 }();
5128
5129 thymol.objects.thHttpServletRequestObject = function() {
5130     var thExpressionObjectName = "#httpServletRequest";
5131     function getAttribute(name) {
5132         var result = thymol.requestContext[name][0];
5133         if (result instanceof thymol.ThParam) {
5134             result = thymol.ThUtils.unQuote(result.value);
5135         }
5136         return result;
5137     }
5138     function getParameter(name) {
5139         var result = thymol.requestContext[name];
5140         return result;
5141     }
5142     function getContextPath() {
5143         var result = "";
5144         return result;
5145     }
5146     function getRequestName() {
5147         var result = "";
5148         return result;
5149     }
5150     function getParameterValues(name) {
5151         var result = thymol.requestContext[name];
5152         return result;
5153     }
5154     function getSession(create) {
5155         return thymol.objects.thHttpSessionObject;
5156     }
5157     return {
5158         thExpressionObjectName: thExpressionObjectName,
5159         getAttribute: getAttribute,
5160         getParameter: getParameter,
5161         getContextPath: getContextPath,
5162         getRequestName: getRequestName,
5163         getParameterValues: getParameterValues,
5164         getSession: getSession
5165     };
5166 }();
5167
5168 thymol.objects.thAggregatesObject = function() {
5169     var thExpressionObjectName = "#aggregates";
5170     function sum(target) {
5171         return aggregate(target, false, "sum");
5172     }
5173     function avg(target) {
5174         return aggregate(target, true, "avg");
5175     }
5176     function aggregate(target, doAvg, label) {
5177         if (target !== null) {
5178             var result = 0;
5179             var count;
5180             var tt = typeof target;
5181             var ptc = Object.prototype.toString.call(target);
5182             if (tt === "Array" || ptc === "[object Array]") {
5183                 count = target.length;
5184                 for (var i = 0; i < count; i++) {
5185                     if (target[i] !== null) {
5186                         result += target[i];
5187                     } else {
5188                         throw new thymol.ThError("#aggregates." + label + " Cannot aggregate on object containing nulls");
5189                     }
5190                 }
5191             } else {
5192                 count = 0;
5193                 for (var k in target) {
5194                     var value = target[k];
5195                     var process = false;
5196                     if (value !== null) {
5197                         if (target instanceof thymol.ThSet) {
5198                             process = target.isContent(k);
5199                         } else {
5200                             process = target.hasOwnProperty(k) && typeof value !== "function";
5201                         }
5202                     } else {
5203                         throw new thymol.ThError("#aggregates." + label + " Cannot aggregate on object containing nulls");
5204                     }
5205                     if (process) {
5206                         result += value;
5207                         count++;
5208                     }
5209                 }
5210             }
5211             if (doAvg) {
5212                 if (count == 0) {
5213                     throw new thymol.ThError("#aggregates." + label + " Cannot get size of object");
5214                 }
5215                 result = result / count;
5216             }
5217             return result;
5218         }
5219         throw new thymol.ThError("#aggregates." + label + " Cannot aggregate on null");
5220     }
5221     return {
5222         thExpressionObjectName: thExpressionObjectName,
5223         sum: sum,
5224         avg: avg
5225     };
5226 }();
5227
5228 thymol.objects.thArraysObject = function() {
5229     var thExpressionObjectName = "#arrays";
5230     function toArray(target) {
5231         if (target !== null) {
5232             return toTypedArray(null, target);
5233         }
5234         throw new thymol.ThError("#arrays.toArray Cannot convert null to array");
5235     }
5236     function toStringArray(target) {
5237         if (target !== null) {
5238             return toTypedArray("string", target);
5239         }
5240         throw new thymol.ThError("#arrays.toStringArray Cannot convert null to array");
5241     }
5242     function toNumberArray(target) {
5243         if (target !== null) {
5244             return toTypedArray("number", target);
5245         }
5246         throw new thymol.ThError("#arrays.toNumberArray Cannot convert null to array");
5247     }
5248     function toBooleanArray(target) {
5249         if (target !== null) {
5250             return toTypedArray("boolean", target);
5251         }
5252         throw new thymol.ThError("#arrays.toBooleanArray Cannot convert null to array");
5253     }
5254     function toTypedArray(componentClass, target) {
5255         if (target instanceof Array) {
5256             if (componentClass === null || componentClass === "undefined") {
5257                 return target;
5258             }
5259             var result = new Array();
5260             try {
5261                 for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5262                     if (target[i] !== null) {
5263                         if (componentClass === "string") {
5264                             result.push(new String(target[i]).valueOf());
5265                         } else if (componentClass === "number") {
5266                             result.push(new Number(target[i]).valueOf());
5267                         } else if (componentClass === "boolean") {
5268                             result.push(new Boolean(target[i]).valueOf());
5269                         } else {
5270                             result.push(target[i]);
5271                         }
5272                     }
5273                 }
5274             } catch (err) {
5275                 throw new IllegalArgumentException('#arrays.toArray Cannot convert object of class "' + targetComponentClass.getName() + '[]" to an array' + " of " + componentClass.getClass().getSimpleName());
5276             }
5277             return result;
5278         } else if (target instanceof Object) {
5279             var result = new Array();
5280             try {
5281                 for (var k in target) {
5282                     var value = target[k];
5283                     var process = false;
5284                     if (value !== null) {
5285                         if (target instanceof thymol.ThSet) {
5286                             process = target.isContent(k);
5287                         } else {
5288                             process = target.hasOwnProperty(k) && typeof value !== "function";
5289                         }
5290                     }
5291                     if (process) {
5292                         if (componentClass === "string") {
5293                             result.push(new String(value).valueOf());
5294                         } else if (componentClass === "number") {
5295                             result.push(new Number(value).valueOf());
5296                         } else if (componentClass === "boolean") {
5297                             result.push(new Boolean(value).valueOf());
5298                         } else {
5299                             result.push(value);
5300                         }
5301                     }
5302                 }
5303             } catch (err) {
5304                 throw new IllegalArgumentException('#arrays.toArray Cannot convert object of class "' + targetComponentClass.getName() + '[]" to an array' + " of " + componentClass.getClass().getSimpleName());
5305             }
5306             return result;
5307         } else {
5308             throw new thymol.ThError('#arrays.toArray Cannot convert object of type "' + typeof target + '" to an array' + (componentClass == null ? "" : " of " + componentClass));
5309         }
5310     }
5311     function length(target) {
5312         if (target !== null) {
5313             return target.length;
5314         }
5315         throw new thymol.ThError("#arrays.length Cannot get array length of null");
5316     }
5317     function isEmpty(target) {
5318         return target === null || target.length <= 0;
5319     }
5320     function contains(target, element) {
5321         if (target !== null) {
5322             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5323                 if (target[i] === null) {
5324                     if (element === null) {
5325                         return true;
5326                     }
5327                 } else if (element !== null && target[i] === element) {
5328                     return true;
5329                 }
5330             }
5331             return false;
5332         }
5333         throw new thymol.ThError("#arrays.contains Cannot execute array contains: target is null");
5334     }
5335     function containsAll(target, elements) {
5336         if (target !== null) {
5337             if (elements !== null) {
5338                 var elementsArray;
5339                 if (elements instanceof Array) {
5340                     elementsArray = [].concat(elements);
5341                 } else {
5342                     if (elements instanceof thymol.ThSet) {
5343                         elementsArray = elements.toArray();
5344                     } else {
5345                         elementsArray = [];
5346                         for (var k in elements) {
5347                             if (elements.hasOwnProperty(k) && typeof elements[k] !== "function") {
5348                                 elementsArray.push(elements[k]);
5349                             }
5350                         }
5351                     }
5352                 }
5353                 for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5354                     for (var j = 0, jLimit = elementsArray.length; j < jLimit; j++) {
5355                         if (target[i] === elementsArray[j]) {
5356                             elementsArray.splice(j, 1);
5357                         }
5358                     }
5359                 }
5360                 return elementsArray.length === 0;
5361             }
5362             throw new thymol.ThError("#arrays.containsAll Cannot execute array containsAll: elements is null");
5363         }
5364         throw new thymol.ThError("#arrays.containsAll Cannot execute array containsAll: target is null");
5365     }
5366     return {
5367         thExpressionObjectName: thExpressionObjectName,
5368         toArray: toArray,
5369         toStringArray: toStringArray,
5370         toIntegerArray: toNumberArray,
5371         toLongArray: toNumberArray,
5372         toDoubleArray: toNumberArray,
5373         toFloatArray: toNumberArray,
5374         toBooleanArray: toBooleanArray,
5375         length: length,
5376         isEmpty: isEmpty,
5377         contains: contains,
5378         containsAll: containsAll
5379     };
5380 }();
5381
5382 thymol.objects.thBoolsObject = function() {
5383     var thExpressionObjectName = "#bools";
5384     function isTrue(target) {
5385         var result = true;
5386         var tc;
5387         if (target == null || (tc = typeof target) === "undefined") {
5388             result = false;
5389         } else {
5390             if (tc === "boolean") {
5391                 result = target;
5392             } else if (tc === "number") {
5393                 result = target != 0;
5394             } else if (tc === "string") {
5395                 if (target.length === 1) {
5396                     result = target.charCodeAt(0) != 0;
5397                 } else if (thymol.ThUtils.testLiteralFalse(target)) {
5398                     result = false;
5399                 }
5400             }
5401         }
5402         return result;
5403     }
5404     function arrayIsTrue(target) {
5405         if (target !== null) {
5406             var result = [];
5407             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5408                 result.push(isTrue(target[i]));
5409             }
5410             return result;
5411         }
5412         throw new thymol.ThError("#bools.arrayIsTrue Target cannot be null");
5413     }
5414     function setIsTrue(target) {
5415         if (target !== null) {
5416             var result = new thymol.ThSet();
5417             for (var k in target) {
5418                 if (target.isContent(k)) {
5419                     result.add(isTrue(target[k]));
5420                 }
5421             }
5422             return result;
5423         }
5424         throw new thymol.ThError("#bools.setIsTrue Target cannot be null");
5425     }
5426     function isFalse(target) {
5427         return !isTrue(target);
5428     }
5429     function arrayIsFalse(target) {
5430         if (target !== null) {
5431             var result = [];
5432             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5433                 result.push(!isTrue(target[i]));
5434             }
5435             return result;
5436         }
5437         throw new thymol.ThError("#bools.arrayIsFalse Target cannot be null");
5438     }
5439     function setIsFalse(target) {
5440         if (target !== null) {
5441             var result = new thymol.ThSet();
5442             for (var k in target) {
5443                 if (target.isContent(k)) {
5444                     result.add(!isTrue(target[k]));
5445                 }
5446             }
5447             return result;
5448         }
5449         throw new thymol.ThError("#bools.setIsFalse Target cannot be null");
5450     }
5451     function arrayAnd(target) {
5452         if (target !== null) {
5453             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5454                 if (!isTrue(target[i])) {
5455                     return false;
5456                 }
5457             }
5458             return true;
5459         }
5460         throw new thymol.ThError("#bools.arrayAnd Target cannot be null");
5461     }
5462     function setAnd(target) {
5463         if (target !== null) {
5464             for (var k in target) {
5465                 if (target.isContent(k)) {
5466                     if (!isTrue(target[k])) {
5467                         return false;
5468                     }
5469                 }
5470             }
5471             return true;
5472         }
5473         throw new thymol.ThError("#bools.setAnd Target cannot be null");
5474     }
5475     function arrayOr(target) {
5476         if (target !== null) {
5477             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5478                 if (isTrue(target[i])) {
5479                     return true;
5480                 }
5481             }
5482             return false;
5483         }
5484         throw new thymol.ThError("#bools.arrayOr Target cannot be null");
5485     }
5486     function setOr(target) {
5487         if (target !== null) {
5488             for (var k in target) {
5489                 if (target.isContent(k)) {
5490                     if (isTrue(target[k])) {
5491                         return true;
5492                     }
5493                 }
5494             }
5495             return false;
5496         }
5497         throw new thymol.ThError("#bools.setOr Target cannot be null");
5498     }
5499     return {
5500         thExpressionObjectName: thExpressionObjectName,
5501         isTrue: isTrue,
5502         arrayIsTrue: arrayIsTrue,
5503         listIsTrue: arrayIsTrue,
5504         setIsTrue: setIsTrue,
5505         isFalse: isFalse,
5506         arrayIsFalse: arrayIsFalse,
5507         listIsFalse: arrayIsFalse,
5508         setIsFalse: setIsFalse,
5509         arrayAnd: arrayAnd,
5510         listAnd: arrayAnd,
5511         setAnd: setAnd,
5512         arrayOr: arrayOr,
5513         listOr: arrayOr,
5514         setOr: setOr
5515     };
5516 }();
5517
5518 thymol.objects.thDatesObject = function() {
5519     var thExpressionObjectName = "#dates";
5520     function createProxy() {
5521         if (arguments !== null) {
5522             if (arguments.length > 6) {
5523                 return create(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
5524             } else if (arguments.length > 5) {
5525                 return create(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], 0);
5526             } else if (arguments.length > 4) {
5527                 return create(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], 0, 0);
5528             }
5529             return create(arguments[0], arguments[1], arguments[2], 0, 0, 0, 0);
5530         }
5531     }
5532     function create(year, month, day, hour, minute, second, millisecond) {
5533         var result = new Date();
5534         result.setMilliseconds(millisecond);
5535         result.setSeconds(second);
5536         result.setMinutes(minute);
5537         result.setHours(hour);
5538         result.setDate(day);
5539         result.setMonth(month - 1);
5540         result.setFullYear(year);
5541         return result;
5542     }
5543     function getDay(dateValue) {
5544         var month = dateValue.getMonth() + 1;
5545         var year = dateValue.getFullYear();
5546         var day = dateValue.getDate();
5547         var a = Math.floor((14 - month) / 12);
5548         var y = year + 4800 - a;
5549         var m = month + 12 * a - 3;
5550         var jdn = day + Math.floor((153 * m + 2) / 5) + 365 * y + Math.floor(y / 4);
5551         if (jdn < 2331254) {
5552             jdn = jdn - 32083;
5553         } else {
5554             jdn = jdn - Math.floor(y / 100) + Math.floor(y / 400) - 32045;
5555         }
5556         var mjdn = (jdn + 1) % 7;
5557         return mjdn;
5558     }
5559     function createNow() {
5560         return new Date();
5561     }
5562     function createToday() {
5563         var today = new Date();
5564         today.setHours(0, 0, 0, 0);
5565         return today;
5566     }
5567     function format(dateParam, patternParam, locale) {
5568         var pattern = "";
5569         var date;
5570         if (arguments === null) {
5571             date = new Date();
5572         } else {
5573             if (arguments.length > 1) {
5574                 pattern = patternParam;
5575             }
5576             date = dateParam;
5577         }
5578         return formatDate(date, pattern, locale);
5579     }
5580     function formatDate(target, patternParam, locale) {
5581         var pattern = "";
5582         if (arguments.length > 1) {
5583             pattern = patternParam;
5584         }
5585         var result = dateFormat(target, pattern, false);
5586         return result;
5587     }
5588     function arrayFormat(target, patternParam) {
5589         var pattern = "";
5590         if (arguments.length > 1) {
5591             pattern = patternParam;
5592         }
5593         var result = [];
5594         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5595             result.push(dateFormat(target[i], pattern, false));
5596         }
5597         return result;
5598     }
5599     function setFormat(target, patternParam) {
5600         var pattern = "";
5601         if (arguments.length > 1) {
5602             pattern = patternParam;
5603         }
5604         var result = new thymol.ThSet();
5605         for (var k in target) {
5606             if (target.isContent(k)) {
5607                 result.add(dateFormat(target[k], pattern, false));
5608             }
5609         }
5610         return result;
5611     }
5612     function day(target) {
5613         return target.getDate();
5614     }
5615     function arrayDay(target) {
5616         var result = [];
5617         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5618             result.push(target[i].getDate());
5619         }
5620         return result;
5621     }
5622     function setDay(target) {
5623         var result = new thymol.ThSet();
5624         for (var k in target) {
5625             if (target.isContent(k)) {
5626                 result.add(target[k].getDate());
5627             }
5628         }
5629         return result;
5630     }
5631     function month(target) {
5632         return target.getMonth() + 1;
5633     }
5634     function arrayMonth(target) {
5635         var result = [];
5636         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5637             result.push(target[i].getMonth() + 1);
5638         }
5639         return result;
5640     }
5641     function setMonth(target) {
5642         var result = new thymol.ThSet();
5643         for (var k in target) {
5644             if (target.isContent(k)) {
5645                 result.add(target[k].getMonth() + 1);
5646             }
5647         }
5648         return result;
5649     }
5650     function monthName(target) {
5651         return dateFormat.i18n.monthNames[target.getMonth() + 12];
5652     }
5653     function arrayMonthName(target) {
5654         var result = [];
5655         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5656             result.push(dateFormat.i18n.monthNames[target[i].getMonth() + 12]);
5657         }
5658         return result;
5659     }
5660     function setMonthName(target) {
5661         var result = new thymol.ThSet();
5662         for (var k in target) {
5663             if (target.isContent(k)) {
5664                 result.add(dateFormat.i18n.monthNames[target[k].getMonth() + 12]);
5665             }
5666         }
5667         return result;
5668     }
5669     function monthNameShort(target) {
5670         return dateFormat.i18n.monthNames[target.getMonth()];
5671     }
5672     function arrayMonthNameShort(target) {
5673         var result = [];
5674         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5675             result.push(dateFormat.i18n.monthNames[target[i].getMonth()]);
5676         }
5677         return result;
5678     }
5679     function setMonthNameShort(target) {
5680         var result = new thymol.ThSet();
5681         for (var k in target) {
5682             if (target.isContent(k)) {
5683                 result.add(dateFormat.i18n.monthNames[target[k].getMonth()]);
5684             }
5685         }
5686         return result;
5687     }
5688     function year(target) {
5689         return target.getFullYear();
5690     }
5691     function arrayYear(target) {
5692         var result = [];
5693         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5694             result.push(target[i].getFullYear());
5695         }
5696         return result;
5697     }
5698     function setYear(target) {
5699         var result = new thymol.ThSet();
5700         for (var k in target) {
5701             if (target.isContent(k)) {
5702                 result.add(target[k].getFullYear());
5703             }
5704         }
5705         return result;
5706     }
5707     function dayOfWeek(target) {
5708         return getDay(target) + 1;
5709     }
5710     function arrayDayOfWeek(target) {
5711         var result = [];
5712         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5713             result.push(getDay(target[i]) + 1);
5714         }
5715         return result;
5716     }
5717     function setDayOfWeek(target) {
5718         var result = new thymol.ThSet();
5719         for (var k in target) {
5720             if (target.isContent(k)) {
5721                 result.add(getDay(target[k]) + 1);
5722             }
5723         }
5724         return result;
5725     }
5726     function dayOfWeekName(target) {
5727         return dateFormat.i18n.dayNames[getDay(target) + 7];
5728     }
5729     function arrayDayOfWeekName(target) {
5730         var result = [];
5731         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5732             result.push(dateFormat.i18n.dayNames[getDay(target[i]) + 7]);
5733         }
5734         return result;
5735     }
5736     function setDayOfWeekName(target) {
5737         var result = new thymol.ThSet();
5738         for (var k in target) {
5739             if (target.isContent(k)) {
5740                 result.add(dateFormat.i18n.dayNames[getDay(target[k]) + 7]);
5741             }
5742         }
5743         return result;
5744     }
5745     function dayOfWeekNameShort(target) {
5746         return dateFormat.i18n.dayNames[getDay(target)];
5747     }
5748     function arrayDayOfWeekNameShort(target) {
5749         var result = [];
5750         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5751             result.push(dateFormat.i18n.dayNames[getDay(target[i])]);
5752         }
5753         return result;
5754     }
5755     function setDayOfWeekNameShort(target) {
5756         var result = new thymol.ThSet();
5757         for (var k in target) {
5758             if (target.isContent(k)) {
5759                 result.add(dateFormat.i18n.dayNames[getDay(target[k])]);
5760             }
5761         }
5762         return result;
5763     }
5764     function hour(target) {
5765         return target.getHours();
5766     }
5767     function arrayHour(target) {
5768         var result = [];
5769         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5770             result.push(target[i].getHours());
5771         }
5772         return result;
5773     }
5774     function setHour(target) {
5775         var result = new thymol.ThSet();
5776         for (var k in target) {
5777             if (target.isContent(k)) {
5778                 result.add(target[k].getHours());
5779             }
5780         }
5781         return result;
5782     }
5783     function minute(target) {
5784         return target.getMinutes();
5785     }
5786     function arrayMinute(target) {
5787         var result = [];
5788         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5789             result.push(target[i].getMinutes());
5790         }
5791         return result;
5792     }
5793     function setMinute(target) {
5794         var result = new thymol.ThSet();
5795         for (var k in target) {
5796             if (target.isContent(k)) {
5797                 result.add(target[k].getMinutes());
5798             }
5799         }
5800         return result;
5801     }
5802     function second(target) {
5803         return target.getSeconds();
5804     }
5805     function arraySecond(target) {
5806         var result = [];
5807         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5808             result.push(target[i].getSeconds());
5809         }
5810         return result;
5811     }
5812     function setSecond(target) {
5813         var result = new thymol.ThSet();
5814         for (var k in target) {
5815             if (target.isContent(k)) {
5816                 result.add(target[k].getSeconds());
5817             }
5818         }
5819         return result;
5820     }
5821     function millisecond(target) {
5822         return target.getMilliseconds();
5823     }
5824     function arrayMillisecond(target) {
5825         var result = [];
5826         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
5827             result.push(target[i].getMilliseconds());
5828         }
5829         return result;
5830     }
5831     function setMillisecond(target) {
5832         var result = new thymol.ThSet();
5833         for (var k in target) {
5834             if (target.isContent(k)) {
5835                 result.add(target[k].getMilliseconds());
5836             }
5837         }
5838         return result;
5839     }
5840     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;
5841     function processTZ(target) {
5842         var toStr = String(target);
5843         var result = toStr;
5844         result = (result.match(timezone) || [ "" ]).pop();
5845         if ("" !== result) {
5846             result = result.replace(timezoneClip, "");
5847             var tail = toStr.match(/[\(]((?:[GL]M|BS)T[^\)]*?)[\)]/);
5848             if (tail) {
5849                 if (target.getFullYear() > 1916 || target.getFullYear() === 1916 && target.getMonth() > 4 || target.getFullYear() === 1916 && target.getMonth() === 4 && target.getDate() > 20) {
5850                     result = result.replace(/GMT\+\d{1,4}/, "BST");
5851                 } else {
5852                     result = result.replace(/GMT\+\d{1,4}/, "GMT");
5853                 }
5854             }
5855         }
5856         return result;
5857     }
5858     var dateFormat = function() {
5859         var token = /d{1,4}|M{1,4}|yy(?:yy)?|([HhmsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, pad = function(valp, lenp) {
5860             var val = String(valp), len = lenp || 2;
5861             while (val.length < len) val = "0" + val;
5862             return val;
5863         };
5864         return function(datep, maskp, utcp) {
5865             var dF = dateFormat, mask = maskp, date = datep, utc = utcp;
5866             if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
5867                 mask = date;
5868                 date = undefined;
5869             }
5870             date = date ? new Date(date) : new Date();
5871             if (isNaN(date)) throw SyntaxError("invalid date");
5872             mask = String(dF.masks[mask] || mask || dF.masks["default"]);
5873             if (mask.slice(0, 4) == "UTC:") {
5874                 mask = mask.slice(4);
5875                 utc = true;
5876             }
5877             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 = {
5878                 d: d,
5879                 dd: pad(d),
5880                 ddd: dF.i18n.dayNames[D],
5881                 dddd: dF.i18n.dayNames[D + 7],
5882                 M: M + 1,
5883                 MM: pad(M + 1),
5884                 MMM: dF.i18n.monthNames[M],
5885                 MMMM: dF.i18n.monthNames[M + 12],
5886                 yy: String(y).slice(2),
5887                 yyyy: y,
5888                 h: H % 12 || 12,
5889                 hh: pad(H % 12 || 12),
5890                 H: H,
5891                 HH: pad(H),
5892                 m: m,
5893                 mm: pad(m),
5894                 s: s,
5895                 ss: pad(s),
5896                 l: pad(L, 3),
5897                 L: pad(L > 99 ? Math.round(L / 10) : L),
5898                 t: H < 12 ? "a" : "p",
5899                 tt: H < 12 ? "am" : "pm",
5900                 T: H < 12 ? "A" : "P",
5901                 TT: H < 12 ? "AM" : "PM",
5902                 Z: utc ? "UTC" : processTZ(date),
5903                 o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
5904                 S: [ "th", "st", "nd", "rd" ][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
5905             };
5906             return mask.replace(token, function($0) {
5907                 return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
5908             });
5909         };
5910     }();
5911     dateFormat.masks = {
5912         "default": "dd MMMM yyyy HH:mm:ss Z",
5913         shortDate: "M/d/yy",
5914         mediumDate: "MMM d, yyyy",
5915         longDate: "d MMMM yyyy",
5916         fullDate: "dddd, MMMM d, yyyy",
5917         shortTime: "h:mm TT",
5918         mediumTime: "h:mm:ss TT",
5919         longTime: "h:mm:ss TT Z",
5920         isoDate: "yyyy-MM-dd",
5921         isoTime: "HH:mm:ss",
5922         isoDateTime: "yyyy-MM-dd'T'HH:mm:ss",
5923         isoUtcDateTime: "UTC:yyyy-MM-dd'T'HH:mm:ss'Z'"
5924     };
5925     dateFormat.i18n = {
5926         dayNames: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
5927         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" ]
5928     };
5929     Date.prototype.format = function(mask, utc) {
5930         return dateFormat(this, mask, utc);
5931     };
5932     return {
5933         thExpressionObjectName: thExpressionObjectName,
5934         create: createProxy,
5935         createNow: createNow,
5936         createNowForTimeZone: createNow,
5937         createToday: createToday,
5938         createTodayForTimeZone: createToday,
5939         format: format,
5940         dateFormat: dateFormat,
5941         arrayFormat: arrayFormat,
5942         listFormat: arrayFormat,
5943         setFormat: setFormat,
5944         day: day,
5945         arrayDay: arrayDay,
5946         listDay: arrayDay,
5947         setDay: setDay,
5948         month: month,
5949         arrayMonth: arrayMonth,
5950         listMonth: arrayMonth,
5951         setMonth: setMonth,
5952         monthName: monthName,
5953         arrayMonthName: arrayMonthName,
5954         listMonthName: arrayMonthName,
5955         setMonthName: setMonthName,
5956         monthNameShort: monthNameShort,
5957         arrayMonthNameShort: arrayMonthNameShort,
5958         listMonthNameShort: arrayMonthNameShort,
5959         setMonthNameShort: setMonthNameShort,
5960         year: year,
5961         arrayYear: arrayYear,
5962         listYear: arrayYear,
5963         setYear: setYear,
5964         dayOfWeek: dayOfWeek,
5965         arrayDayOfWeek: arrayDayOfWeek,
5966         listDayOfWeek: arrayDayOfWeek,
5967         setDayOfWeek: setDayOfWeek,
5968         dayOfWeekName: dayOfWeekName,
5969         arrayDayOfWeekName: arrayDayOfWeekName,
5970         listDayOfWeekName: arrayDayOfWeekName,
5971         setDayOfWeekName: setDayOfWeekName,
5972         dayOfWeekNameShort: dayOfWeekNameShort,
5973         arrayDayOfWeekNameShort: arrayDayOfWeekNameShort,
5974         listDayOfWeekNameShort: arrayDayOfWeekNameShort,
5975         setDayOfWeekNameShort: setDayOfWeekNameShort,
5976         hour: hour,
5977         arrayHour: arrayHour,
5978         listHour: arrayHour,
5979         setHour: setHour,
5980         minute: minute,
5981         arrayMinute: arrayMinute,
5982         listMinute: arrayMinute,
5983         setMinute: setMinute,
5984         second: second,
5985         arraySecond: arraySecond,
5986         listSecond: arraySecond,
5987         setSecond: setSecond,
5988         millisecond: millisecond,
5989         arrayMillisecond: arrayMillisecond,
5990         listMillisecond: arrayMillisecond,
5991         setMillisecond: setMillisecond
5992     };
5993 }();
5994
5995 thymol.objects.thCalendarsObject = function() {
5996     var thExpressionObjectName = "#calendars";
5997     return {
5998         thExpressionObjectName: thExpressionObjectName,
5999         create: thymol.objects.thDatesObject.create,
6000         createNow: thymol.objects.thDatesObject.createNow,
6001         createNowForTimeZone: thymol.objects.thDatesObject.createNow,
6002         createToday: thymol.objects.thDatesObject.createToday,
6003         createTodayForTimeZone: thymol.objects.thDatesObject.createToday,
6004         format: thymol.objects.thDatesObject.format,
6005         dateFormat: thymol.objects.thDatesObject.dateFormat,
6006         arrayFormat: thymol.objects.thDatesObject.arrayFormat,
6007         listFormat: thymol.objects.thDatesObject.arrayFormat,
6008         setFormat: thymol.objects.thDatesObject.setFormat,
6009         day: thymol.objects.thDatesObject.day,
6010         arrayDay: thymol.objects.thDatesObject.arrayDay,
6011         listDay: thymol.objects.thDatesObject.arrayDay,
6012         setDay: thymol.objects.thDatesObject.setDay,
6013         month: thymol.objects.thDatesObject.month,
6014         arrayMonth: thymol.objects.thDatesObject.arrayMonth,
6015         listMonth: thymol.objects.thDatesObject.arrayMonth,
6016         setMonth: thymol.objects.thDatesObject.setMonth,
6017         monthName: thymol.objects.thDatesObject.monthName,
6018         arrayMonthName: thymol.objects.thDatesObject.arrayMonthName,
6019         listMonthName: thymol.objects.thDatesObject.arrayMonthName,
6020         setMonthName: thymol.objects.thDatesObject.setMonthName,
6021         monthNameShort: thymol.objects.thDatesObject.monthNameShort,
6022         arrayMonthNameShort: thymol.objects.thDatesObject.arrayMonthNameShort,
6023         listMonthNameShort: thymol.objects.thDatesObject.arrayMonthNameShort,
6024         setMonthNameShort: thymol.objects.thDatesObject.setMonthNameShort,
6025         year: thymol.objects.thDatesObject.year,
6026         arrayYear: thymol.objects.thDatesObject.arrayYear,
6027         listYear: thymol.objects.thDatesObject.arrayYear,
6028         setYear: thymol.objects.thDatesObject.setYear,
6029         dayOfWeek: thymol.objects.thDatesObject.dayOfWeek,
6030         arrayDayOfWeek: thymol.objects.thDatesObject.arrayDayOfWeek,
6031         listDayOfWeek: thymol.objects.thDatesObject.arrayDayOfWeek,
6032         setDayOfWeek: thymol.objects.thDatesObject.setDayOfWeek,
6033         dayOfWeekName: thymol.objects.thDatesObject.dayOfWeekName,
6034         arrayDayOfWeekName: thymol.objects.thDatesObject.arrayDayOfWeekName,
6035         listDayOfWeekName: thymol.objects.thDatesObject.arrayDayOfWeekName,
6036         setDayOfWeekName: thymol.objects.thDatesObject.setDayOfWeekName,
6037         dayOfWeekNameShort: thymol.objects.thDatesObject.dayOfWeekNameShort,
6038         arrayDayOfWeekNameShort: thymol.objects.thDatesObject.arrayDayOfWeekNameShort,
6039         listDayOfWeekNameShort: thymol.objects.thDatesObject.arrayDayOfWeekNameShort,
6040         setDayOfWeekNameShort: thymol.objects.thDatesObject.setDayOfWeekNameShort,
6041         hour: thymol.objects.thDatesObject.hour,
6042         arrayHour: thymol.objects.thDatesObject.arrayHour,
6043         listHour: thymol.objects.thDatesObject.arrayHour,
6044         setHour: thymol.objects.thDatesObject.setHour,
6045         minute: thymol.objects.thDatesObject.minute,
6046         arrayMinute: thymol.objects.thDatesObject.arrayMinute,
6047         listMinute: thymol.objects.thDatesObject.arrayMinute,
6048         setMinute: thymol.objects.thDatesObject.setMinute,
6049         second: thymol.objects.thDatesObject.second,
6050         arraySecond: thymol.objects.thDatesObject.arraySecond,
6051         listSecond: thymol.objects.thDatesObject.arraySecond,
6052         setSecond: thymol.objects.thDatesObject.setSecond,
6053         millisecond: thymol.objects.thDatesObject.millisecond,
6054         arrayMillisecond: thymol.objects.thDatesObject.arrayMillisecond,
6055         listMillisecond: thymol.objects.thDatesObject.arrayMillisecond,
6056         setMillisecond: thymol.objects.thDatesObject.setMillisecond
6057     };
6058 }();
6059
6060 thymol.objects.thIdsObject = function() {
6061     var thExpressionObjectName = "#ids";
6062     function seq(id) {
6063         if (id !== null) {
6064             var str = id.toString();
6065             var idCount = getLocal(str);
6066             var result = str + idCount;
6067             idCount++;
6068             setLocal(str, idCount);
6069             return result;
6070         }
6071         throw new thymol.ThError("#ids.seq ID Cannot be null");
6072     }
6073     function next(id) {
6074         if (id !== null) {
6075             var str = id.toString();
6076             var idCount = getLocal(str);
6077             return str + idCount;
6078         }
6079         throw new thymol.ThError("#ids.next ID Cannot be null");
6080     }
6081     function prev(id) {
6082         if (id !== null) {
6083             var str = id.toString();
6084             var idCount = getLocal(str);
6085             return str + (idCount - 1);
6086         }
6087         throw new thymol.ThError("#ids.prev ID Cannot be null");
6088     }
6089     function setLocal(str, idCount) {
6090         if (!thymol.objects.thIdsObject.thLocalVars) {
6091             thymol.objects.thIdsObject.thLocalVars = [];
6092         }
6093         if (!thymol.objects.thIdsObject.thLocalVars["thIdCounts"]) {
6094             thymol.objects.thIdsObject.thLocalVars["thIdCounts"] = [];
6095         }
6096         thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str] = idCount;
6097     }
6098     function getLocal(str) {
6099         if (!thymol.objects.thIdsObject.thLocalVars) {
6100             thymol.objects.thIdsObject.thLocalVars = [];
6101         }
6102         if (!thymol.objects.thIdsObject.thLocalVars["thIdCounts"]) {
6103             thymol.objects.thIdsObject.thLocalVars["thIdCounts"] = [];
6104         }
6105         if (!thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str]) {
6106             thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str] = 1;
6107         }
6108         return thymol.objects.thIdsObject.thLocalVars["thIdCounts"][str];
6109     }
6110     return {
6111         thExpressionObjectName: thExpressionObjectName,
6112         seq: seq,
6113         next: next,
6114         prev: prev
6115     };
6116 }();
6117
6118 thymol.objects.thListsObject = function() {
6119     var thExpressionObjectName = "#lists";
6120     function sort(list, comparator) {
6121         if (list !== null) {
6122             if (arguments.length > 1) {
6123                 if (comparator !== null) {
6124                     if (typeof comparator === "function") {
6125                         return list.sort(comparator);
6126                     }
6127                     throw new thymol.ThError("#lists.sort Cannot execute list sort: comparator is not a function");
6128                 }
6129                 throw new thymol.ThError("#lists.sort Cannot execute list sort: comparator is null");
6130             }
6131             return list.sort();
6132         }
6133         throw new thymol.ThError("#lists.sort Cannot execute list sort: list is null");
6134     }
6135     return {
6136         thExpressionObjectName: thExpressionObjectName,
6137         toList: thymol.objects.thArraysObject.toArray,
6138         size: thymol.objects.thArraysObject.length,
6139         isEmpty: thymol.objects.thArraysObject.isEmpty,
6140         contains: thymol.objects.thArraysObject.contains,
6141         containsAll: thymol.objects.thArraysObject.containsAll,
6142         sort: sort
6143     };
6144 }();
6145
6146 thymol.objects.thMapsObject = function() {
6147     var thExpressionObjectName = "#maps";
6148     function size(target) {
6149         if (target !== null) {
6150             if (target instanceof thymol.ThMap) {
6151                 return target.size();
6152             }
6153             throw new thymol.ThError('#maps.size Cannot get size of non-map type "' + typeof target + '"');
6154         }
6155         throw new thymol.ThError("#maps.size Cannot get size of null");
6156     }
6157     function isEmpty(target) {
6158         if (target !== null) {
6159             if (target instanceof thymol.ThMap) {
6160                 return target.isEmpty();
6161             }
6162             throw new thymol.ThError('#maps.size Cannot get isEmpty of non-map type "' + typeof target + '"');
6163         }
6164         throw new thymol.ThError("#maps.size Cannot get isEmpty of null");
6165     }
6166     function containsKey(target, key) {
6167         if (target !== null) {
6168             if (target instanceof thymol.ThMap) {
6169                 return target.containsKey(key);
6170             }
6171             throw new thymol.ThError('#maps.size Cannot get containsKey of non-map type "' + typeof target + '"');
6172         }
6173         throw new thymol.ThError("#maps.containsKey Cannot execute map containsKey: target is null");
6174     }
6175     function containsValue(target, value) {
6176         if (target !== null) {
6177             if (target instanceof thymol.ThMap) {
6178                 return target.containsValue(value);
6179             }
6180             throw new thymol.ThError('#maps.size Cannot get containsValue of non-map type "' + typeof target + '"');
6181         }
6182         throw new thymol.ThError("#maps.containsKey Cannot execute map containsValue: target is null");
6183     }
6184     function containsAllKeys(target, keys) {
6185         if (target !== null) {
6186             if (target instanceof thymol.ThMap) {
6187                 var ptc = Object.prototype.toString.call(keys);
6188                 if (keys instanceof thymol.ThSet || keys instanceof Array || ptc === "[object Array]") {
6189                     return target.containsAll(keys);
6190                 }
6191                 throw new thymol.ThError('#maps.size Cannot get containsAllKeys with non-collection type "' + ptc + '"');
6192             }
6193             throw new thymol.ThError('#maps.size Cannot get containsAllKeys of non-map type "' + typeof target + '"');
6194         }
6195         throw new thymol.ThError("#maps.containsKey Cannot execute map containsAllKeys: target is null");
6196     }
6197     function containsAllValues(target, values) {
6198         if (target !== null) {
6199             if (target instanceof thymol.ThMap) {
6200                 var ptc = Object.prototype.toString.call(values);
6201                 if (values instanceof thymol.ThSet || values instanceof Array || ptc === "[object Array]") {
6202                     var vArray = values;
6203                     if (values instanceof thymol.ThSet) {
6204                         vArray = values.toArray();
6205                     }
6206                     for (var i = 0, iLimit = vArray.length; i < iLimit; i++) {
6207                         var found = false;
6208                         for (var k in target) {
6209                             if (target.hasOwnProperty(k)) {
6210                                 var value = target[k];
6211                                 if (value === vArray[i]) {
6212                                     found = true;
6213                                     break;
6214                                 }
6215                             }
6216                         }
6217                         if (!found) {
6218                             return false;
6219                         }
6220                     }
6221                     return true;
6222                 }
6223                 throw new thymol.ThError('#maps.size Cannot get containsAllValues with non-collection type "' + ptc + '"');
6224             }
6225             throw new thymol.ThError('#maps.size Cannot get containsAllValues of non-map type "' + typeof target + '"');
6226         }
6227         throw new thymol.ThError("#maps.containsKey Cannot execute map containsAllValues: target is null");
6228     }
6229     return {
6230         thExpressionObjectName: thExpressionObjectName,
6231         size: size,
6232         isEmpty: isEmpty,
6233         containsKey: containsKey,
6234         containsValue: containsValue,
6235         containsAllKeys: containsAllKeys,
6236         containsAllValues: containsAllValues
6237     };
6238 }();
6239
6240 thymol.objects.thMessagesObject = function() {
6241     var thExpressionObjectName = "#messages";
6242     function msg() {
6243         if (arguments !== null) {
6244             if (arguments.length > 0) {
6245                 return msgWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
6246             }
6247             throw new thymol.ThError("#messages.msg Invoked with no arguments!");
6248         }
6249         throw new thymol.ThError("#messages.msg Target cannot be null");
6250     }
6251     function msgWithParams(target, params) {
6252         if (target !== null) {
6253             return thymol.getMessage(target, params, true);
6254         }
6255         throw new thymol.ThError("#messages.msgWithParams Target cannot be null");
6256     }
6257     function msgOrNull() {
6258         if (arguments !== null) {
6259             if (arguments.length > 0) {
6260                 return msgOrNullWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
6261             }
6262             throw new thymol.ThError("#messages.msgOrNull Invoked with no arguments!");
6263         }
6264         throw new thymol.ThError("#messages.msgOrNull Target cannot be null");
6265     }
6266     function msgOrNullWithParams(target, params) {
6267         if (target !== null) {
6268             return thymol.getMessage(target, params, false);
6269         }
6270         throw new thymol.ThError("#messages.msgOrNullWithParams Target cannot be null");
6271     }
6272     function arrayMsg() {
6273         if (arguments !== null) {
6274             if (arguments.length > 0) {
6275                 return arrayMsgWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
6276             }
6277             throw new thymol.ThError("#messages.arrayMsg Invoked with no arguments!");
6278         }
6279         throw new thymol.ThError("#messages.arrayMsg Target cannot be null");
6280     }
6281     function arrayMsgWithParams(target, params) {
6282         if (target !== null) {
6283             var result = [];
6284             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6285                 result.push(msgWithParams(target[i], params));
6286             }
6287             return result;
6288         }
6289         throw new thymol.ThError("#messages.arrayMsgWithParams Target cannot be null");
6290     }
6291     function setMsg() {
6292         if (arguments !== null) {
6293             if (arguments.length > 0) {
6294                 return setMsgWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
6295             }
6296             throw new thymol.ThError("#messages.setMsg Invoked with no arguments!");
6297         }
6298         throw new thymol.ThError("#messages.setMsg Target cannot be null");
6299     }
6300     function setMsgWithParams(target, params) {
6301         if (target !== null) {
6302             var result = new thymol.ThSet();
6303             for (var k in target) {
6304                 if (target.isContent(k)) {
6305                     result.add(msgWithParams(target[k], params));
6306                 }
6307             }
6308             return result;
6309         }
6310         throw new thymol.ThError("#messages.setMsgWithParams Target cannot be null");
6311     }
6312     function arrayMsgOrNull() {
6313         if (arguments !== null) {
6314             if (arguments.length > 0) {
6315                 return arrayMsgOrNullWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
6316             }
6317             throw new thymol.ThError("#messages.arrayMsgOrNull Invoked with no arguments!");
6318         }
6319         throw new thymol.ThError("#messages.arrayMsgOrNull Target cannot be null");
6320     }
6321     function arrayMsgOrNullWithParams(target, params) {
6322         if (target !== null) {
6323             var result = [];
6324             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6325                 result.push(msgOrNullWithParams(target[i], params));
6326             }
6327             return result;
6328         }
6329         throw new thymol.ThError("#messages.arrayMsgOrNullWithParams Target cannot be null");
6330     }
6331     function setMsgOrNull() {
6332         if (arguments !== null) {
6333             if (arguments.length > 0) {
6334                 return setMsgOrNullWithParams(arguments[0], Array.prototype.slice.call(arguments, 1));
6335             }
6336             throw new thymol.ThError("#messages.setMsgOrNull Invoked with no arguments!");
6337         }
6338         throw new thymol.ThError("#messages.setMsgOrNull Target cannot be null");
6339     }
6340     function setMsgOrNullWithParams(target, params) {
6341         if (target !== null) {
6342             var result = new thymol.ThSet();
6343             for (var k in target) {
6344                 if (target.isContent(k)) {
6345                     result.add(msgOrNullWithParams(target[k], params));
6346                 }
6347             }
6348             return result;
6349         }
6350         throw new thymol.ThError("#messages.setMsgOrNullWithParams Target cannot be null");
6351     }
6352     return {
6353         thExpressionObjectName: thExpressionObjectName,
6354         msg: msg,
6355         msgWithParams: msgWithParams,
6356         msgOrNull: msgOrNull,
6357         msgOrNullWithParams: msgOrNullWithParams,
6358         arrayMsg: arrayMsg,
6359         listMsg: arrayMsg,
6360         setMsg: setMsg,
6361         arrayMsgWithParams: arrayMsgWithParams,
6362         listMsgWithParams: arrayMsgWithParams,
6363         setMsgWithParams: setMsgWithParams,
6364         arrayMsgOrNull: arrayMsgOrNull,
6365         listMsgOrNull: arrayMsgOrNull,
6366         setMsgOrNull: setMsgOrNull,
6367         arrayMsgOrNullWithParams: arrayMsgOrNullWithParams,
6368         listMsgOrNullWithParams: arrayMsgOrNullWithParams,
6369         setMsgOrNullWithParams: setMsgOrNullWithParams
6370     };
6371 }();
6372
6373 thymol.objects.thNumbersObject = function() {
6374     var thExpressionObjectName = "#numbers";
6375     var DEFAULT_THOU_PT = ",";
6376     var DEFAULT_DECI_PT = ".";
6377     var DEFAULT_NONE_PT = "?";
6378     function formatDecimalProxy() {
6379         if (arguments !== null) {
6380             if (arguments.length > 4) {
6381                 return formatDecimal5(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
6382             } else if (arguments.length > 3) {
6383                 return formatDecimal4(arguments[0], arguments[1], arguments[2], arguments[3]);
6384             }
6385             return formatDecimal3(arguments[0], arguments[1], arguments[2]);
6386         }
6387     }
6388     function formatIntegerProxy() {
6389         if (arguments !== null) {
6390             if (arguments.length > 4) {
6391                 return formatDecimal5(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
6392             } else if (arguments.length > 3) {
6393                 return formatDecimal5(arguments[0], arguments[1], "NONE", arguments[2], arguments[3]);
6394             } else if (arguments.length > 2) {
6395                 if (typeof arguments[2] === "string") {
6396                     return formatDecimal5(arguments[0], arguments[1], arguments[2], 0, "POINT");
6397                 }
6398                 return formatDecimal5(arguments[0], arguments[1], "NONE", arguments[2], "POINT");
6399             } else {
6400                 return formatDecimal5(arguments[0], arguments[1], "NONE", 0, "POINT");
6401             }
6402         }
6403     }
6404     function arrayFormatIntegerProxy() {
6405         if (arguments !== null) {
6406             if (arguments.length > 2) {
6407                 return arrayFormatDecimal(arguments[0], arguments[1], arguments[2], 0, "POINT");
6408             }
6409             return arrayFormatDecimal(arguments[0], arguments[1], "NONE", 0, "POINT");
6410         }
6411     }
6412     function setFormatIntegerProxy() {
6413         if (arguments !== null) {
6414             if (arguments.length > 2) {
6415                 return setFormatDecimal(arguments[0], arguments[1], arguments[2], 0, "POINT");
6416             }
6417             return setFormatDecimal(arguments[0], arguments[1], "NONE", 0, "POINT");
6418         }
6419     }
6420     function arrayFormatDecimalProxy() {
6421         if (arguments !== null) {
6422             if (arguments.length > 4) {
6423                 return arrayFormatDecimal(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
6424             } else if (arguments.length > 3) {
6425                 return arrayFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], arguments[3]);
6426             }
6427             return arrayFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], "POINT");
6428         }
6429     }
6430     function setFormatDecimalProxy() {
6431         if (arguments !== null) {
6432             if (arguments.length > 4) {
6433                 return setFormatDecimal(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
6434             } else if (arguments.length > 3) {
6435                 return setFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], arguments[3]);
6436             }
6437             return setFormatDecimal(arguments[0], arguments[1], "NONE", arguments[2], "POINT");
6438         }
6439     }
6440     function sequenceProxy() {
6441         if (arguments !== null) {
6442             if (arguments.length > 2) {
6443                 return sequence(arguments[0], arguments[1], arguments[2]);
6444             }
6445             return sequence(arguments[0], arguments[1], 1);
6446         }
6447     }
6448     function getIntegerDigits(val) {
6449         var s = val.toString();
6450         var digits = s.length;
6451         var dp = s.indexOf(".");
6452         if (dp > 0) {
6453             digits = dp;
6454         }
6455         return digits;
6456     }
6457     function formatDecimal3(target, minIntegerDigits, decimalDigits) {
6458         var result = target.toString();
6459         var value = new Number(target);
6460         value = value.toFixed(decimalDigits);
6461         if (minIntegerDigits > 0) {
6462             result = value;
6463             value = new Number(value);
6464             var a = Math.abs(value);
6465             if (a < Math.pow(10, minIntegerDigits)) {
6466                 if (target < 0) {
6467                     result = result.substring(1);
6468                 }
6469                 var p = getIntegerDigits(a);
6470                 var x = minIntegerDigits - p;
6471                 if (x > 0) {
6472                     for (var i = 0; i < x; i++) {
6473                         result = "0" + result;
6474                     }
6475                 }
6476                 if (target < 0) {
6477                     result = "-" + result;
6478                 }
6479             }
6480         } else {
6481             result = value.toString();
6482         }
6483         result = new String(result);
6484         result.precision = decimalDigits;
6485         return result;
6486     }
6487     function formatDecimal4(target, minIntegerDigits, decimalDigits, decimalPointType) {
6488         var result = formatDecimal3(target, minIntegerDigits, decimalDigits);
6489         var decimalPoint;
6490         if ("DEFAULT" === decimalPointType) {
6491             decimalPoint = DEFAULT_DECI_PT;
6492         } else if ("NONE" === decimalPointType) {
6493             decimalPoint = DEFAULT_NONE_PT;
6494         } else {
6495             decimalPoint = getPointType(decimalPointType);
6496         }
6497         if ("." !== decimalPoint) {
6498             result = result.replace(".", decimalPoint, "g");
6499         }
6500         return result;
6501     }
6502     function formatDecimal5(target, minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType) {
6503         var result = target.toString();
6504         var decimalPoint;
6505         if ("DEFAULT" === decimalPointType) {
6506             decimalPoint = DEFAULT_DECI_PT;
6507         } else if ("NONE" === decimalPointType) {
6508             decimalPoint = DEFAULT_NONE_PT;
6509         } else {
6510             decimalPoint = getPointType(decimalPointType);
6511         }
6512         if ("" !== decimalPoint) {
6513             result = formatDecimal4(target, minIntegerDigits, decimalDigits, decimalPointType);
6514         } else {
6515             result = formatDecimal3(target, minIntegerDigits, decimalDigits);
6516         }
6517         var thousandsPoint;
6518         if ("DEFAULT" === thousandsPointType) {
6519             thousandsPoint = DEFAULT_THOU_PT;
6520         } else {
6521             thousandsPoint = getPointType(thousandsPointType);
6522         }
6523         if ("" !== thousandsPoint) {
6524             result = addThousandsPointType(result.toString(), decimalPoint, thousandsPoint);
6525         }
6526         return result;
6527     }
6528     function getPointType(type) {
6529         var result = ".";
6530         if ("COMMA" === type) {
6531             result = ",";
6532         } else if ("WHITESPACE" === type) {
6533             result = " ";
6534         } else if ("NONE" === type) {
6535             result = "";
6536         }
6537         return result;
6538     }
6539     function arrayFormatDecimal(target, minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType) {
6540         var result = [];
6541         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6542             result.push(formatDecimal5(target[i], minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType));
6543         }
6544         return result;
6545     }
6546     function setFormatDecimal(target, minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType) {
6547         var result = new thymol.ThSet();
6548         for (var k in target) {
6549             if (target.hasOwnProperty(k) && typeof target[k] !== "function") {
6550                 result.add(formatDecimal5(target[k], minIntegerDigits, thousandsPointType, decimalDigits, decimalPointType));
6551             }
6552         }
6553         return result;
6554     }
6555     function addThousandsPointType(nStr, dpt, tpt) {
6556         var x = nStr.split(dpt);
6557         var x1 = x[0];
6558         var x2 = x.length > 1 ? dpt + x[1] : "";
6559         var rgx = /(\d+)(\d{3})/;
6560         while (rgx.test(x1)) {
6561             x1 = x1.replace(rgx, "$1" + tpt + "$2");
6562         }
6563         return x1 + x2;
6564     }
6565     function sequence(start, stop, step) {
6566         var result = [];
6567         if (step > 0) {
6568             var value = start;
6569             if (start <= stop) {
6570                 do {
6571                     result.push(value);
6572                     value += step;
6573                 } while (value <= stop);
6574             } else {
6575                 do {
6576                     result.push(value);
6577                     value -= step;
6578                 } while (value >= stop);
6579             }
6580         }
6581         return result;
6582     }
6583     return {
6584         thExpressionObjectName: thExpressionObjectName,
6585         formatDecimal: formatDecimalProxy,
6586         formatInteger: formatIntegerProxy,
6587         arrayFormatInteger: arrayFormatIntegerProxy,
6588         arrayFormatDecimal: arrayFormatDecimalProxy,
6589         listFormatInteger: arrayFormatIntegerProxy,
6590         listFormatDecimal: arrayFormatDecimalProxy,
6591         setFormatInteger: setFormatIntegerProxy,
6592         setFormatDecimal: setFormatDecimalProxy,
6593         sequence: sequenceProxy
6594     };
6595 }();
6596
6597 thymol.objects.thObjectsObject = function() {
6598     var thExpressionObjectName = "#objects";
6599     function nullSafe(target, defaultValue) {
6600         return target != null ? target : defaultValue;
6601     }
6602     function arrayNullSafe(target, defaultValue) {
6603         if (target !== null) {
6604             var result = [];
6605             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6606                 result.push(nullSafe(target[i], defaultValue));
6607             }
6608             return result;
6609         }
6610         throw new thymol.ThError("#objects.arrayNullSafe Target cannot be null");
6611     }
6612     function setNullSafe(target, defaultValue) {
6613         if (target !== null) {
6614             var result = new thymol.ThSet();
6615             for (var k in target) {
6616                 if (target.isContent(k)) {
6617                     result.add(nullSafe(target[k], defaultValue));
6618                 }
6619             }
6620             return result;
6621         }
6622         throw new thymol.ThError("#objects.setNullSafe Target cannot be null");
6623     }
6624     return {
6625         thExpressionObjectName: thExpressionObjectName,
6626         nullSafe: nullSafe,
6627         arrayNullSafe: arrayNullSafe,
6628         listNullSafe: arrayNullSafe,
6629         setNullSafe: setNullSafe
6630     };
6631 }();
6632
6633 thymol.objects.thSetsObject = function() {
6634     var thExpressionObjectName = "#sets";
6635     function toSet(target) {
6636         if (target !== null) {
6637             var tt = typeof target;
6638             var ptc = Object.prototype.toString.call(target);
6639             var result;
6640             if (tt === "thymol.ThSet") {
6641                 result = target;
6642             }
6643             if (tt === "Array" || ptc === "[object Array]") {
6644                 result = thymol.ThSet.prototype.fromArray(target);
6645             } else if (tt === "object") {
6646                 result = new thymol.ThSet();
6647                 for (var k in target) {
6648                     var value = target[k];
6649                     var process = false;
6650                     if (value !== null) {
6651                         if (target instanceof thymol.ThSet) {
6652                             process = target.isContent(k);
6653                         } else {
6654                             process = target.hasOwnProperty(k) && typeof value !== "function";
6655                         }
6656                     }
6657                     if (process) {
6658                         result.add(value);
6659                     }
6660                 }
6661             } else {
6662                 throw new thymol.ThError('#sets.toSet Cannot convert object of type "' + tt + '" to a set');
6663             }
6664             return result;
6665         }
6666         throw new thymol.ThError("#sets.toSet Cannot convert null to set");
6667     }
6668     function size(target) {
6669         if (target !== null) {
6670             if (target instanceof thymol.ThSet) {
6671                 return target.size();
6672             }
6673             throw new thymol.ThError('#sets.size Cannot get size of non-set type "' + typeof target + '"');
6674         }
6675         throw new thymol.ThError("#sets.size Cannot get size of null");
6676     }
6677     function isEmpty(target) {
6678         if (target !== null) {
6679             if (target instanceof thymol.ThSet) {
6680                 return target.isEmpty();
6681             }
6682             throw new thymol.ThError('#sets.size Cannot get isEmpty of non-set type "' + typeof target + '"');
6683         }
6684         throw new thymol.ThError("#sets.size Cannot get isEmpty of null");
6685     }
6686     function contains(target, element) {
6687         if (target !== null) {
6688             for (var k in target) {
6689                 if (target.isContent(k)) {
6690                     if (target[k] === null) {
6691                         if (element === null) {
6692                             return true;
6693                         }
6694                     } else if (element !== null && target[k] === element) {
6695                         return true;
6696                     }
6697                 }
6698             }
6699             return false;
6700         }
6701         throw new thymol.ThError("#sets.contains Cannot execute sets contains: target is null");
6702     }
6703     function containsAll(target, elements) {
6704         if (target !== null) {
6705             if (elements !== null) {
6706                 var elementsArray;
6707                 if (elements instanceof Array) {
6708                     elementsArray = [].concat(elements);
6709                 } else {
6710                     if (elements instanceof thymol.ThSet) {
6711                         elementsArray = elements.toArray();
6712                     } else {
6713                         elementsArray = [];
6714                         for (var k in elements) {
6715                             if (elements.hasOwnProperty(k) && typeof elements[k] !== "function") {
6716                                 elementsArray.push(elements[k]);
6717                             }
6718                         }
6719                     }
6720                 }
6721                 for (var k in target) {
6722                     if (target.isContent(k)) {
6723                         for (var j = 0, jLimit = elementsArray.length; j < jLimit; j++) {
6724                             if (target[k] === elementsArray[j]) {
6725                                 elementsArray.splice(j, 1);
6726                             }
6727                         }
6728                     }
6729                 }
6730                 return elementsArray.length === 0;
6731             }
6732             throw new thymol.ThError("#sets.containsAll Cannot execute sets containsAll: elements is null");
6733         }
6734         throw new thymol.ThError("#sets.containsAll Cannot execute sets containsAll: target is null");
6735     }
6736     return {
6737         thExpressionObjectName: thExpressionObjectName,
6738         toSet: toSet,
6739         size: size,
6740         isEmpty: isEmpty,
6741         contains: contains,
6742         containsAll: containsAll
6743     };
6744 }();
6745
6746 thymol.objects.thStringsObject = function() {
6747     var thExpressionObjectName = "#strings";
6748     function toString(target) {
6749         var result = null;
6750         if (target !== null && typeof target !== "undefined") {
6751             result = target.toString();
6752         }
6753         return result;
6754     }
6755     function arrayToString(target) {
6756         var result = null;
6757         if (target !== null && typeof target !== "undefined") {
6758             result = [];
6759             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6760                 if (target[i] !== null) {
6761                     result.push(target[i].toString());
6762                 } else {
6763                     result.push(null);
6764                 }
6765             }
6766         }
6767         return result;
6768     }
6769     function setToString(target) {
6770         var result = null;
6771         if (target !== null && typeof target !== "undefined") {
6772             result = new thymol.ThSet();
6773             for (var k in target) {
6774                 if (target.isContent(k)) {
6775                     result.add(toString(target[k]));
6776                 }
6777             }
6778         }
6779         return result;
6780     }
6781     function abbreviate(target, maxSize, source) {
6782         if (maxSize >= 3) {
6783             var result = null;
6784             if (target !== null && typeof target !== "undefined") {
6785                 result = target.toString();
6786                 if (result.length > maxSize) {
6787                     result = result.substring(0, maxSize - 3) + "...";
6788                 }
6789             }
6790             return result;
6791         }
6792         throwAbbreviateException("abbreviate", maxSize);
6793     }
6794     function arrayAbbreviate(target, maxSize) {
6795         if (maxSize >= 3) {
6796             var result = null;
6797             if (target !== null && typeof target !== "undefined") {
6798                 result = [];
6799                 for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6800                     result.push(abbreviate(target[i], maxSize));
6801                 }
6802             }
6803             return result;
6804         }
6805         throwAbbreviateException("arrayAbbreviate", maxSize);
6806     }
6807     function setAbbreviate(target, maxSize) {
6808         if (maxSize >= 3) {
6809             var result = null;
6810             if (target !== null && typeof target !== "undefined") {
6811                 result = new thymol.ThSet();
6812                 for (var k in target) {
6813                     if (target.isContent(k)) {
6814                         result.add(abbreviate(target[k], maxSize));
6815                     }
6816                 }
6817             }
6818             return result;
6819         }
6820         throwAbbreviateException("setAbbreviate", maxSize);
6821     }
6822     function throwAbbreviateException(source, maxSize) {
6823         throw new thymol.ThError("#strings." + source + ' Maximum size must be greater than or equal to 3 but was: "' + maxSize + '"');
6824     }
6825     function equals(o1, o2) {
6826         if (o1 === null) {
6827             return o2 === null;
6828         } else if (o2 !== null) {
6829             return o1.toString() === o2.toString();
6830         }
6831         return false;
6832     }
6833     function equalsIgnoreCase(o1, o2) {
6834         if (o1 === null) {
6835             return o2 === null;
6836         } else if (o2 !== null) {
6837             return o1.toString().toLowerCase() === o2.toString().toLowerCase();
6838         }
6839         return false;
6840     }
6841     function contains(target, fragment) {
6842         if (target !== null) {
6843             if (fragment !== null) {
6844                 return target.toString().indexOf(fragment) >= 0;
6845             }
6846             throw new thymol.ThError("#strings.contains Fragment cannot be null");
6847         }
6848         throw new thymol.ThError("#strings.contains Cannot apply contains on null");
6849     }
6850     function arrayContains(target, fragment) {
6851         if (target !== null) {
6852             var result = [];
6853             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6854                 result.push(contains(target[i], fragment));
6855             }
6856             return result;
6857         }
6858         throw new thymol.ThError("#strings.arrayContains Cannot apply arrayContains on null");
6859     }
6860     function setContains(target, fragment) {
6861         if (target !== null) {
6862             var result = new thymol.ThSet();
6863             for (var k in target) {
6864                 if (target.isContent(k)) {
6865                     result.add(contains(target[k], fragment));
6866                 }
6867             }
6868             return result;
6869         }
6870         throw new thymol.ThError("#strings.setContains Cannot apply setContains on null");
6871     }
6872     function containsIgnoreCase(target, fragment) {
6873         if (target !== null) {
6874             if (fragment !== null) {
6875                 return target.toString().toLowerCase().indexOf(fragment.toLowerCase()) >= 0;
6876             }
6877             throw new thymol.ThError("#strings.containsIgnoreCase Fragment cannot be null");
6878         }
6879         throw new thymol.ThError("#strings.containsIgnoreCase Cannot apply containsIgnoreCase on null");
6880     }
6881     function arrayContainsIgnoreCase(target, fragment) {
6882         if (target !== null) {
6883             var result = [];
6884             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6885                 result.push(containsIgnoreCase(target[i], fragment));
6886             }
6887             return result;
6888         }
6889         throw new thymol.ThError("#strings.arrayContainsIgnoreCase Cannot apply arrayContainsIgnoreCase on null");
6890     }
6891     function setContainsIgnoreCase(target, fragment) {
6892         if (target !== null) {
6893             var result = new thymol.ThSet();
6894             for (var k in target) {
6895                 if (target.isContent(k)) {
6896                     result.add(containsIgnoreCase(target[k], fragment));
6897                 }
6898             }
6899             return result;
6900         }
6901         throw new thymol.ThError("#strings.setContainsIgnoreCase Cannot apply setContainsIgnoreCase on null");
6902     }
6903     function startsWith(target, prefix) {
6904         if (target !== null) {
6905             if (prefix !== null) {
6906                 return target.toString().indexOf(prefix) === 0;
6907             }
6908             throw new thymol.ThError("#strings.startsWith Prefix cannot be null");
6909         }
6910         throw new thymol.ThError("#strings.startsWith Cannot apply startsWith on null");
6911     }
6912     function arrayStartsWith(target, prefix) {
6913         if (target !== null) {
6914             var result = [];
6915             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6916                 result.push(startsWith(target[i], prefix));
6917             }
6918             return result;
6919         }
6920         throw new thymol.ThError("#strings.arrayStartsWith Target cannot be null");
6921     }
6922     function setStartsWith(target, prefix) {
6923         if (target !== null) {
6924             var result = new thymol.ThSet();
6925             for (var k in target) {
6926                 if (target.isContent(k)) {
6927                     result.add(startsWith(target[k], prefix));
6928                 }
6929             }
6930             return result;
6931         }
6932         throw new thymol.ThError("#strings.setStartsWith Target cannot be null");
6933     }
6934     function endsWith(target, suffix) {
6935         if (target !== null) {
6936             if (suffix !== null) {
6937                 var str = target.toString();
6938                 return str.indexOf(suffix) === str.length - suffix.length;
6939             }
6940             throw new thymol.ThError("#strings.startsWith Suffix cannot be null");
6941         }
6942         throw new thymol.ThError("#strings.endsWith Cannot apply endsWith on null");
6943     }
6944     function arrayEndsWith(target, suffix) {
6945         if (target !== null) {
6946             var result = [];
6947             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6948                 result.push(endsWith(target[i], suffix));
6949             }
6950             return result;
6951         }
6952         throw new thymol.ThError("#strings.arrayEndsWith Target cannot be null");
6953     }
6954     function setEndsWith(target, suffix) {
6955         if (target !== null) {
6956             var result = new thymol.ThSet();
6957             for (var k in target) {
6958                 if (target.isContent(k)) {
6959                     result.add(endsWith(target[k], suffix));
6960                 }
6961             }
6962             return result;
6963         }
6964         throw new thymol.ThError("#strings.setEndsWith Target cannot be null");
6965     }
6966     function substring(target, start, end) {
6967         if (target !== null) {
6968             return target.toString().substring(start, end);
6969         }
6970         throw new thymol.ThError("#strings.substring Target cannot be null");
6971     }
6972     function arraySubstring(target, start, end) {
6973         if (target !== null) {
6974             var result = [];
6975             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
6976                 result.push(substring(target[i], start, end));
6977             }
6978             return result;
6979         }
6980         throw new thymol.ThError("#strings.arraySubstring Target cannot be null");
6981     }
6982     function setSubstring(target, start, end) {
6983         if (target !== null) {
6984             var result = new thymol.ThSet();
6985             for (var k in target) {
6986                 if (target.isContent(k)) {
6987                     result.add(substring(target[k], start, end));
6988                 }
6989             }
6990             return result;
6991         }
6992         throw new thymol.ThError("#strings.setSubstring Target cannot be null");
6993     }
6994     function substringAfter(target, substr) {
6995         if (target !== null) {
6996             if (substr !== null) {
6997                 var str = target.toString();
6998                 var indx = str.indexOf(substr);
6999                 if (indx < 0) {
7000                     return null;
7001                 }
7002                 return str.substring(indx + substr.length);
7003             }
7004             throw new thymol.ThError("#strings.substringAfter Parameter substring cannot be null");
7005         }
7006         throw new thymol.ThError("#strings.substringAfter Cannot apply substringAfter on null");
7007     }
7008     function arraySubstringAfter(target, substr) {
7009         if (target !== null) {
7010             var result = [];
7011             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7012                 result.push(substringAfter(target[i], substr));
7013             }
7014             return result;
7015         }
7016         throw new thymol.ThError("#strings.arraySubstringAfter Cannot apply arraySubstringAfter on null");
7017     }
7018     function setSubstringAfter(target, substr) {
7019         if (target !== null) {
7020             var result = new thymol.ThSet();
7021             for (var k in target) {
7022                 if (target.isContent(k)) {
7023                     result.add(substringAfter(target[k], substr));
7024                 }
7025             }
7026             return result;
7027         }
7028         throw new thymol.ThError("#strings.setSubstringAfter Cannot apply setSubstringAfter on null");
7029     }
7030     function substringBefore(target, substr) {
7031         if (target !== null) {
7032             if (substr !== null) {
7033                 var str = target.toString();
7034                 var indx = str.indexOf(substr);
7035                 if (indx < 0) {
7036                     return null;
7037                 }
7038                 return str.substring(0, indx);
7039             }
7040             throw new thymol.ThError("#strings.substringBefore Parameter substring cannot be null");
7041         }
7042         throw new thymol.ThError("#strings.substringBefore Cannot apply substringBefore on null");
7043     }
7044     function arraySubstringBefore(target, substr) {
7045         if (target !== null) {
7046             var result = [];
7047             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7048                 result.push(substringBefore(target[i], substr));
7049             }
7050             return result;
7051         }
7052         throw new thymol.ThError("#strings.arraySubstringBefore Cannot apply arraySubstringBefore on null");
7053     }
7054     function setSubstringBefore(target, substr) {
7055         if (target !== null) {
7056             var result = new thymol.ThSet();
7057             for (var k in target) {
7058                 if (target.isContent(k)) {
7059                     result.add(substringBefore(target[k], substr));
7060                 }
7061             }
7062             return result;
7063         }
7064         throw new thymol.ThError("#strings.setSubstringBefore Cannot apply setSubstringBefore on null");
7065     }
7066     function prepend(target, prefix) {
7067         if (target !== null) {
7068             if (prefix !== null) {
7069                 return prefix.toString() + target.toString();
7070             }
7071             throw new thymol.ThError("#strings.prepend Prefix cannot be null");
7072         }
7073         throw new thymol.ThError("#strings.prepend Cannot apply prepend on null");
7074     }
7075     function arrayPrepend(target, prefix) {
7076         if (target !== null) {
7077             var result = [];
7078             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7079                 result.push(prepend(target[i], prefix));
7080             }
7081             return result;
7082         }
7083         throw new thymol.ThError("#strings.arrayPrepend Cannot apply arrayPrepend on null");
7084     }
7085     function setPrepend(target, prefix) {
7086         if (target !== null) {
7087             var result = new thymol.ThSet();
7088             for (var k in target) {
7089                 if (target.isContent(k)) {
7090                     result.add(prepend(target[k], prefix));
7091                 }
7092             }
7093             return result;
7094         }
7095         throw new thymol.ThError("#strings.setPrepend Cannot apply setPrepend on null");
7096     }
7097     function repeat(target, times) {
7098         var result = "";
7099         for (var i = 0; i < times; i++) {
7100             result += target.toString();
7101         }
7102         return result;
7103     }
7104     function append(target, suffix) {
7105         if (target !== null) {
7106             if (suffix !== null) {
7107                 return target.toString() + suffix.toString();
7108             }
7109             throw new thymol.ThError("#strings.append Suffix cannot be null");
7110         }
7111         throw new thymol.ThError("#strings.append Cannot apply append on null");
7112     }
7113     function concat() {
7114         var result = "";
7115         for (var i = 0, iLimit = arguments.length; i < iLimit; i++) {
7116             if (arguments[i] !== null) {
7117                 result += arguments[i];
7118             }
7119         }
7120         return result;
7121     }
7122     function concatReplaceNulls() {
7123         var result = "";
7124         for (var i = 1, iLimit = arguments.length; i < iLimit; i++) {
7125             if (arguments[i] === null) {
7126                 result += arguments[0];
7127             } else {
7128                 result += arguments[i];
7129             }
7130         }
7131         return result;
7132     }
7133     function arrayAppend(target, suffix) {
7134         if (target !== null) {
7135             var result = [];
7136             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7137                 result.push(append(target[i], suffix));
7138             }
7139             return result;
7140         }
7141         throw new thymol.ThError("#strings.arrayAppend Target cannot be null");
7142     }
7143     function setAppend(target, suffix) {
7144         if (target !== null) {
7145             var result = new thymol.ThSet();
7146             for (var k in target) {
7147                 if (target.isContent(k)) {
7148                     result.add(append(target[k], suffix));
7149                 }
7150             }
7151             return result;
7152         }
7153         throw new thymol.ThError("#strings.setAppend Target cannot be null");
7154     }
7155     function indexOf(target, fragment) {
7156         if (target !== null) {
7157             if (fragment !== null) {
7158                 var str = target.toString();
7159                 var indx = str.indexOf(fragment);
7160                 return indx;
7161             }
7162             throw new thymol.ThError("#strings.indexOf Fragment cannot be null");
7163         }
7164         throw new thymol.ThError("#strings.indexOf Cannot apply indexOf on null");
7165     }
7166     function arrayIndexOf(target, fragment) {
7167         if (target !== null) {
7168             var result = [];
7169             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7170                 result.push(indexOf(target[i], fragment));
7171             }
7172             return result;
7173         }
7174         throw new thymol.ThError("#strings.arrayIndexOf Cannot apply arrayIndexOf on null");
7175     }
7176     function setIndexOf(target, fragment) {
7177         if (target !== null) {
7178             var result = new thymol.ThSet();
7179             for (var k in target) {
7180                 if (target.isContent(k)) {
7181                     result.add(indexOf(target[k], fragment));
7182                 }
7183             }
7184             return result;
7185         }
7186         throw new thymol.ThError("#strings.setIndexOf Cannot apply setIndexOf on null");
7187     }
7188     function isEmpty(target) {
7189         if (target !== null) {
7190             var str = target.toString();
7191             if (str !== null) {
7192                 str = str.replace(/(?:[\\]t)/g, "       ").replace(/(?:[\\]n)/g, "\n").replace(/(?:[\\]v)/g, "\v").replace(/(?:[\\]f)/g, "\f").replace(/(?:[\\]r)/g, "\r");
7193                 str = str.trim();
7194                 if (str.length !== 0) {
7195                     return false;
7196                 }
7197             }
7198         }
7199         return true;
7200     }
7201     function arrayIsEmpty(target) {
7202         if (target !== null) {
7203             var result = [];
7204             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7205                 result.push(isEmpty(target[i]));
7206             }
7207             return result;
7208         }
7209         throw new thymol.ThError("#strings.arrayIsEmpty Target cannot be null");
7210     }
7211     function setIsEmpty(target) {
7212         if (target !== null) {
7213             var result = new thymol.ThSet();
7214             for (var k in target) {
7215                 if (target.isContent(k)) {
7216                     result.add(isEmpty(target[k]));
7217                 }
7218             }
7219             return result;
7220         }
7221         throw new thymol.ThError("#strings.setIsEmpty Target cannot be null");
7222     }
7223     function arrayJoin(stringArray, separator) {
7224         if (stringArray !== null) {
7225             if (separator !== null) {
7226                 var sepStr = separator.toString();
7227                 var result = "";
7228                 for (var i = 0, iLimit = stringArray.length; i < iLimit; i++) {
7229                     if ("" !== result) {
7230                         result += sepStr;
7231                     }
7232                     result += stringArray[i];
7233                 }
7234                 return result;
7235             }
7236             throw new thymol.ThError("#strings.arrayJoin Separator cannot be null");
7237         }
7238         throw new thymol.ThError("#strings.arrayJoin Cannot apply join on null");
7239     }
7240     function setJoin(stringSet, separator) {
7241         if (stringSet !== null) {
7242             if (separator !== null) {
7243                 var sepStr = separator.toString();
7244                 var result = "";
7245                 for (var k in stringSet) {
7246                     if (stringSet.isContent(k)) {
7247                         if ("" !== result) {
7248                             result += sepStr;
7249                         }
7250                         result += stringSet[k];
7251                     }
7252                 }
7253                 return result;
7254             }
7255             throw new thymol.ThError("#strings.setJoin Separator cannot be null");
7256         }
7257         throw new thymol.ThError("#strings.setJoin Cannot apply join on null");
7258     }
7259     function doRegExpify(target, flags) {
7260         var result = target.toString();
7261         result = result.replace(/[\\]/g, "\\").replace(/[\^]/g, "^").replace(/[\[]/g, "[").replace(/[\]]/g, "]").replace(/[\(]/g, "(").replace(/[\)]/g, ")");
7262         result = "[" + result + "]";
7263         return new RegExp(result, flags);
7264     }
7265     function doSplit(target, separator) {
7266         var re = doRegExpify(separator);
7267         var splits = target.split(re);
7268         var result = [];
7269         for (var i = 0, iLimit = splits.length; i < iLimit; i++) {
7270             if (splits[i]) {
7271                 result.push(splits[i]);
7272             }
7273         }
7274         return result;
7275     }
7276     function arraySplit(target, separator) {
7277         if (target !== null) {
7278             if (separator !== null) {
7279                 return doSplit(target, separator);
7280             }
7281             throw new thymol.ThError("#strings.arraySplit Separator cannot be null");
7282         }
7283         throw new thymol.ThError("#strings.arraySplit Cannot apply split on null");
7284     }
7285     function setSplit(target, separator) {
7286         if (target !== null) {
7287             if (separator !== null) {
7288                 var result = new thymol.ThSet();
7289                 var splits = doSplit(target, separator);
7290                 for (var i = 0, iLimit = splits.length; i < iLimit; i++) {
7291                     result.add(splits[i]);
7292                 }
7293                 return result;
7294             }
7295             throw new thymol.ThError("#strings.setSplit Separator cannot be null");
7296         }
7297         throw new thymol.ThError("#strings.setSplit Cannot apply split on null");
7298     }
7299     function length(target) {
7300         if (target !== null) {
7301             return target.toString().length;
7302         }
7303         throw new thymol.ThError("#strings.length Cannot apply length on null");
7304     }
7305     function arrayLength(target) {
7306         if (target !== null) {
7307             var result = [];
7308             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7309                 result.push(length(target[i]));
7310             }
7311             return result;
7312         }
7313         throw new thymol.ThError("#strings.arrayLength Target cannot be null");
7314     }
7315     function setLength(target) {
7316         if (target !== null) {
7317             var result = new thymol.ThSet();
7318             for (var k in target) {
7319                 if (target.isContent(k)) {
7320                     result.add(length(target[k]));
7321                 }
7322             }
7323             return result;
7324         }
7325         throw new thymol.ThError("#strings.setLength Target cannot be null");
7326     }
7327     function getReplacer(target) {
7328         var bfr = target.replace(/[$]/g, "[$]").replace(/[*]/g, "[*]").replace(/[\']/g, "[']").replace(/[+]/g, "[+]").replace(/[\(]/g, "[(]").replace(/[\)]/g, "[)]");
7329         return new RegExp(bfr, "g");
7330     }
7331     function replace(target, before, after) {
7332         if (target !== null) {
7333             if (before !== null) {
7334                 var bfr = unescapeXml(before);
7335                 if (after !== null) {
7336                     var re = getReplacer(bfr);
7337                     var aft = unescapeXml(after);
7338                     return target.replace(re, aft);
7339                 }
7340                 throw new thymol.ThError("#strings.replace After cannot be null");
7341             }
7342             throw new thymol.ThError("#strings.replace Before cannot be null");
7343         }
7344         throw new thymol.ThError("#strings.replace Cannot apply replace on null");
7345     }
7346     function arrayReplace(target, before, after) {
7347         if (target !== null) {
7348             if (before !== null) {
7349                 var bfr = unescapeXml(before);
7350                 if (after !== null) {
7351                     var re = getReplacer(bfr);
7352                     var aft = unescapeXml(after);
7353                     var result = [];
7354                     for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7355                         result.push(target[i].toString().replace(re, aft));
7356                     }
7357                     return result;
7358                 }
7359                 throw new thymol.ThError("#strings.arrayReplace After cannot be null");
7360             }
7361             throw new thymol.ThError("#strings.arrayReplace Before cannot be null");
7362         }
7363         throw new thymol.ThError("#strings.arrayReplace Cannot apply replace on null");
7364     }
7365     function setReplace(target, before, after) {
7366         if (target !== null) {
7367             if (before !== null) {
7368                 var bfr = unescapeXml(before);
7369                 if (after !== null) {
7370                     var re = getReplacer(bfr);
7371                     var aft = unescapeXml(after);
7372                     var result = new thymol.ThSet();
7373                     for (var k in target) {
7374                         if (target.isContent(k)) {
7375                             result.add(target[k].toString().replace(re, aft));
7376                         }
7377                     }
7378                     return result;
7379                 }
7380                 throw new thymol.ThError("#strings.setReplace Array of 'after' values cannot be null");
7381             }
7382             throw new thymol.ThError("#strings.setReplace Array of 'before' values cannot be null");
7383         }
7384         throw new thymol.ThError("#strings.setReplace Cannot apply replace on null");
7385     }
7386     function multipleReplace(target, before, after) {
7387         if (target !== null) {
7388             if (before !== null) {
7389                 if (Object.prototype.toString.call(before) == "[object Array]") {
7390                     if (after !== null) {
7391                         if (Object.prototype.toString.call(after) == "[object Array]") {
7392                             if (before.length === after.length) {
7393                                 var result = target;
7394                                 var bfr, aft;
7395                                 for (var i = 0, iLimit = before.length; i < iLimit; i++) {
7396                                     bfr = unescapeXml(before[i]);
7397                                     var re = getReplacer(bfr);
7398                                     aft = unescapeXml(after[i]);
7399                                     result = result.replace(re, aft);
7400                                 }
7401                                 return result;
7402                             }
7403                             throw new thymol.ThError("#strings.multipleReplace Arrays of 'before' and 'after' values must have the same length");
7404                         }
7405                         throw new thymol.ThError("#strings.multipleReplace After must be an array type");
7406                     }
7407                     throw new thymol.ThError("#strings.multipleReplace After cannot be null");
7408                 }
7409                 throw new thymol.ThError("#strings.multipleReplace Before must be an array type");
7410             }
7411             throw new thymol.ThError("#strings.multipleReplace Before cannot be null");
7412         }
7413         throw new thymol.ThError("#strings.multipleReplace Target cannot be null");
7414     }
7415     function arrayMultipleReplace(target, before, after) {
7416         if (target !== null) {
7417             var result = [];
7418             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7419                 result.push(multipleReplace(target[i].toString(), before, after));
7420             }
7421             return result;
7422         }
7423         throw new thymol.ThError("#strings.arrayMultipleReplace Target cannot be null");
7424     }
7425     function setMultipleReplace(target, before, after) {
7426         if (target !== null) {
7427             var result = new thymol.ThSet();
7428             for (var k in target) {
7429                 if (target.isContent(k)) {
7430                     result.add(multipleReplace(target[k].toString(), before, after));
7431                 }
7432             }
7433             return result;
7434         }
7435         throw new thymol.ThError("#strings.setMultipleReplace Target cannot be null");
7436     }
7437     function toUpperCase(target) {
7438         var result = null;
7439         if (target !== null && typeof target !== "undefined") {
7440             result = target.toString().toUpperCase();
7441         }
7442         return result;
7443     }
7444     function arrayToUpperCase(target) {
7445         var result = null;
7446         if (target !== null && typeof target !== "undefined") {
7447             result = [];
7448             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7449                 if (target[i] !== null) {
7450                     result.push(target[i].toString().toUpperCase());
7451                 } else {
7452                     result.push(null);
7453                 }
7454             }
7455         }
7456         return result;
7457     }
7458     function setToUpperCase(target) {
7459         var result = null;
7460         if (target !== null && typeof target !== "undefined") {
7461             result = new thymol.ThSet();
7462             for (var k in target) {
7463                 if (target.isContent(k)) {
7464                     result.add(target[k].toString().toUpperCase());
7465                 }
7466             }
7467         }
7468         return result;
7469     }
7470     function toLowerCase(target) {
7471         var result = null;
7472         if (target !== null && typeof target !== "undefined") {
7473             result = target.toString().toLowerCase();
7474         }
7475         return result;
7476     }
7477     function arrayToLowerCase(target) {
7478         var result = null;
7479         if (target !== null && typeof target !== "undefined") {
7480             result = [];
7481             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7482                 if (target[i] !== null) {
7483                     result.push(target[i].toString().toLowerCase());
7484                 } else {
7485                     result.push(null);
7486                 }
7487             }
7488         }
7489         return result;
7490     }
7491     function setToLowerCase(target) {
7492         var result = null;
7493         if (target !== null && typeof target !== "undefined") {
7494             result = new thymol.ThSet();
7495             for (var k in target) {
7496                 if (target.isContent(k)) {
7497                     result.add(target[k].toString().toLowerCase());
7498                 }
7499             }
7500         }
7501         return result;
7502     }
7503     function trim(target) {
7504         var result = null;
7505         if (target !== null && typeof target !== "undefined") {
7506             result = target.toString().trim();
7507         }
7508         return result;
7509     }
7510     function arrayTrim(target) {
7511         var result = null;
7512         if (target !== null && typeof target !== "undefined") {
7513             result = [];
7514             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7515                 if (target[i] !== null) {
7516                     result.push(target[i].toString().trim());
7517                 } else {
7518                     result.push(null);
7519                 }
7520             }
7521         }
7522         return result;
7523     }
7524     function setTrim(target) {
7525         var result = null;
7526         if (target !== null && typeof target !== "undefined") {
7527             result = new thymol.ThSet();
7528             for (var k in target) {
7529                 if (target.isContent(k)) {
7530                     result.add(target[k].toString().trim());
7531                 }
7532             }
7533         }
7534         return result;
7535     }
7536     function capitalize(target) {
7537         var result = null;
7538         if (target !== null && typeof target !== "undefined") {
7539             result = target.toString();
7540             if (result.length > 0) {
7541                 result = result.charAt(0).toUpperCase() + result.substr(1);
7542             }
7543         }
7544         return result;
7545     }
7546     function arrayCapitalize(target) {
7547         var result = null;
7548         if (target !== null && typeof target !== "undefined") {
7549             result = [];
7550             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7551                 if (target[i] !== null) {
7552                     result.push(capitalize(target[i]));
7553                 } else {
7554                     result.push(null);
7555                 }
7556             }
7557         }
7558         return result;
7559     }
7560     function setCapitalize(target) {
7561         var result = null;
7562         if (target !== null && typeof target !== "undefined") {
7563             result = new thymol.ThSet();
7564             for (var k in target) {
7565                 if (target.isContent(k)) {
7566                     result.add(capitalize(target[k]));
7567                 }
7568             }
7569         }
7570         return result;
7571     }
7572     function unCapitalize(target) {
7573         var result = null;
7574         if (target !== null && typeof target !== "undefined") {
7575             result = target.toString();
7576             if (result.length > 0) {
7577                 result = result.charAt(0).toLowerCase() + result.substr(1);
7578             }
7579         }
7580         return result;
7581     }
7582     function arrayUnCapitalize(target) {
7583         var result = null;
7584         if (target !== null && typeof target !== "undefined") {
7585             result = [];
7586             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7587                 if (target[i] !== null) {
7588                     result.push(unCapitalize(target[i]));
7589                 } else {
7590                     result.push(null);
7591                 }
7592             }
7593         }
7594         return result;
7595     }
7596     function setUnCapitalize(target) {
7597         var result = null;
7598         if (target !== null && typeof target !== "undefined") {
7599             result = new thymol.ThSet();
7600             for (var k in target) {
7601                 if (target.isContent(k)) {
7602                     result.add(unCapitalize(target[k]));
7603                 }
7604             }
7605         }
7606         return result;
7607     }
7608     function capitalizeWords(target, delimiters) {
7609         var splitter;
7610         if (typeof delimiters === "undefined") {
7611             splitter = new RegExp("[^   \r\n\f\v]\\w*", "g");
7612         } else {
7613             var spec = "[^ " + delimiters + "]\\w*";
7614             splitter = new RegExp(spec, "g");
7615         }
7616         var result = null;
7617         if (target !== null && typeof target !== "undefined") {
7618             var str = target.toString();
7619             if (str.length > 0) {
7620                 result = "";
7621                 var matched;
7622                 var indx = 0;
7623                 while ((matched = splitter.exec(str)) !== null) {
7624                     result += str.substring(indx, matched.index);
7625                     result += matched[0].charAt(0).toUpperCase() + matched[0].substr(1);
7626                     indx = splitter.lastIndex;
7627                 }
7628                 result += str.substring(indx);
7629             }
7630         }
7631         return result;
7632     }
7633     function arrayCapitalizeWords(target, delimiters) {
7634         var result = null;
7635         if (target !== null && typeof target !== "undefined") {
7636             result = [];
7637             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7638                 if (target[i] !== null) {
7639                     result.push(capitalizeWords(target[i], delimiters));
7640                 } else {
7641                     result.push(null);
7642                 }
7643             }
7644         }
7645         return result;
7646     }
7647     function setCapitalizeWords(target, delimiters) {
7648         var result = null;
7649         if (target !== null && typeof target !== "undefined") {
7650             result = new thymol.ThSet();
7651             for (var k in target) {
7652                 if (target.isContent(k)) {
7653                     result.add(capitalizeWords(target[k], delimiters));
7654                 }
7655             }
7656         }
7657         return result;
7658     }
7659     function escapeXml(target, escapeQuotesParam) {
7660         var result = target;
7661         if (target !== null && typeof target !== "undefined") {
7662             var escapeQuotes = escapeQuotesParam !== null && typeof escapeQuotesParam !== "undefined" && escapeQuotesParam;
7663             if (escapeQuotes) {
7664                 result = escapeXmlTrue(target);
7665             } else {
7666                 result = "";
7667                 for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7668                     var c = target.charAt(i);
7669                     if (c === "&") {
7670                         if (!isEntityStart(target, i)) {
7671                             c = "&amp;";
7672                         }
7673                     } else if (c === "<") {
7674                         c = "&amp;lt;";
7675                     } else if (c === ">") {
7676                         c = "&amp;gt;";
7677                     } else if (c === '"') {
7678                         c = "&amp;quot;";
7679                     } else if (c === "'") {
7680                         c = "&amp;#39;";
7681                     }
7682                     result += c;
7683                 }
7684             }
7685         }
7686         return result;
7687     }
7688     function escapeXmlTrue(target) {
7689         var result = "";
7690         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7691             var c = target.charAt(i);
7692             if (c === "&") {
7693                 if (!isEntityStart(target, i)) {
7694                     c = "&amp;";
7695                 }
7696             } else if (c === "<") {
7697                 c = "&lt;";
7698             } else if (c === ">") {
7699                 c = "&gt;";
7700             } else if (c === '"') {
7701                 c = "&quot;";
7702             } else if (c === "'") {
7703                 c = "&#39;";
7704             }
7705             result += c;
7706         }
7707         return result;
7708     }
7709     function unescapeXml(target) {
7710         var result = "";
7711         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7712             var c = target.charAt(i);
7713             if (c === "&") {
7714                 c = isEntity(target, i);
7715                 if (c !== "&") {
7716                     i += c.length;
7717                     if (c === "&lt;") {
7718                         c = "<";
7719                     } else if (c === "&gt;") {
7720                         c = ">";
7721                     } else if (c === "&amp;") {
7722                         c = "&";
7723                     } else if (c === "&quot;") {
7724                         c = '"';
7725                     } else if (c === "&#39;") {
7726                         c = "'";
7727                     }
7728                 } else {
7729                     c = "&amp;";
7730                 }
7731             }
7732             result += c;
7733         }
7734         return result;
7735     }
7736     function isEntity(buffer, position) {
7737         var entity = "&";
7738         var i = position + 1;
7739         while (i < buffer.length) {
7740             var c = buffer[i];
7741             if (!(c >= "A" && c <= "Z" || c >= "a" && c <= "z" || c >= "0" && c <= "9" || c == ";" || c == "#")) {
7742                 return "&";
7743             }
7744             entity += c;
7745             if (c == ";") {
7746                 return entity;
7747             }
7748             i++;
7749         }
7750         return "&";
7751     }
7752     function isEntityStart(buffer, position) {
7753         var i = position + 1;
7754         while (i < buffer.length) {
7755             var c = buffer[i];
7756             if (!(c >= "A" && c <= "Z" || c >= "a" && c <= "z" || c >= "0" && c <= "9" || c == ";" || c == "#")) {
7757                 return false;
7758             }
7759             if (c == ";") {
7760                 return true;
7761             }
7762             i++;
7763         }
7764         return false;
7765     }
7766     function arrayEscapeXml(target) {
7767         var result = null;
7768         if (target !== null && typeof target !== "undefined") {
7769             result = [];
7770             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7771                 if (target[i] !== null) {
7772                     result.push(escapeXml(target[i], false));
7773                 } else {
7774                     result.push(null);
7775                 }
7776             }
7777         }
7778         return result;
7779     }
7780     function setEscapeXml(target) {
7781         var result = null;
7782         if (target !== null && typeof target !== "undefined") {
7783             result = new thymol.ThSet();
7784             for (var k in target) {
7785                 if (target.isContent(k)) {
7786                     result.add(escapeXml(target[k], false));
7787                 }
7788             }
7789         }
7790         return result;
7791     }
7792     function escapeJavaScript(target) {
7793         var result = target;
7794         if (target !== null && typeof target !== "undefined") {
7795             result = escapeJavaAny(target, true);
7796         }
7797         return result;
7798     }
7799     function escapeJavaAny(target, javaScript) {
7800         var result = "";
7801         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7802             var c = target.charAt(i);
7803             var cc = target.charCodeAt(i);
7804             if (cc >= 32 && cc <= 127) {
7805                 switch (c) {
7806                   case "\\":
7807                     c = "\\";
7808                     break;
7809
7810                   case '"':
7811                     c = '\\"';
7812                     break;
7813
7814                   case "'":
7815                     if (javaScript) {
7816                         c = "\\'";
7817                     }
7818                     break;
7819
7820                   case "/":
7821                     if (javaScript) {
7822                         if (i > 0 && target.charAt(i - 1) == "<") {
7823                             c = "\\/";
7824                         }
7825                     }
7826                     break;
7827
7828                   case ">":
7829                     if (javaScript && i > 1) {
7830                         if (target.charAt(i - 1) == "]" && target.charAt(i - 2) == "]") {
7831                             c = "\\>";
7832                         }
7833                     }
7834                     break;
7835
7836                   default:
7837                     break;
7838                 }
7839             } else {
7840                 switch (c) {
7841                   case "        ":
7842                     c = "\\t";
7843                     break;
7844
7845                   case "\n":
7846                     c = "\\n";
7847                     break;
7848
7849                   case "\b":
7850                     c = "\\b";
7851                     break;
7852
7853                   case "\f":
7854                     c = "\\f";
7855                     break;
7856
7857                   case "\r":
7858                     c = "\\r";
7859                     break;
7860
7861                   default:
7862                     if (javaScript) {
7863                         c = hexEscape(cc);
7864                     } else {
7865                         c = unicodeEscape(cc);
7866                     }
7867                     break;
7868                 }
7869             }
7870             result += c;
7871         }
7872         return result;
7873     }
7874     function unicodeEscape(c) {
7875         var x = c + 65536;
7876         x = x.toString(16);
7877         x = x.slice(1);
7878         var output = "\\u" + x.toUpperCase();
7879         return output;
7880     }
7881     function hexEscape(c) {
7882         var x = c + 256;
7883         x = x.toString(16);
7884         x = x.slice(1);
7885         var output = "\\x" + x.toUpperCase();
7886         return output;
7887     }
7888     function arrayEscapeJavaScript(target) {
7889         var result = null;
7890         if (target !== null && typeof target !== "undefined") {
7891             result = [];
7892             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7893                 if (target[i] !== null) {
7894                     result.push(escapeJavaScript(target[i]));
7895                 } else {
7896                     result.push(null);
7897                 }
7898             }
7899         }
7900         return result;
7901     }
7902     function setEscapeJavaScript(target) {
7903         var result = null;
7904         if (target !== null && typeof target !== "undefined") {
7905             result = new thymol.ThSet();
7906             for (var k in target) {
7907                 if (target.isContent(k)) {
7908                     result.add(escapeJavaScript(target[k]));
7909                 }
7910             }
7911         }
7912         return result;
7913     }
7914     function unescapeJavaScript(target) {
7915         var result = target;
7916         if (target !== null && typeof target !== "undefined") {
7917             result = unescapeJavaAny(target);
7918         }
7919         return result;
7920     }
7921     function unescapeJavaAny(target) {
7922         var result = "";
7923         var unicodeSpec = "";
7924         var unicodeLen = -1;
7925         var hexSpec = "";
7926         var hexLen = -1;
7927         var lastWasEscape = false;
7928         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
7929             var c = target.charAt(i);
7930             if (unicodeLen >= 0) {
7931                 unicodeSpec += c;
7932                 if (c >= "0" && c <= "9" || c >= "A" && c <= "F" || c >= "a" && c <= "f") {
7933                     unicodeLen++;
7934                     if (unicodeLen > 3) {
7935                         var cc = parseInt(unicodeSpec, 16);
7936                         c = String.fromCharCode(cc);
7937                         unicodeSpec = "";
7938                         unicodeLen = -1;
7939                         result += c;
7940                         lastWasEscape = false;
7941                     }
7942                 } else {
7943                     return target;
7944                 }
7945             } else if (hexLen >= 0) {
7946                 hexSpec += c;
7947                 if (c >= "0" && c <= "9" || c >= "A" && c <= "F" || c >= "a" && c <= "f") {
7948                     hexLen++;
7949                     if (hexLen > 1) {
7950                         var cc = parseInt(hexSpec, 16);
7951                         c = String.fromCharCode(cc);
7952                         hexSpec = "";
7953                         hexLen = -1;
7954                         result += c;
7955                         lastWasEscape = false;
7956                     }
7957                 } else {
7958                     return target;
7959                 }
7960             } else if (lastWasEscape) {
7961                 if (c === "u") {
7962                     unicodeLen = 0;
7963                 } else if (c === "x") {
7964                     hexLen = 0;
7965                 } else {
7966                     switch (c) {
7967                       case "t":
7968                         c = "   ";
7969                         break;
7970
7971                       case "n":
7972                         c = "\n";
7973                         break;
7974
7975                       case "b":
7976                         c = "\b";
7977                         break;
7978
7979                       case "f":
7980                         c = "\f";
7981                         break;
7982
7983                       case "r":
7984                         c = "\r";
7985                         break;
7986
7987                       default:
7988                         break;
7989                     }
7990                     result += c;
7991                     lastWasEscape = false;
7992                 }
7993             } else if (c == "\\") {
7994                 lastWasEscape = true;
7995             } else {
7996                 result += c;
7997                 lastWasEscape = false;
7998             }
7999         }
8000         if (unicodeLen >= 0) {
8001             result += "\\u" + unicodeSpec;
8002         } else if (hexLen >= 0) {
8003             result += "\\x" + hexSpec;
8004         } else if (lastWasEscape) {
8005             result += "\\";
8006         }
8007         return result;
8008     }
8009     function arrayUnescapeJavaScript(target) {
8010         var result = null;
8011         if (target !== null && typeof target !== "undefined") {
8012             result = [];
8013             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
8014                 if (target[i] !== null) {
8015                     result.push(unescapeJavaScript(target[i]));
8016                 } else {
8017                     result.push(null);
8018                 }
8019             }
8020         }
8021         return result;
8022     }
8023     function setUnescapeJavaScript(target) {
8024         var result = null;
8025         if (target !== null && typeof target !== "undefined") {
8026             result = new thymol.ThSet();
8027             for (var k in target) {
8028                 if (target.isContent(k)) {
8029                     result.add(unescapeJavaScript(target[k]));
8030                 }
8031             }
8032         }
8033         return result;
8034     }
8035     function escapeJava(target) {
8036         var result = target;
8037         if (target !== null && typeof target !== "undefined") {
8038             result = escapeJavaAny(target, false);
8039         }
8040         return result;
8041     }
8042     function arrayEscapeJava(target) {
8043         var result = null;
8044         if (target !== null && typeof target !== "undefined") {
8045             result = [];
8046             for (var i = 0, iLimit = target.length; i < iLimit; i++) {
8047                 if (target[i] !== null) {
8048                     result.push(escapeJava(target[i]));
8049                 } else {
8050                     result.push(null);
8051                 }
8052             }
8053         }
8054         return result;
8055     }
8056     function setEscapeJava(target) {
8057         var result = null;
8058         if (target !== null && typeof target !== "undefined") {
8059             result = new thymol.ThSet();
8060             for (var k in target) {
8061                 if (target.isContent(k)) {
8062                     result.add(escapeJava(target[k]));
8063                 }
8064             }
8065         }
8066         return result;
8067     }
8068     var ALPHA_NUMERIC = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
8069     function randomAlphanumeric(count) {
8070         var result = "";
8071         for (var i = 0; i < count; i++) {
8072             result += ALPHA_NUMERIC.charAt(Math.floor(Math.random() * ALPHA_NUMERIC.length));
8073         }
8074         return result;
8075     }
8076     function defaultString(target, defaultValue) {
8077         if (defaultValue !== null && typeof defaultValue !== "undefined") {
8078             if (target == null) {
8079                 return defaultValue.toString();
8080             }
8081             var targetString = target.toString();
8082             if (isEmpty(targetString)) {
8083                 return defaultValue.toString();
8084             }
8085             return targetString;
8086         }
8087         throw new thymol.ThError("#strings.defaultString defaultValue cannot be null");
8088     }
8089     function doArrayDefaultString(target, defaultValue) {
8090         if (target == null || typeof target === "undefined") {
8091             return target;
8092         }
8093         var result = [];
8094         for (var i = 0, iLimit = target.length; i < iLimit; i++) {
8095             result.push(defaultString(target[i], defaultValue));
8096         }
8097         return result;
8098     }
8099     function arrayDefaultString(target, defaultValue) {
8100         if (defaultValue !== null && typeof defaultValue !== "undefined") {
8101             return doArrayDefaultString(target, defaultValue);
8102         }
8103         throw new thymol.ThError("#strings.arrayDefaultString defaultValue cannot be null");
8104     }
8105     function listDefaultString(target, defaultValue) {
8106         if (defaultValue !== null && typeof defaultValue !== "undefined") {
8107             return doArrayDefaultString(target, defaultValue);
8108         }
8109         throw new thymol.ThError("#strings.listDefaultString defaultValue cannot be null");
8110     }
8111     function setDefaultString(target, defaultValue) {
8112         if (defaultValue !== null && typeof defaultValue !== "undefined") {
8113             if (target == null || typeof target === "undefined") {
8114                 return target;
8115             }
8116             result = new thymol.ThSet();
8117             for (var k in target) {
8118                 if (target.isContent(k)) {
8119                     result.add(defaultString(target[k], defaultValue));
8120                 }
8121             }
8122             return result;
8123         }
8124         throw new thymol.ThError("#strings.setDefaultString defaultValue cannot be null");
8125     }
8126     return {
8127         thExpressionObjectName: thExpressionObjectName,
8128         toString: toString,
8129         arrayToString: arrayToString,
8130         listToString: arrayToString,
8131         setToString: setToString,
8132         abbreviate: abbreviate,
8133         arrayAbbreviate: arrayAbbreviate,
8134         listAbbreviate: arrayAbbreviate,
8135         setAbbreviate: setAbbreviate,
8136         equals: equals,
8137         equalsIgnoreCase: equalsIgnoreCase,
8138         contains: contains,
8139         arrayContains: arrayContains,
8140         listContains: arrayContains,
8141         setContains: setContains,
8142         containsIgnoreCase: containsIgnoreCase,
8143         arrayContainsIgnoreCase: arrayContainsIgnoreCase,
8144         listContainsIgnoreCase: arrayContainsIgnoreCase,
8145         setContainsIgnoreCase: setContainsIgnoreCase,
8146         startsWith: startsWith,
8147         arrayStartsWith: arrayStartsWith,
8148         listStartsWith: arrayStartsWith,
8149         setStartsWith: setStartsWith,
8150         endsWith: endsWith,
8151         arrayEndsWith: arrayEndsWith,
8152         listEndsWith: arrayEndsWith,
8153         setEndsWith: setEndsWith,
8154         substring: substring,
8155         arraySubstring: arraySubstring,
8156         listSubstring: arraySubstring,
8157         setSubstring: setSubstring,
8158         substringAfter: substringAfter,
8159         arraySubstringAfter: arraySubstringAfter,
8160         listSubstringAfter: arraySubstringAfter,
8161         setSubstringAfter: setSubstringAfter,
8162         substringBefore: substringBefore,
8163         arraySubstringBefore: arraySubstringBefore,
8164         listSubstringBefore: arraySubstringBefore,
8165         setSubstringBefore: setSubstringBefore,
8166         prepend: prepend,
8167         arrayPrepend: arrayPrepend,
8168         listPrepend: arrayPrepend,
8169         setPrepend: setPrepend,
8170         repeat: repeat,
8171         append: append,
8172         concat: concat,
8173         concatReplaceNulls: concatReplaceNulls,
8174         arrayAppend: arrayAppend,
8175         listAppend: arrayAppend,
8176         setAppend: setAppend,
8177         indexOf: indexOf,
8178         arrayIndexOf: arrayIndexOf,
8179         listIndexOf: arrayIndexOf,
8180         setIndexOf: setIndexOf,
8181         isEmpty: isEmpty,
8182         arrayIsEmpty: arrayIsEmpty,
8183         listIsEmpty: arrayIsEmpty,
8184         setIsEmpty: setIsEmpty,
8185         arrayJoin: arrayJoin,
8186         listJoin: arrayJoin,
8187         setJoin: setJoin,
8188         arraySplit: arraySplit,
8189         listSplit: arraySplit,
8190         setSplit: setSplit,
8191         length: length,
8192         arrayLength: arrayLength,
8193         listLength: arrayLength,
8194         setLength: setLength,
8195         replace: replace,
8196         arrayReplace: arrayReplace,
8197         listReplace: arrayReplace,
8198         setReplace: setReplace,
8199         multipleReplace: multipleReplace,
8200         arrayMultipleReplace: arrayMultipleReplace,
8201         listMultipleReplace: arrayMultipleReplace,
8202         setMultipleReplace: setMultipleReplace,
8203         toUpperCase: toUpperCase,
8204         arrayToUpperCase: arrayToUpperCase,
8205         listToUpperCase: arrayToUpperCase,
8206         setToUpperCase: setToUpperCase,
8207         toLowerCase: toLowerCase,
8208         arrayToLowerCase: arrayToLowerCase,
8209         listToLowerCase: arrayToLowerCase,
8210         setToLowerCase: setToLowerCase,
8211         trim: trim,
8212         arrayTrim: arrayTrim,
8213         listTrim: arrayTrim,
8214         setTrim: setTrim,
8215         capitalize: capitalize,
8216         arrayCapitalize: arrayCapitalize,
8217         listCapitalize: arrayCapitalize,
8218         setCapitalize: setCapitalize,
8219         unCapitalize: unCapitalize,
8220         arrayUnCapitalize: arrayUnCapitalize,
8221         listUnCapitalize: arrayUnCapitalize,
8222         setUnCapitalize: setUnCapitalize,
8223         capitalizeWords: capitalizeWords,
8224         arrayCapitalizeWords: arrayCapitalizeWords,
8225         listCapitalizeWords: arrayCapitalizeWords,
8226         setCapitalizeWords: setCapitalizeWords,
8227         escapeXml: escapeXml,
8228         arrayEscapeXml: arrayEscapeXml,
8229         listEscapeXml: arrayEscapeXml,
8230         setEscapeXml: setEscapeXml,
8231         escapeJavaScript: escapeJavaScript,
8232         arrayEscapeJavaScript: arrayEscapeJavaScript,
8233         listEscapeJavaScript: arrayEscapeJavaScript,
8234         setEscapeJavaScript: setEscapeJavaScript,
8235         unescapeJavaScript: unescapeJavaScript,
8236         arrayUnescapeJavaScript: arrayUnescapeJavaScript,
8237         listUnescapeJavaScript: arrayUnescapeJavaScript,
8238         setUnescapeJavaScript: setUnescapeJavaScript,
8239         escapeJava: escapeJava,
8240         arrayEscapeJava: arrayEscapeJava,
8241         listEscapeJava: arrayEscapeJava,
8242         setEscapeJava: setEscapeJava,
8243         unescapeJava: unescapeJavaScript,
8244         arrayUnescapeJava: arrayUnescapeJavaScript,
8245         listUnescapeJava: arrayUnescapeJavaScript,
8246         setUnescapeJava: setUnescapeJavaScript,
8247         randomAlphanumeric: randomAlphanumeric,
8248         defaultString: defaultString,
8249         arrayDefaultString: arrayDefaultString,
8250         listDefaultString: listDefaultString,
8251         setDefaultString: setDefaultString
8252     };
8253 }();
8254
8255 thymol.thObjectsConfigureModules = function() {
8256     thymol.addDialect({
8257         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 ]
8258     });
8259 };
8260
8261 (function() {
8262     var DOMParser_proto = thymol.thDomParser.prototype, real_parseFromString = DOMParser_proto.parseFromString;
8263     try {
8264         if (new thymol.thDomParser().parseFromString("", "text/html")) {
8265             return;
8266         }
8267     } catch (ignore) {}
8268     DOMParser_proto.parseFromString = function(markup, type) {
8269         var res, doc;
8270         if (/^\s*text\/html\s*(?:;|$)/i.test(type)) {
8271             doc = thymol.thDocument.implementation.createHTMLDocument("");
8272             if (markup.toLowerCase().indexOf("<!doctype") > -1) {
8273                 doc.documentElement.innerHTML = markup;
8274             } else {
8275                 doc.body.innerHTML = markup;
8276             }
8277             res = doc;
8278         } else {
8279             res = real_parseFromString.apply(this, arguments);
8280         }
8281         return res;
8282     };
8283 })();
8284
8285 if (!Array.indexOf) {
8286     Array.prototype.indexOf = function(obj, start) {
8287         for (var i = start || 0; i < this.length; i++) {
8288             if (this[i] === obj) {
8289                 return i;
8290             }
8291         }
8292         return -1;
8293     };
8294 }
8295
8296 $(function() {
8297     thymol.jqSetup($);
8298     thymol.execute(document);
8299 });
8300
8301 $(window).unload(function() {
8302     if (thymol.sessionContext && thymol.sessionContext.persist) {
8303         thymol.sessionContext.persist();
8304     }
8305 });