server/java/renkan-web/src/main/webapp/static/js/thymol.js
changeset 316 242510015401
parent 309 0c3e6e66881f
equal deleted inserted replaced
315:8c85ab4cf3aa 316:242510015401
       
     1 /*-------------------- Thymol - the flavour of Thymeleaf --------------------*
       
     2 
       
     3    Thymol version 0.1.2 Copyright 2012 James J. Benson.
       
     4    jjbenson .AT. users.sf.net
       
     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 var thURL = "http://www.thymeleaf.org";
       
    21 var thPrefix = "th";
       
    22 var thProtocol = "file:///";
       
    23 var thCache = new Object;
       
    24 
       
    25 $(function() {
       
    26 	thymol();
       
    27 });
       
    28 
       
    29 var thymol = function() {
       
    30 	
       
    31 	var urlParams = {};
       
    32 	(function() {
       
    33 		var e, a = /\+/g, r = /([^&=]+)=?([^&]*)/g, d = function(s) {
       
    34 			return decodeURIComponent(s.replace(a, " "));
       
    35 		}, f = function(s) {
       
    36 			return new Param(d(s));
       
    37 		}, q = window.location.search.substring(1);
       
    38 		while (e = r.exec(q)) {
       
    39 			urlParams[d(e[1])] = f(e[2]);
       
    40 		}
       
    41 	})();
       
    42 
       
    43 	var debug = getThParam("thDebug",true,false);
       
    44 	var root = getThParam("thRoot",false,true);
       
    45 	var path = getThParam("thPath",false,true);
       
    46 
       
    47 	$.ajaxSetup({
       
    48 		async : false,
       
    49 		isLocal : true
       
    50 	});
       
    51 
       
    52 	(function() {
       
    53 		var htmlTag = $("html")[0];
       
    54 		$(htmlTag.attributes).each(function() {
       
    55 			if (thURL == this.value) {
       
    56 				var nsspec = this.localName.split(":");
       
    57 				if (nsspec.length > 0) {
       
    58 					thPrefix = nsspec[nsspec.length - 1];
       
    59 					return;
       
    60 				}
       
    61 			}
       
    62 		});
       
    63 	})();
       
    64 
       
    65 	var thIncl = new ThObj("include");
       
    66 	var thSubs = new ThObj("substituteby");
       
    67 	var thIf = new ThObj("if");
       
    68 	var thUnless = new ThObj("unless");
       
    69 	var thSwitch = new ThObj("switch");
       
    70 	var thCase = new ThObj("case");
       
    71 
       
    72 	var thFragEscp = "[" + thPrefix + "\\:fragment='";
       
    73 	var base = new ThNode(document, false, null, null, null, document.nodeName, "::", false, document);
       
    74 	process(base);
       
    75 	return;
       
    76 
       
    77 	function process(base) {
       
    78 		var n = base;
       
    79 		while (n.thDoc) {
       
    80 			getChildren(n);
       
    81 			if (n.firstChild && n.firstChild.thDoc && !n.visited) {
       
    82 				n.visited = true;
       
    83 				n = n.firstChild;
       
    84 			}
       
    85 			else {
       
    86 				doReplace(n.isNode, n.element, n.thDoc);
       
    87 				if (n.nextSibling && n.nextSibling.thDoc) {
       
    88 					n = n.nextSibling;
       
    89 				}
       
    90 				else {
       
    91 					if (n == base)
       
    92 						break;
       
    93 					else {
       
    94 						n = n.parentDoc;
       
    95 					}
       
    96 				}
       
    97 			}
       
    98 		}
       
    99 	}
       
   100 
       
   101 	function getChildren(base) {
       
   102 		var thIfSpecs = $(thIf.escp, base.thDoc);
       
   103 		var thUnlessSpecs = $(thUnless.escp, base.thDoc);
       
   104 		var thSwitchSpecs = $(thSwitch.escp, base.thDoc);
       
   105 		var ths = $(thIfSpecs).add(thUnlessSpecs).add(thSwitchSpecs);
       
   106 		ths.each(function() {
       
   107 			var element = this;
       
   108 			$(element.attributes).each(function() {
       
   109 				var thAttr = this;
       
   110 				if (thIf.name == thAttr.name || thUnless.name == thAttr.name || thSwitch.name == thAttr.name) {
       
   111 					processConditional(element, base, thAttr);
       
   112 				}
       
   113 			});
       
   114 		});
       
   115 		var thInclSpecs = $(thIncl.escp, base.thDoc);
       
   116 		var thSubsSpecs = $(thSubs.escp, base.thDoc);
       
   117 		ths = $(thInclSpecs).add(thSubsSpecs);
       
   118 		var count = 0;
       
   119 		var last = null;
       
   120 		ths.each(function() {
       
   121 			var element = this;
       
   122 			$(element.attributes).each(function() {
       
   123 				var thAttr = this;
       
   124 				if (thIncl.name == thAttr.name || thSubs.name == thAttr.name) {
       
   125 					var child = processImport(element, base, thAttr);
       
   126 					if( child != null ) {
       
   127 						if (count == 0) {
       
   128 							base.firstChild = child;
       
   129 						}
       
   130 						else {
       
   131 							last.nextSibling = child;
       
   132 						}
       
   133 						last = child;
       
   134 						count++;						
       
   135 					}
       
   136 				}
       
   137 			});
       
   138 		});
       
   139 	}
       
   140 
       
   141 	function processConditional(element, base, attr) {
       
   142 		var args = attr.value.match(/[$\*#]{(!?.*)}/);
       
   143 		var processed = false;
       
   144 		if (args.length > 0) {
       
   145 			var param = args[1];
       
   146 			if (thSwitch.name == attr.name) {
       
   147 				processed = processSwitch(element, base, attr, param);
       
   148 			}
       
   149 			else {
       
   150 				var negate = false;
       
   151 				if (args[1].charAt(0) == '!') {
       
   152 					negate = true;
       
   153 					param = args[1].substring(1);
       
   154 				}
       
   155 				if ((!negate && isTrue(param)) || (negate && !isTrue(param))) {
       
   156 					if (thUnless.name == attr.name) { // true for "if" and
       
   157 						// false for "unless"
       
   158 						element.innerHTML = "";
       
   159 					}
       
   160 					processed = true;
       
   161 				}
       
   162 				else {
       
   163 					if (thIf.name == attr.name) { // false for "if", true for
       
   164 						// "unless"
       
   165 						element.innerHTML = "";
       
   166 					}
       
   167 					processed = true;
       
   168 				}
       
   169 
       
   170 			}
       
   171 		}
       
   172 		if (!processed && debug) {
       
   173 			window.alert("thymol.processConditional cannot process: " + attr.name + "=\"" + attr.value + "\"\n" + element.innerHTML);
       
   174 		}
       
   175 		element.removeAttribute(attr.name);
       
   176 	}
       
   177 
       
   178 	function processSwitch(element, base, attr, param) {
       
   179 		var matched = false;
       
   180 		var haveDefault = false;
       
   181 		var thCaseSpecs = $(thCase.escp, element);
       
   182 		thCaseSpecs.each(function() {
       
   183 			var caseClause = this;
       
   184 			var remove = true;
       
   185 			$(caseClause.attributes).each(function() {
       
   186 				var ccAttr = this;
       
   187 				if (thCase.name == ccAttr.name) {
       
   188 					if (!matched) {
       
   189 						var s = urlParams[param];
       
   190 						if (ccAttr.value == "*" || (s && (s.getStringValue() == ccAttr.value))) {
       
   191 							matched = true;
       
   192 							remove = false;
       
   193 						}
       
   194 					}
       
   195 					caseClause.removeAttribute(ccAttr.name);
       
   196 				}
       
   197 			});
       
   198 			if (remove) {
       
   199 				caseClause.innerHTML = "";
       
   200 			}
       
   201 		});
       
   202 		return matched;
       
   203 	}
       
   204 
       
   205 	function processImport(element, base, attr) {
       
   206 		var importNode = null;
       
   207 		var filePart = null;
       
   208 		var fragmentPart = "::";
       
   209 		if (attr.value.indexOf("::") < 0) {
       
   210 			filePart = getFilePart(attr.value); 
       
   211 		}
       
   212 		else {
       
   213 			var names = attr.value.split("::");
       
   214 			filePart = getFilePart(names[0].trim());
       
   215 			fragmentPart = substitute(names[1].trim());
       
   216 		}
       
   217 		var isNode = (thSubs.name == attr.localName);
       
   218 		if (thCache[filePart] != null && thCache[filePart][fragmentPart] != null) {
       
   219 			isNode = ((thSubs.name == attr.localName) || (fragmentPart == "::"));
       
   220 			importNode = new ThNode(thCache[filePart][fragmentPart], false, base, null, null, filePart, fragmentPart, isNode, element);
       
   221 		}
       
   222 		else {
       
   223 			var fileName = filePart + ".html";
       
   224 			$.get(fileName, function(content, status) {
       
   225 				if ("success" == status) {
       
   226 					if (thCache[filePart] == null) {
       
   227 						thCache[filePart] = new Object;
       
   228 					}
       
   229 					if (fragmentPart == "::") {
       
   230 						var htmlContent = $("html", content)[0];
       
   231 						thCache[filePart][fragmentPart] = htmlContent;
       
   232 					}
       
   233 					else {
       
   234 						var fragSpec = thFragEscp + fragmentPart + "']";
       
   235 						var fragArray = $(fragSpec, content);
       
   236 						$(fragArray).each(function() {
       
   237 							thCache[filePart][fragmentPart] = this;
       
   238 						});
       
   239 					}
       
   240 					importNode = new ThNode(thCache[filePart][fragmentPart], false, base, null, null, filePart, fragmentPart, isNode, element);
       
   241 				}
       
   242 				else if (debug) {
       
   243 					window.alert("file read failed: " + filePart + " fragment: " + fragmentPart);
       
   244 				}
       
   245 	    	}, "xml");
       
   246 			if (importNode == null && debug) {
       
   247 				window.alert("fragment import failed: " + filePart + " fragment: " + fragmentPart);
       
   248 			}
       
   249 		}
       
   250 		element.removeAttribute(attr.name);		
       
   251 		return importNode;
       
   252 	}
       
   253 	
       
   254 	function getFilePart(part) {
       
   255 		var result = substitute(part);
       
   256 		if( result.charAt(0) != '.' ) {	// Initial period character indicates a relative path
       
   257 			if( result.indexOf('/') >= 0 ) {	// If it doesn't start with a '.', and there are no path separators, it's also treated as relative
       
   258 				result = thProtocol + root + path + result;													
       
   259 			}
       
   260 		}
       
   261 		return result;
       
   262 	}
       
   263 
       
   264 	function doReplace(isNode, element, content) {
       
   265 		if (isNode) {
       
   266 			element.parentNode.replaceChild(content.cloneNode(true), element);
       
   267 		}
       
   268 		else {			
       
   269 			try {
       
   270 				element.innerHTML = content.innerHTML;
       
   271 			}
       
   272 			catch (err) { // Work-around for IE
       
   273 				while (element.firstChild != null) {
       
   274 					element.removeChild(element.firstChild);
       
   275 				}
       
   276 				for (i = 0; i < content.childNodes.length; i++) {
       
   277 					element.appendChild(content.childNodes[i].cloneNode(true));
       
   278 				}
       
   279 			}			
       
   280 		}
       
   281 	}
       
   282 
       
   283 	function ThNode(thDoc, visited, parentDoc, firstChild, nextSibling, fileName, fragName, isNode, element) {
       
   284 		this.thDoc = thDoc;
       
   285 		this.visited = visited;
       
   286 		this.parentDoc = parentDoc;
       
   287 		this.firstChild = firstChild;
       
   288 		this.nextSibling = nextSibling;
       
   289 		this.fileName = fileName;
       
   290 		this.fragName = fragName;
       
   291 		this.isNode = isNode;
       
   292 		this.element = element;
       
   293 	}
       
   294 
       
   295 	function ThObj(suffix) {
       
   296 		this.name = thPrefix + ":" + suffix;
       
   297 		this.escp = "[" + thPrefix + "\\:" + suffix + "]";
       
   298 	}
       
   299 
       
   300 	function Param(valueArg) {
       
   301 		this.value = valueArg;
       
   302 		this.getBooleanValue = function() {
       
   303 			return !(this.value == "false" || this.value == "off" || this.value == "no");
       
   304 		};
       
   305 		this.getStringValue = function() {
       
   306 			return this.value;
       
   307 		};
       
   308 		this.getNumericValue = function() {
       
   309 			return Number(this.value);
       
   310 		};
       
   311 	}
       
   312 
       
   313 	function isTrue(arg) {
       
   314 		var p = urlParams[arg];
       
   315 		if (p) {
       
   316 			return p.getBooleanValue();
       
   317 		}
       
   318 		return false;
       
   319 	}
       
   320 	
       
   321 	function substitute(argValue) {
       
   322 		var result = argValue;
       
   323 		var args = argValue.match(/[$\*#]{(!?.*)}/);
       
   324 		if (args != null && args.length > 0) {
       
   325 			var param = args[1];
       
   326 			if(param) {
       
   327 				var paramValue = urlParams[param];
       
   328 				if (paramValue) {
       
   329 					result = paramValue.value;
       
   330 				}					
       
   331 			}		
       
   332 		}			
       
   333 		return result;
       
   334 	}
       
   335 
       
   336 	function getThParam(paramName,isBoolean,isPath) {
       
   337 		var localValue;
       
   338 		if( isBoolean ) {
       
   339 			localValue = false;
       
   340 		}
       
   341 		else {
       
   342 			localValue = "";			
       
   343 		}
       
   344 		var theParam = urlParams[paramName];
       
   345 		if (isBoolean && theParam) {
       
   346 			localValue = theParam.getBooleanValue();
       
   347 		}
       
   348 		else {
       
   349 			var paramValue;
       
   350 			try {			
       
   351 				paramValue = eval(paramName);
       
   352 				if( !(typeof paramValue === "undefined") ) {
       
   353 					if( paramValue != null ) {
       
   354 						if ( isBoolean ) {
       
   355 							localValue = (paramValue==true);
       
   356 						}								
       
   357 						else {
       
   358 							localValue = paramValue;							
       
   359 						}
       
   360 					}
       
   361 				}
       
   362 			}
       
   363 			catch (err) {
       
   364 				if (err instanceof ReferenceError) {					
       
   365 				}
       
   366 				if (err instanceof EvalError) {					
       
   367 				}
       
   368 			}				
       
   369 		}
       
   370 		if( !isBoolean && isPath && localValue.length > 0 && localValue.charAt(localValue.length-1) != '/' ) {
       
   371 			localValue = localValue + '/';
       
   372 		}
       
   373 		return localValue;
       
   374 	}
       
   375 
       
   376 };